diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index e5c180954..864d9c52f 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -488,16 +488,17 @@ RsTurtleGenericTunnelItem *ftServer::deserialiseItem(void *data,uint32_t size) c } } -void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) +void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) { - mFtController->addFileSource(hash,virtual_peer_id) ; + if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) + mFtController->addFileSource(hash,virtual_peer_id) ; } void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) { mFtController->removeFileSource(hash,virtual_peer_id) ; } -bool ftServer::handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) +bool ftServer::handleTunnelRequest(const std::string& hash,const std::string& peer_id) { FileInfo info ; bool res = FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info); @@ -522,9 +523,6 @@ bool ftServer::handleTunnelRequest(const std::string& hash,const std::string& pe // res = res && (RS_FILE_HINTS_NETWORK_WIDE & rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups)) ; - if(res) - description_info_string = info.fname ; - return res ; } diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index d0f1ec553..32a881b27 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -114,11 +114,11 @@ class ftServer: public RsFiles, public ftDataSend, public RsTurtleClientService, // Implements RsTurtleClientService // - virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) ; + virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ; virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; virtual RsTurtleGenericTunnelItem *deserialiseItem(void *data,uint32_t size) const ; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; + void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; /***************************************************************/ diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index 165df106a..9f7538a12 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -246,10 +246,27 @@ void p3ChatService::sendStatusString( const std::string& id , const std::string& std::cerr << "sending chat status packet:" << std::endl ; cs->print(std::cerr) ; #endif - sendItem(cs); + sendPrivateChatItem(cs); } } +void p3ChatService::sendPrivateChatItem(RsChatItem *item) +{ + bool found = false ; + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if(_distant_chat_peers.find(item->PeerId()) != _distant_chat_peers.end()) + found = true ; + } + + if(found) + sendTurtleData(item) ; + else + sendItem(item) ; +} + void p3ChatService::checkSizeAndSendMessage_deprecated(RsChatMsgItem *msg) { // We check the message item, and possibly split it into multiple messages, if the message is too big. @@ -273,9 +290,9 @@ void p3ChatService::checkSizeAndSendMessage_deprecated(RsChatMsgItem *msg) // Indicate that the message is to be continued. // item->chatFlags |= RS_CHAT_FLAG_PARTIAL_MESSAGE ; - sendItem(item) ; + sendPrivateChatItem(item) ; } - sendItem(msg) ; + sendPrivateChatItem(msg) ; } // This function should be used for all types of chat messages. But this requires a non backward compatible change in // chat protocol. To be done for version 0.6 @@ -508,7 +525,7 @@ bool p3ChatService::sendPrivateChat(const std::string &id, const std::wstrin #endif RsChatStatusItem *cs = makeOwnCustomStateStringItem() ; cs->PeerId(id) ; - sendItem(cs) ; + sendPrivateChatItem(cs) ; } return true; @@ -677,7 +694,7 @@ void p3ChatService::handleIncomingItem(RsItem *item) case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated: handleRecvChatLobbyList (dynamic_cast(item)) ; break ; default: - std::cerr << "Unhandled item subtype " << item->PacketSubType() << " in p3ChatService: " << std::endl; + std::cerr << "Unhandled item subtype " << (int)item->PacketSubType() << " in p3ChatService: " << std::endl; } delete item ; } @@ -1511,17 +1528,19 @@ void p3ChatService::getOwnAvatarJpegData(unsigned char *& data,int& size) std::string p3ChatService::getCustomStateString(const std::string& peer_id) { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _state_strings.find(peer_id) ; - - // has it. Return it strait away. - // - if(it!=_state_strings.end()) { - it->second._peer_is_new = false ; - return it->second._custom_status_string ; + // should be a Mutex here. + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it = _state_strings.find(peer_id) ; + + // has it. Return it strait away. + // + if(it!=_state_strings.end()) + { + it->second._peer_is_new = false ; + return it->second._custom_status_string ; + } } sendCustomStateRequest(peer_id); @@ -1530,33 +1549,35 @@ std::string p3ChatService::getCustomStateString(const std::string& peer_id) void p3ChatService::getAvatarJpegData(const std::string& peer_id,unsigned char *& data,int& size) { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it = _avatars.find(peer_id) ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ; -#endif - // has avatar. Return it straight away. - // - if(it!=_avatars.end()) { - uint32_t s=0 ; - it->second->toUnsignedChar(data,s) ; - size = s ; - it->second->_peer_is_new = false ; -#ifdef CHAT_DEBUG - std::cerr << "Already has avatar. Returning it" << std::endl ; -#endif - return ; - } else { -#ifdef CHAT_DEBUG - std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ; -#endif - } + // should be a Mutex here. + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - sendAvatarRequest(peer_id); + std::map::const_iterator it = _avatars.find(peer_id) ; + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ; +#endif + // has avatar. Return it straight away. + // + if(it!=_avatars.end()) + { + uint32_t s=0 ; + it->second->toUnsignedChar(data,s) ; + size = s ; + it->second->_peer_is_new = false ; +#ifdef CHAT_DEBUG + std::cerr << "Already has avatar. Returning it" << std::endl ; +#endif + return ; + } else { +#ifdef CHAT_DEBUG + std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ; +#endif + } + } + + sendAvatarRequest(peer_id); } void p3ChatService::sendAvatarRequest(const std::string& peer_id) @@ -1575,7 +1596,7 @@ void p3ChatService::sendAvatarRequest(const std::string& peer_id) std::cerr << std::endl; #endif - sendItem(ci); + sendPrivateChatItem(ci); } void p3ChatService::sendCustomStateRequest(const std::string& peer_id){ @@ -1591,7 +1612,7 @@ void p3ChatService::sendCustomStateRequest(const std::string& peer_id){ std::cerr << std::endl; #endif - sendItem(cs); + sendPrivateChatItem(cs); } RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem() @@ -1633,7 +1654,7 @@ void p3ChatService::sendAvatarJpegData(const std::string& peer_id) std::cerr << std::endl; #endif - sendItem(ci) ; + sendPrivateChatItem(ci) ; } else { #ifdef CHAT_DEBUG @@ -1651,7 +1672,7 @@ std::cerr << "p3chatservice: sending requested status string for peer " << peer_ RsChatStatusItem *cs = makeOwnCustomStateStringItem(); cs->PeerId(peer_id); - sendItem(cs); + sendPrivateChatItem(cs); } bool p3ChatService::loadList(std::list& load) @@ -2777,7 +2798,7 @@ void p3ChatService::cleanLobbyCaches() sendConnectionChallenge(*it) ; } -bool p3ChatService::handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) +bool p3ChatService::handleTunnelRequest(const std::string& hash,const std::string& peer_id) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ @@ -2788,15 +2809,20 @@ bool p3ChatService::handleTunnelRequest(const std::string& hash,const std::strin if(it == _distant_chat_invites.end()) return false ; - std::cerr << "Responding ok." << std::endl; return true ; } -void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) +void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) { + std::cerr << "p3ChatService:: adding new virtual peer " << virtual_peer_id << " for hash " << hash << std::endl; + time_t now = time(NULL) ; + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + std::cerr << " Side is in direction to server." << std::endl; + std::map::iterator it = _distant_chat_peers.find(hash) ; if(it == _distant_chat_peers.end()) @@ -2805,12 +2831,36 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua return ; } - time_t now = time(NULL) ; it->second.last_contact = now ; it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ; + it->second.virtual_peer_id = virtual_peer_id ; std::cerr << "(II) Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl; } + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::cerr << " Side is in direction to client." << std::endl; + std::cerr << " Initing encryption parameters from existing distant chat invites." << std::endl; + + std::map::iterator it = _distant_chat_invites.find(hash) ; + + if(it == _distant_chat_invites.end()) + { + std::cerr << "(EE) Cannot find distant chat invite for hash " << hash << ": no chat invite found for that hash." << std::endl; + return ; + } + DistantChatPeerInfo info ; + info.last_contact = now ; + info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ; + info.virtual_peer_id = virtual_peer_id ; + memcpy(info.aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ; + + _distant_chat_peers[hash] = info ; + } + rsicontrol->getNotify().notifyChatStatus(hash,"tunnel is up again!",true) ; rsicontrol->getNotify().notifyPeerStatusChanged(hash,RS_STATUS_ONLINE) ; @@ -2865,7 +2915,7 @@ void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const st return ; } it->second.last_contact = time(NULL) ; - memcpy(aes_key,it->second.aes_key,8) ; + memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ; } // Call the AES crypto module @@ -2905,8 +2955,10 @@ void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const st handleIncomingItem(citem) ; // Treats the item, and deletes it } -void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& hash) +void p3ChatService::sendTurtleData(RsChatItem *item) { + std::cerr << "p3ChatService::sendTurtleData(): try sending item " << (void*)item << " to tunnel " << item->PeerId() << std::endl; + uint32_t rssize = item->serial_size(); uint8_t *buff = new uint8_t[rssize] ; @@ -2922,7 +2974,7 @@ void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& hash) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _distant_chat_peers.find(hash) ; + std::map::iterator it = _distant_chat_peers.find(item->PeerId()) ; if(it == _distant_chat_peers.end()) { @@ -2934,10 +2986,12 @@ void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& hash) virtual_peer_id = it->second.virtual_peer_id ; memcpy(aes_key,it->second.aes_key,8) ; } + std::cerr << "p3ChatService::sendTurtleData(): tunnel found. Encrypting data." << std::endl; + // Now encrypt this data using AES. // - uint32_t encrypted_size ; uint8_t *encrypted_data = new uint8_t[RsAES::get_buffer_size(rssize)]; + uint32_t encrypted_size = RsAES::get_buffer_size(rssize); uint64_t IV = RSRandom::random_u64() ; // make a random 8 bytes IV @@ -2963,6 +3017,8 @@ void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& hash) delete[] encrypted_data ; delete item ; + std::cerr << "p3ChatService::sendTurtleData(): Sending through virtual peer: " << virtual_peer_id << std::endl; + mTurtle->sendTurtleData(virtual_peer_id,gitem) ; } diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index 550a546c2..2a5fe2dab 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -344,15 +344,16 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi // Overloaded from RsTurtleClientService - virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) ; + virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ; virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; + void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; // Utility functions void cleanDistantChatInvites() ; - void sendTurtleData(RsChatItem *,const std::string& virtual_peer_id) ; + void sendTurtleData(RsChatItem *) ; + void sendPrivateChatItem(RsChatItem *) ; p3turtle *mTurtle ; }; diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index fbf1e5f15..0604db3a7 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -578,7 +578,7 @@ void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector::iterator itHash = _outgoing_file_hashes.find(it->second.hash); + std::map::iterator itHash = _outgoing_file_hashes.find(it->second.hash); if(itHash != _outgoing_file_hashes.end()) _outgoing_file_hashes.erase(itHash) ; } @@ -1094,7 +1094,7 @@ bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,std::string& vpid,s if(it2 == _local_tunnels.end()) { #ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnelId() << std::endl ; + std::cerr << "p3turtle: unknown tunnel id " << (void*)item->tunnelId() << std::endl ; #endif return false; } @@ -1113,15 +1113,39 @@ bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,std::string& vpid,s vpid = tunnel.vpid ; hash = tunnel.hash ; - std::map::const_iterator it = _incoming_file_hashes.find(hash) ; + // Now sort out the case of client vs. server side items. + // + std::string ownid = mLinkMgr->getOwnId() ; - if(it == _incoming_file_hashes.end()) + if(tunnel.local_src == ownid) { - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl; - return false; - } + std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - service = it->second.service ; + if(it == _incoming_file_hashes.end()) + { + std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl; + return false; + } + + service = it->second.service ; + } + else if(tunnel.local_dst == ownid) + { + std::map::const_iterator it = _outgoing_file_hashes.find(hash) ; + + if(it == _outgoing_file_hashes.end()) + { + std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl; + return false; + } + + service = it->second; + } + else + { + std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << ". Tunnel is not a end-point or a starting tunnel!! This is a serious consistency error." << std::endl; + return false ; + } return true ; } @@ -1391,13 +1415,14 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item) bool found = false ; std::string info ; + RsTurtleClientService *service = NULL ; if(item->PeerId() != mLinkMgr->getOwnId()) { #ifdef P3TURTLE_DEBUG std::cerr << " Request not from us. Performing local search" << std::endl ; #endif - found = performLocalHashSearch(item->file_hash,item->PeerId(),info) ; + found = performLocalHashSearch(item->file_hash,item->PeerId(),service) ; } { @@ -1435,9 +1460,15 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item) // Store some info string about the tunnel. // - _outgoing_file_hashes[item->file_hash] = info ; + _outgoing_file_hashes[item->file_hash] = service ; + + // Notify the client service that there's a new virtual peer id available as a client. + // + service->addVirtualPeer(item->file_hash,_local_tunnels[res_item->tunnel_id].vpid,RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; // We return straight, because when something is found, there's no need to digg a tunnel further. + // + return ; } #ifdef P3TURTLE_DEBUG @@ -1646,7 +1677,7 @@ void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item) // so we deported this code here. // if(new_tunnel && service != NULL) - service->addVirtualPeer(new_hash,new_vpid) ; + service->addVirtualPeer(new_hash,new_vpid,RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; } // -----------------------------------------------------------------------------------// @@ -1857,14 +1888,17 @@ void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item) /// Warning: this function should never be called while the turtle mutex is locked. /// Otherwize this is a possible source of cross-lock with the File mutex. // -bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const std::string& peer_id,std::string& description_string) +bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const std::string& peer_id,RsTurtleClientService *& service) { if(_registered_services.empty()) std::cerr << "Turtle router has no services registered. Tunnel requests cannot be handled." << std::endl; for(std::list::const_iterator it(_registered_services.begin());it!=_registered_services.end();++it) - if( (*it)->handleTunnelRequest(hash,peer_id,description_string)) + if( (*it)->handleTunnelRequest(hash,peer_id)) + { + service = *it ; return true ; + } return false ; } diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h index 8dbcffbeb..aaa3f6d96 100644 --- a/libretroshare/src/turtle/p3turtle.h +++ b/libretroshare/src/turtle/p3turtle.h @@ -369,7 +369,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config void returnSearchResult(RsTurtleSearchResultItem *item) ; /// Returns true if the file with given hash is hosted locally, and accessible in anonymous mode the supplied peer. - virtual bool performLocalHashSearch(const TurtleFileHash& hash,const std::string& client_peer_id,std::string& info) ; + virtual bool performLocalHashSearch(const TurtleFileHash& hash,const std::string& client_peer_id,RsTurtleClientService *& service); //--------------------------- Local variables --------------------------------// @@ -389,7 +389,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config std::map _incoming_file_hashes ; /// stores file info for each file we provide. - std::map _outgoing_file_hashes ; + std::map _outgoing_file_hashes ; /// local tunnels, stored by ids (Either transiting or ending). std::map _local_tunnels ; diff --git a/libretroshare/src/turtle/turtleclientservice.h b/libretroshare/src/turtle/turtleclientservice.h index 37a7f71df..564324f06 100644 --- a/libretroshare/src/turtle/turtleclientservice.h +++ b/libretroshare/src/turtle/turtleclientservice.h @@ -45,7 +45,7 @@ class RsTurtleClientService // The output info_string is used by the turtle router to display info about tunnels it manages. It is // not passed to the tunnel. - virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) { return false ; } + virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) { return false ; } // This method is called by the turtle router to send data that comes out of a turtle tunnel. // The turtle router stays responsible for the memory management of data. Most of the time the @@ -78,7 +78,7 @@ class RsTurtleClientService // These methods are called by the turtle router to add/remove virtual peers when tunnels are created/deleted // - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ; + virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) = 0 ; virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ; };