From 14890ef007a696d72caf2324068d0a44d1a8a9f0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 14 Jul 2013 13:59:38 +0000 Subject: [PATCH] added ACK system to make sure the secured tunnels for distant chat are actually working, before one starts using it. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6502 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/serialiser/rsmsgitems.h | 1 + libretroshare/src/services/p3chatservice.cc | 30 ++++++++++++++++++- libretroshare/src/services/p3chatservice.h | 5 ++++ .../src/gui/chat/PopupDistantChatDialog.cpp | 16 +++++----- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index 81735566e..5fed960c6 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -46,6 +46,7 @@ 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_CHAT_FLAG_ACK_DISTANT_CONNECTION = 0x0800; const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001; diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index a9409ab11..4790cd731 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -54,6 +54,7 @@ static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connect static const time_t CONNECTION_CHALLENGE_MAX_MSG_AGE = 30 ; // maximum age of a message to be used in a connection challenge static const int CONNECTION_CHALLENGE_MIN_DELAY = 15 ; // sends a connection at most every 15 seconds static const int LOBBY_CACHE_CLEANING_PERIOD = 10 ; // clean lobby caches every 10 secs (remove old messages) + static const time_t MAX_KEEP_MSG_RECORD = 1200 ; // keep msg record for 1200 secs max. static const time_t MAX_KEEP_INACTIVE_NICKNAME = 180 ; // keep inactive nicknames for 3 mn max. static const time_t MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE = 120 ; // send keep alive packet every 2 minutes. @@ -61,6 +62,7 @@ static const time_t MAX_KEEP_PUBLIC_LOBBY_RECORD = 60 ; // keep inactiv static const time_t MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ = 20 ; // don't ask for lobby list more than once every 30 secs. static const time_t DISTANT_CHAT_CLEANING_PERIOD = 60 ; // don't ask for lobby list more than once every 30 secs. +static const time_t DISTANT_CHAT_KEEP_ALIVE_PERIOD = 10 ; // sens keep alive distant chat packets every 10 secs. static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; // size of AES encryption key for distant chat. static const uint32_t DISTANT_CHAT_HASH_SIZE = 20 ; // This is sha1 size in bytes. @@ -106,6 +108,14 @@ int p3ChatService::tick() cleanDistantChatInvites() ; last_clean_time_dchat = now ; } + + // Flush items that could not be sent, probably because of a Mutex protected zone. + // + while(!pendingDistantChatItems.empty()) + { + sendTurtleData( pendingDistantChatItems.front() ) ; + pendingDistantChatItems.pop_front() ; + } return 0; } @@ -2988,8 +2998,26 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua it->second.last_hit_time = now ; } + // then we send an ACK packet to notify that the tunnel works. That's useful + // because it makes the peer at the other end of the tunnel know that all + // intermediate peer in the tunnel are able to transmit the data. + // However, it is not possible here to call sendTurtleData(), without dead-locking + // the turtle router, so we store the item is a list of items to be sent. + + RsChatStatusItem *cs = new RsChatStatusItem ; + + cs->status_string = "Tunnel is working. You can talk!" ; + cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_ACK_DISTANT_CONNECTION; + cs->PeerId(hash); + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + pendingDistantChatItems.push_back(cs) ; + } + + // Notify the GUI that the tunnel is up. + // rsicontrol->getNotify().notifyChatStatus(hash,"tunnel is up again!",true) ; - //rsicontrol->getNotify().notifyPeerStatusChanged(hash,RS_STATUS_ONLINE) ; } void p3ChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index ccd02068e..8fbd6e750 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -355,6 +355,11 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi // std::map _distant_chat_peers ; + // List of items to be sent asap. Used to store items that we cannot pass directly to + // sendTurtleData(), because of Mutex protection. + + std::list pendingDistantChatItems ; + // Overloaded from RsTurtleClientService virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ; diff --git a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp index 29b62c426..1e8fe5290 100644 --- a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp @@ -68,7 +68,7 @@ void PopupDistantChatDialog::updateDisplay() if(!isVisible()) return ; - std::cerr << "Checking tunnel..." ; + //std::cerr << "Checking tunnel..." ; // make sure about the tunnel status // @@ -78,7 +78,7 @@ void PopupDistantChatDialog::updateDisplay() switch(status) { - case RS_DISTANT_CHAT_STATUS_UNKNOWN: std::cerr << "Unknown hash. Error!" << std::endl; + case RS_DISTANT_CHAT_STATUS_UNKNOWN: //std::cerr << "Unknown hash. Error!" << std::endl; _status_label->setPixmap(QPixmap(IMAGE_GRY_LED)) ; _status_label->setToolTip(QObject::tr("Hash error")) ; setPeerStatus(RS_STATUS_OFFLINE) ; @@ -92,19 +92,19 @@ void PopupDistantChatDialog::updateDisplay() setPeerStatus(RS_STATUS_OFFLINE) ; break ; - case RS_DISTANT_CHAT_STATUS_TUNNEL_DN: std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl; + 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 pending...")) ; setPeerStatus(RS_STATUS_OFFLINE) ; break ; - case RS_DISTANT_CHAT_STATUS_TUNNEL_OK: std::cerr << "Tunnel is ok. " << std::endl; + 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("Secured tunnel established!")) ; + _status_label->setToolTip(QObject::tr("Secured tunnel established. Waiting for ACK...")) ; setPeerStatus(RS_STATUS_ONLINE) ; break ; - case RS_DISTANT_CHAT_STATUS_CAN_TALK: std::cerr << "Tunnel is ok and data is transmitted." << std::endl; + case RS_DISTANT_CHAT_STATUS_CAN_TALK: //std::cerr << "Tunnel is ok and data is transmitted." << std::endl; _status_label->setPixmap(QPixmap(IMAGE_GRN_LED)) ; - _status_label->setToolTip(QObject::tr("Secured tunnel is working")) ; + _status_label->setToolTip(QObject::tr("Secured tunnel is working. You can talk!")) ; setPeerStatus(RS_STATUS_ONLINE) ; break ; } @@ -112,7 +112,7 @@ void PopupDistantChatDialog::updateDisplay() void PopupDistantChatDialog::closeEvent(QCloseEvent *e) { - std::cerr << "Closing window => closing distant chat for hash " << _hash << std::endl; + //std::cerr << "Closing window => closing distant chat for hash " << _hash << std::endl; uint32_t status= RS_DISTANT_CHAT_STATUS_UNKNOWN; std::string pgp_id ;