added proper tunnel closing mechanism with notification of the talking peer, and popups to inform the chat participants

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6430 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2013-06-13 21:12:07 +00:00
parent 7ba8be0a56
commit ff544da72e
5 changed files with 96 additions and 30 deletions

View File

@ -146,10 +146,11 @@ 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_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_ERROR_NO_ERROR 0x0000
#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001

View File

@ -35,16 +35,17 @@
/**************************************************************************/
/* chat Flags */
const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001;
const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002;
const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004;
const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008;
const uint32_t RS_CHAT_FLAG_CUSTOM_STATE = 0x0010; // used for transmitting peer status string
const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020;
const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040;
const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080;
const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE = 0x0100;
const uint32_t RS_CHAT_FLAG_LOBBY = 0x0200;
const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001;
const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002;
const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004;
const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008;
const uint32_t RS_CHAT_FLAG_CUSTOM_STATE = 0x0010; // used for transmitting peer status string
const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020;
const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040;
const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080;
const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE = 0x0100;
const uint32_t RS_CHAT_FLAG_LOBBY = 0x0200;
const uint32_t RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400;
const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001;

View File

@ -1196,7 +1196,12 @@ void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
sendCustomStateRequest(cs->PeerId()) ;
}
else if(cs->flags & RS_CHAT_FLAG_PRIVATE)
{
rsicontrol->getNotify().notifyChatStatus(cs->PeerId(),cs->status_string,true) ;
if(cs->flags & RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION)
markDistantChatAsClosed(cs->PeerId()) ;
}
else if(cs->flags & RS_CHAT_FLAG_PUBLIC)
rsicontrol->getNotify().notifyChatStatus(cs->PeerId(),cs->status_string,false) ;
}
@ -3379,22 +3384,41 @@ bool p3ChatService::closeDistantChatConnexion(const std::string& hash)
// - 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 if a message arrives.
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end()) // server side. Nothing to do.
bool is_client = false ;
{
std::cerr << "Cannot close chat associated to hash " << hash << ": not found." << std::endl;
return false ;
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,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;
return false ;
}
if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
is_client = true ;
}
// We can't do just that. We should:
// - mark the peer as closing, but not closed. If the tunnel gets deleted because of no traffic, then stop monitor
// it. That can be done in removeVirtualPeer
//
if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
if(is_client)
{
// send a status item saying that we're closing the connection
RsChatStatusItem *cs = new RsChatStatusItem ;
cs->status_string = "" ;
cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION;
cs->PeerId(hash);
sendTurtleData(cs) ; // that needs to be done off-mutex!
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,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;
return false ;
}
// Client side: Stop tunnels
//
std::cerr << "This is client side. Stopping tunnel manageement for hash " << hash << std::endl;
@ -3407,6 +3431,20 @@ bool p3ChatService::closeDistantChatConnexion(const std::string& hash)
return true ;
}
void p3ChatService::markDistantChatAsClosed(const std::string& hash)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end()) // server side. Nothing to do.
{
std::cerr << "Cannot mask distant chat as closed for hash " << hash << ": not found." << std::endl;
return ;
}
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
}

View File

@ -351,6 +351,7 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
void markDistantChatAsClosed(const TurtleFileHash& hash) ;
// Utility functions

View File

@ -21,6 +21,8 @@
#include <QTimer>
#include <QCloseEvent>
#include <QMessageBox>
#include "RsAutoUpdatePage.h"
#include "PopupDistantChatDialog.h"
@ -78,17 +80,24 @@ void PopupDistantChatDialog::updateDisplay()
_status_label->setPixmap(QPixmap(IMAGE_GRY_LED)) ;
_status_label->setToolTip(QObject::tr("Hash error")) ;
break ;
case RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED: std::cerr << "Chat remotely closed. " << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_RED_LED)) ;
_status_label->setToolTip(QObject::tr("Distant peer has closed the chat")) ;
QMessageBox::warning(NULL,tr("Distant chat terminated"),tr("The person you're talking to has deleted the secured chat tunnel. You may remove the chat window now.")) ;
_update_timer->stop() ;
break ;
case RS_DISTANT_CHAT_STATUS_TUNNEL_DN: std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_RED_LED)) ;
_status_label->setToolTip(QObject::tr("Tunnel is broken")) ;
_status_label->setToolTip(QObject::tr("Tunnel is pending...")) ;
break ;
case RS_DISTANT_CHAT_STATUS_TUNNEL_OK: std::cerr << "Tunnel is ok. " << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_YEL_LED)) ;
_status_label->setToolTip(QObject::tr("Tunnel established")) ;
_status_label->setToolTip(QObject::tr("Secured tunnel established!")) ;
break ;
case RS_DISTANT_CHAT_STATUS_CAN_TALK: std::cerr << "Tunnel is ok and works. You can talk!" << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_GRN_LED)) ;
_status_label->setToolTip(QObject::tr("Tunnel is working")) ;
_status_label->setToolTip(QObject::tr("Secured tunnel is working")) ;
break ;
}
}
@ -96,7 +105,23 @@ void PopupDistantChatDialog::updateDisplay()
void PopupDistantChatDialog::closeEvent(QCloseEvent *e)
{
std::cerr << "Closing window => closing distant chat for hash " << _hash << std::endl;
rsMsgs->closeDistantChatConnexion(_hash) ;
uint32_t status= RS_DISTANT_CHAT_STATUS_UNKNOWN;
std::string pgp_id ;
rsMsgs->getDistantChatStatus(_hash,status,pgp_id) ;
if(status != RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED)
{
QString msg = tr("Closing this window will end the conversation, notify the peer and remove the encrypted tunnel.") ;
if(QMessageBox::Ok == QMessageBox::critical(NULL,tr("Kill the tunnel?"),msg, QMessageBox::Ok | QMessageBox::Cancel))
rsMsgs->closeDistantChatConnexion(_hash) ;
else
{
e->ignore() ;
return ;
}
}
e->accept() ;