Improve async distant chat, fix chat msg receiving

DistantChatService::initiateDistantChatConnexion(...) made notification
  message optional (enabled by default)
p3ChatService removed duplicion avoidance as it is not necessary
p3ChatService::sendStatusString(...) send status only if peer is online
protect p3ChatService::mDistantGxsMap with mutex as operation on it may
  be done by different threads
p3ChatService::receiveGxsMai(...) set chat message item peer id with
  distant tunnel id, so it is recognized as a distant message later
made p3GxsTunnelService::makeGxsTunnelId(...) static as it need no
  access to this, now it can be used easier by other components
rename RsGxsMailItem::recipientsHint to recipientHint as for now only
  one recipient is possible (TODO: update documentation too)
GxsMailsClient::receiveGxsMail(...) changed paramethers for better
  abstracion, now destination id is passed too because it is usually a
  very useful information
ChatWidget some adaptation to async chat, a couple of method have been
  deprecated too
PopupDistantChatDialog::updateDisplay(...) adapt message shown to the
  user to the new async chat paradigm (TODO: need review)
This commit is contained in:
Gioacchino Mazzurco 2017-03-01 23:07:53 +01:00
parent 0f1106fd8f
commit 953b70fbe4
14 changed files with 212 additions and 212 deletions

View File

@ -243,7 +243,9 @@ void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid)
mDistantChatContacts.erase(it) ; mDistantChatContacts.erase(it) ;
} }
bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, DistantChatPeerId& dcpid, uint32_t& error_code) bool DistantChatService::initiateDistantChatConnexion(
const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId& dcpid, uint32_t& error_code, bool notify )
{ {
RsGxsTunnelId tunnel_id ; RsGxsTunnelId tunnel_id ;
@ -259,17 +261,19 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,
error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ; error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ;
// Make a self message to raise the chat window if(notify)
{
RsChatMsgItem *item = new RsChatMsgItem; // Make a self message to raise the chat window
item->message = "[Starting distant chat. Please wait for secure tunnel to be established]" ; RsChatMsgItem *item = new RsChatMsgItem;
item->chatFlags = RS_CHAT_FLAG_PRIVATE ; item->message = "[Starting distant chat. Please wait for secure tunnel";
item->sendTime = time(NULL) ; item->message += " to be established]";
item->PeerId(RsPeerId(tunnel_id)) ; item->chatFlags = RS_CHAT_FLAG_PRIVATE;
handleRecvChatMsgItem(item) ; item->sendTime = time(NULL);
item->PeerId(RsPeerId(tunnel_id));
delete item ; // item is replaced by NULL if partial, but this is not the case here. handleRecvChatMsgItem(item);
delete item ;
}
return true ; return true ;
} }

View File

@ -45,10 +45,15 @@ public:
bool processLoadListItem(const RsItem *item) ; bool processLoadListItem(const RsItem *item) ;
void addToSaveList(std::list<RsItem*>& list) const; void addToSaveList(std::list<RsItem*>& list) const;
// 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. * Creates the invite if the public key of the distant peer is available.
// * On success, stores the invite in the map above, so that we can respond
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ; * to tunnel requests. */
bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id,
const RsGxsId &from_gxs_id,
DistantChatPeerId& dcpid,
uint32_t &error_code,
bool notify = true );
bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ; bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ;
// Sets flags to only allow connexion from some people. // Sets flags to only allow connexion from some people.

View File

@ -59,8 +59,9 @@ p3ChatService::p3ChatService( p3ServiceControl *sc, p3IdService *pids,
DistributedChatService(getServiceInfo().mServiceType, sc, historyMgr,pids), DistributedChatService(getServiceInfo().mServiceType, sc, historyMgr,pids),
mChatMtx("p3ChatService"), mServiceCtrl(sc), mLinkMgr(lm), mChatMtx("p3ChatService"), mServiceCtrl(sc), mLinkMgr(lm),
mHistoryMgr(historyMgr), _own_avatar(NULL), mHistoryMgr(historyMgr), _own_avatar(NULL),
_serializer(new RsChatSerialiser()), mGxsTransport(gxsMailService), _serializer(new RsChatSerialiser()),
recentlyReceivedMutex("p3ChatService recently received mutex") mDGMutex("p3ChatService distant id - gxs id map mutex"),
mGxsTransport(gxsMailService)
{ {
addSerialType(_serializer); addSerialType(_serializer);
mGxsTransport.registerGxsMailsClient( GxsMailSubServices::P3_CHAT_SERVICE, mGxsTransport.registerGxsMailsClient( GxsMailSubServices::P3_CHAT_SERVICE,
@ -76,8 +77,6 @@ int p3ChatService::tick()
DistributedChatService::flush(); DistributedChatService::flush();
cleanListOfReceivedMessageHashes();
return 0; return 0;
} }
@ -203,37 +202,38 @@ void p3ChatService::sendGroupChatStatusString(const std::string& status_string)
} }
} }
void p3ChatService::sendStatusString(const ChatId& id , const std::string& status_string) void p3ChatService::sendStatusString( const ChatId& id,
const std::string& status_string )
{ {
if(id.isLobbyId()) if(id.isLobbyId()) sendLobbyStatusString(id.toLobbyId(),status_string);
sendLobbyStatusString(id.toLobbyId(),status_string) ; else if(id.isBroadcast()) sendGroupChatStatusString(status_string);
else if(id.isBroadcast()) else if(id.isPeerId() || id.isDistantChatId())
sendGroupChatStatusString(status_string); {
else if(id.isPeerId() || id.isDistantChatId()) RsPeerId vpid;
{ if(id.isDistantChatId()) vpid = RsPeerId(id.toDistantChatId());
RsChatStatusItem *cs = new RsChatStatusItem ; else vpid = id.toPeerId();
cs->status_string = status_string ; if(isOnline(vpid))
cs->flags = RS_CHAT_FLAG_PRIVATE ; {
RsPeerId vpid; RsChatStatusItem *cs = new RsChatStatusItem;
if(id.isDistantChatId())
vpid = RsPeerId(id.toDistantChatId()); cs->status_string = status_string;
else cs->flags = RS_CHAT_FLAG_PRIVATE;
vpid = id.toPeerId(); cs->PeerId(vpid);
cs->PeerId(vpid);
#ifdef CHAT_DEBUG #ifdef CHAT_DEBUG
std::cerr << "sending chat status packet:" << std::endl ; std::cerr << "sending chat status packet:" << std::endl;
cs->print(std::cerr) ; cs->print(std::cerr);
#endif #endif
sendChatItem(cs); sendChatItem(cs);
} }
else }
{ else
std::cerr << "p3ChatService::sendStatusString() Error: chat id of this type is not handled, is it empty?" << std::endl; {
return; std::cerr << "p3ChatService::sendStatusString() Error: chat id of this "
} << "type is not handled, is it empty?" << std::endl;
return;
}
} }
void p3ChatService::clearChatLobby(const ChatId& id) void p3ChatService::clearChatLobby(const ChatId& id)
@ -339,7 +339,8 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
if(destination.isDistantChatId()) if(destination.isDistantChatId())
{ {
DEPMap::const_iterator it = RS_STACK_MUTEX(mDGMutex);
DIDEMap::const_iterator it =
mDistantGxsMap.find(destination.toDistantChatId()); mDistantGxsMap.find(destination.toDistantChatId());
if(it != mDistantGxsMap.end()) if(it != mDistantGxsMap.end())
{ {
@ -687,31 +688,50 @@ bool p3ChatService::checkForMessageSecurity(RsChatMsgItem *ci)
return true ; return true ;
} }
bool p3ChatService::initiateDistantChatConnexion( bool p3ChatService::initiateDistantChatConnexion( const RsGxsId& to_gxs_id,
const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId& pid, uint32_t& error_code ) DistantChatPeerId& pid,
uint32_t& error_code,
bool notify )
{ {
if(DistantChatService::initiateDistantChatConnexion( to_gxs_id, if(DistantChatService::initiateDistantChatConnexion( to_gxs_id,
from_gxs_id, pid, from_gxs_id, pid,
error_code )) error_code, notify ))
{ {
RS_STACK_MUTEX(mDGMutex);
DistantEndpoints ep; ep.from = from_gxs_id; ep.to = to_gxs_id; DistantEndpoints ep; ep.from = from_gxs_id; ep.to = to_gxs_id;
mDistantGxsMap.insert(DEPMap::value_type(pid, ep)); mDistantGxsMap.insert(DIDEMap::value_type(pid, ep));
return true; return true;
} }
return false; return false;
} }
bool p3ChatService::receiveGxsMail(const RsGxsMailItem&, const uint8_t* data, uint32_t dataSize) bool p3ChatService::receiveGxsMail( const RsGxsId& authorId,
const RsGxsId& recipientId,
const uint8_t* data, uint32_t dataSize )
{ {
RsChatMsgItem* item = new RsChatMsgItem( const_cast<uint8_t*>(data), DistantChatPeerId pid;
dataSize ); uint32_t error_code;
handleRecvChatMsgItem(item); if(initiateDistantChatConnexion(
delete item; authorId, recipientId, pid, error_code, false ))
return true; {
RsChatMsgItem* item = new RsChatMsgItem( const_cast<uint8_t*>(data),
dataSize );
RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId));
item->PeerId(rd);
handleRecvChatMsgItem(item);
delete item;
return true;
}
std::cerr << "p3ChatService::receiveGxsMail(...) (EE) failed initiating"
<< " distant chat connection error: "<< error_code
<< std::endl;
return false;
} }
bool p3ChatService::notifySendMailStatus(const RsGxsMailItem& originalMessage, GxsMailStatus status) bool p3ChatService::notifySendMailStatus( const RsGxsMailItem& originalMessage,
GxsMailStatus status )
{ {
if ( status != GxsMailStatus::RECEIPT_RECEIVED ) return true; if ( status != GxsMailStatus::RECEIPT_RECEIVED ) return true;
@ -740,29 +760,6 @@ bool p3ChatService::notifySendMailStatus(const RsGxsMailItem& originalMessage, G
bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci) bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci)
{ {
time_t now = time(NULL);
{ // Check for duplicates
uint32_t sz = ci->serial_size();
std::vector<uint8_t> srz; srz.resize(sz);
ci->serialise(&srz[0], sz);
Sha1CheckSum hash = RsDirUtil::sha1sum(&srz[0], sz);
{
RS_STACK_MUTEX(recentlyReceivedMutex);
if( mRecentlyReceivedMessageHashes.find(hash) !=
mRecentlyReceivedMessageHashes.end() )
{
std::cerr << "p3ChatService::handleRecvChatMsgItem(...) (II) "
<< "receiving distant message of hash " << hash
<< " more than once. Probably it has arrived before "
<< "by other means." << std::endl;
delete ci; ci=NULL;
return true;
}
mRecentlyReceivedMessageHashes[hash] = now;
}
}
std::string name; std::string name;
uint32_t popupChatFlag = RS_POPUP_CHAT; uint32_t popupChatFlag = RS_POPUP_CHAT;
@ -840,7 +837,7 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci)
} }
} }
ci->recvTime = now; ci->recvTime = time(NULL);
ChatMessage cm; ChatMessage cm;
initChatMessage(ci, cm); initChatMessage(ci, cm);
@ -1169,24 +1166,6 @@ RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem()
return ci ; return ci ;
} }
void p3ChatService::cleanListOfReceivedMessageHashes()
{
RS_STACK_MUTEX(recentlyReceivedMutex);
time_t now = time(NULL);
for( auto it = mRecentlyReceivedMessageHashes.begin();
it != mRecentlyReceivedMessageHashes.end(); )
if( now > RECENTLY_RECEIVED_INTERVAL + it->second )
{
std::cerr << "p3MsgService(): cleanListOfReceivedMessageHashes("
<< "). Removing old hash " << it->first << ", aged "
<< now - it->second << " secs ago." << std::endl;
it = mRecentlyReceivedMessageHashes.erase(it);
}
else ++it;
}
RsChatAvatarItem *p3ChatService::makeOwnAvatarItem() RsChatAvatarItem *p3ChatService::makeOwnAvatarItem()
{ {
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/

View File

@ -95,11 +95,11 @@ struct p3ChatService :
*/ */
bool sendPrivateChat(const RsPeerId &id, const std::string &msg); bool sendPrivateChat(const RsPeerId &id, const std::string &msg);
/*! /**
* can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs) * can be used to send 'immediate' status msgs, these status updates are
* e.g currently used to update user when a peer 'is typing' during a chat * meant for immediate use by peer (not saved by rs) e.g currently used to
*/ * update user when a peer 'is typing' during a chat */
void sendStatusString(const ChatId& id,const std::string& status_str) ; void sendStatusString( const ChatId& id, const std::string& status_str );
/** /**
* @brief clearChatLobby: Signal chat was cleared by GUI. * @brief clearChatLobby: Signal chat was cleared by GUI.
@ -168,10 +168,12 @@ struct p3ChatService :
virtual bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id, virtual bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id,
const RsGxsId& from_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId &pid, DistantChatPeerId &pid,
uint32_t& error_code ); uint32_t& error_code,
bool notify = true );
/// @see GxsMailsClient::receiveGxsMail(...) /// @see GxsMailsClient::receiveGxsMail(...)
virtual bool receiveGxsMail( const RsGxsMailItem& /*originalMessage*/, virtual bool receiveGxsMail( const RsGxsId& authorId,
const RsGxsId& recipientId,
const uint8_t* data, uint32_t dataSize ); const uint8_t* data, uint32_t dataSize );
/// @see GxsMailsClient::notifySendMailStatus(...) /// @see GxsMailsClient::notifySendMailStatus(...)
@ -256,7 +258,7 @@ private:
AvatarInfo *_own_avatar ; AvatarInfo *_own_avatar ;
std::map<RsPeerId,AvatarInfo *> _avatars ; std::map<RsPeerId,AvatarInfo *> _avatars ;
std::map<RsPeerId,RsChatMsgItem *> _pendingPartialMessages ; std::map<RsPeerId,RsChatMsgItem *> _pendingPartialMessages;
std::string _custom_status_string ; std::string _custom_status_string ;
std::map<RsPeerId,StateStringInfo> _state_strings ; std::map<RsPeerId,StateStringInfo> _state_strings ;
@ -264,16 +266,11 @@ private:
RsChatSerialiser *_serializer; RsChatSerialiser *_serializer;
struct DistantEndpoints { RsGxsId from; RsGxsId to; }; struct DistantEndpoints { RsGxsId from; RsGxsId to; };
typedef std::map<DistantChatPeerId, DistantEndpoints> DEPMap; typedef std::map<DistantChatPeerId, DistantEndpoints> DIDEMap;
DEPMap mDistantGxsMap; DIDEMap mDistantGxsMap;
p3GxsMails& mGxsTransport; RsMutex mDGMutex;
/** As we have multiple backends duplicates are possible, keep track of p3GxsMails& mGxsTransport;
* recently received messages hashes for at least 2h to avoid them */
const static uint32_t RECENTLY_RECEIVED_INTERVAL = 2*3600;
std::map<Sha1CheckSum, uint32_t> mRecentlyReceivedMessageHashes;
RsMutex recentlyReceivedMutex;
void cleanListOfReceivedMessageHashes();
}; };
class p3ChatService::StateStringInfo class p3ChatService::StateStringInfo

View File

@ -1023,7 +1023,8 @@ void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item)
// Note: for some obscure reason, the typedef does not work here. Looks like a compiler error. So I use the primary type. // Note: for some obscure reason, the typedef does not work here. Looks like a compiler error. So I use the primary type.
GXSTunnelId p3GxsTunnelService::makeGxsTunnelId(const RsGxsId &own_id, const RsGxsId &distant_id) const // creates a unique ID from two GXS ids. /*static*/ GXSTunnelId p3GxsTunnelService::makeGxsTunnelId(
const RsGxsId &own_id, const RsGxsId &distant_id )
{ {
unsigned char mem[RsGxsId::SIZE_IN_BYTES * 2] ; unsigned char mem[RsGxsId::SIZE_IN_BYTES * 2] ;
@ -1240,18 +1241,20 @@ bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item)
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ;
if(it == _gxs_tunnel_contacts.end()) if(it == _gxs_tunnel_contacts.end())
{ {
#ifdef DEBUG_GXS_TUNNEL #ifdef DEBUG_GXS_TUNNEL
std::cerr << " Cannot find contact key info for tunnel id " << tunnel_id << ". Cannot send message!" << std::endl; std::cerr << " Cannot find contact key info for tunnel id "
<< tunnel_id << ". Cannot send message!" << std::endl;
#endif #endif
return false; return false;
} }
if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK) if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK)
{ {
std::cerr << "(EE) Cannot talk to tunnel id " << tunnel_id << ". Tunnel status is: " << it->second.status << std::endl; std::cerr << "(EE) Cannot talk to tunnel id " << tunnel_id
return false; << ". Tunnel status is: " << it->second.status << std::endl;
} return false;
}
it->second.total_sent += rssize ; // counts the size of clear data that is sent it->second.total_sent += rssize ; // counts the size of clear data that is sent

View File

@ -232,7 +232,6 @@ private:
bool locked_initDHSessionKey(DH *&dh); bool locked_initDHSessionKey(DH *&dh);
TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ; // ... and to a hash for p3turtle 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 // item handling
@ -256,5 +255,10 @@ private:
std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ; std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ;
void debug_dump(); void debug_dump();
public:
/// creates a unique tunnel ID from two GXS ids.
static RsGxsTunnelId makeGxsTunnelId( const RsGxsId &own_id,
const RsGxsId &distant_id );
}; };

View File

@ -131,9 +131,9 @@ struct RsGxsMailItem : RsGxsMailBaseItem
* mail is directed to the actual recipient as the "apparently" * mail is directed to the actual recipient as the "apparently"
* corresponding hint may be fruit of a "luky" salting of another id. * corresponding hint may be fruit of a "luky" salting of another id.
*/ */
RsGxsId recipientsHint; RsGxsId recipientHint;
void inline saltRecipientHint(const RsGxsId& salt) void inline saltRecipientHint(const RsGxsId& salt)
{ recipientsHint = recipientsHint | salt; } { recipientHint = recipientHint | salt; }
/** /**
* @brief maybeRecipient given an id and an hint check if they match * @brief maybeRecipient given an id and an hint check if they match
@ -141,7 +141,7 @@ struct RsGxsMailItem : RsGxsMailBaseItem
* @return true if the id may be recipient of the hint, false otherwise * @return true if the id may be recipient of the hint, false otherwise
*/ */
bool inline maybeRecipient(const RsGxsId& id) const bool inline maybeRecipient(const RsGxsId& id) const
{ return (~id|recipientsHint) == allRecipientsHint; } { return (~id|recipientHint) == allRecipientsHint; }
const static RsGxsId allRecipientsHint; const static RsGxsId allRecipientsHint;
@ -153,7 +153,7 @@ struct RsGxsMailItem : RsGxsMailBaseItem
{ {
return RsGxsMailBaseItem::size() + return RsGxsMailBaseItem::size() +
1 + // cryptoType 1 + // cryptoType
recipientsHint.serial_size() + recipientHint.serial_size() +
payload.size(); payload.size();
} }
bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const
@ -162,7 +162,7 @@ struct RsGxsMailItem : RsGxsMailBaseItem
ok = ok && RsGxsMailBaseItem::serialize(data, size, offset); ok = ok && RsGxsMailBaseItem::serialize(data, size, offset);
ok = ok && setRawUInt8( data, size, &offset, ok = ok && setRawUInt8( data, size, &offset,
static_cast<uint8_t>(cryptoType) ); static_cast<uint8_t>(cryptoType) );
ok = ok && recipientsHint.serialise(data, size, offset); ok = ok && recipientHint.serialise(data, size, offset);
uint32_t psz = payload.size(); uint32_t psz = payload.size();
ok = ok && memcpy(data+offset, &payload[0], psz); ok = ok && memcpy(data+offset, &payload[0], psz);
offset += psz; offset += psz;
@ -181,7 +181,7 @@ struct RsGxsMailItem : RsGxsMailBaseItem
uint8_t crType; uint8_t crType;
ok = ok && getRawUInt8(dataPtr, rssize, &roffset, &crType); ok = ok && getRawUInt8(dataPtr, rssize, &roffset, &crType);
cryptoType = static_cast<RsGxsMailEncryptionMode>(crType); cryptoType = static_cast<RsGxsMailEncryptionMode>(crType);
ok = ok && recipientsHint.deserialise(dataPtr, rssize, roffset); ok = ok && recipientHint.deserialise(dataPtr, rssize, roffset);
uint32_t psz = rssize - roffset; uint32_t psz = rssize - roffset;
ok = ok && (payload.resize(psz), memcpy(&payload[0], data+roffset, psz)); ok = ok && (payload.resize(psz), memcpy(&payload[0], data+roffset, psz));
ok = ok && (roffset += psz); ok = ok && (roffset += psz);
@ -193,7 +193,7 @@ struct RsGxsMailItem : RsGxsMailBaseItem
{ {
RsGxsMailBaseItem::clear(); RsGxsMailBaseItem::clear();
cryptoType = RsGxsMailEncryptionMode::UNDEFINED_ENCRYPTION; cryptoType = RsGxsMailEncryptionMode::UNDEFINED_ENCRYPTION;
recipientsHint.clear(); recipientHint.clear();
payload.clear(); payload.clear();
} }

View File

@ -262,7 +262,7 @@ void p3GxsMails::service_tick()
<< msg->meta.mMsgId << msg->meta.mMsgId
<< " with cryptoType: " << " with cryptoType: "
<< static_cast<uint32_t>(msg->cryptoType) << static_cast<uint32_t>(msg->cryptoType)
<< " recipientHint: " << msg->recipientsHint << " recipientHint: " << msg->recipientHint
<< " mailId: "<< msg->mailId << " mailId: "<< msg->mailId
<< " payload.size(): " << msg->payload.size() << " payload.size(): " << msg->payload.size()
<< std::endl; << std::endl;
@ -423,8 +423,10 @@ bool p3GxsMails::handleEcryptedMail(const RsGxsMailItem* mail)
getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri); getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri);
std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" std::cerr << "service: " << csri << " got CLEAR_TEXT mail!"
<< std::endl; << std::endl;
return dispatchDecryptedMail( mail, &mail->payload[0], /* As we cannot verify recipient without encryption, just pass the hint
mail->payload.size() ); * as recipient */
return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint,
&mail->payload[0], mail->payload.size() );
} }
case RsGxsMailEncryptionMode::RSA: case RsGxsMailEncryptionMode::RSA:
{ {
@ -432,14 +434,16 @@ bool p3GxsMails::handleEcryptedMail(const RsGxsMailItem* mail)
for( std::set<RsGxsId>::const_iterator it = decryptIds.begin(); for( std::set<RsGxsId>::const_iterator it = decryptIds.begin();
it != decryptIds.end(); ++it ) it != decryptIds.end(); ++it )
{ {
const RsGxsId& decryptId(*it);
uint8_t* decrypted_data = NULL; uint8_t* decrypted_data = NULL;
uint32_t decrypted_data_size = 0; uint32_t decrypted_data_size = 0;
uint32_t decryption_error; uint32_t decryption_error;
if( idService.decryptData( &mail->payload[0], if( idService.decryptData( &mail->payload[0],
mail->payload.size(), decrypted_data, mail->payload.size(), decrypted_data,
decrypted_data_size, *it, decrypted_data_size, decryptId,
decryption_error ) ) decryption_error ) )
ok = ok && dispatchDecryptedMail( mail, decrypted_data, ok = ok && dispatchDecryptedMail( mail->meta.mAuthorId,
decryptId, decrypted_data,
decrypted_data_size ); decrypted_data_size );
free(decrypted_data); free(decrypted_data);
} }
@ -452,7 +456,8 @@ bool p3GxsMails::handleEcryptedMail(const RsGxsMailItem* mail)
} }
} }
bool p3GxsMails::dispatchDecryptedMail( const RsGxsMailItem* received_msg, bool p3GxsMails::dispatchDecryptedMail( const RsGxsId& authorId,
const RsGxsId& decryptId,
const uint8_t* decrypted_data, const uint8_t* decrypted_data,
uint32_t decrypted_data_size ) uint32_t decrypted_data_size )
{ {
@ -486,16 +491,16 @@ bool p3GxsMails::dispatchDecryptedMail( const RsGxsMailItem* received_msg,
std::vector<RsNxsMsg*> rcct; rcct.push_back(receipt); std::vector<RsNxsMsg*> rcct; rcct.push_back(receipt);
RsGenExchange::notifyNewMessages(rcct); RsGenExchange::notifyNewMessages(rcct);
GxsMailsClient* reecipientService = NULL; GxsMailsClient* recipientService = NULL;
{ {
RS_STACK_MUTEX(servClientsMutex); RS_STACK_MUTEX(servClientsMutex);
reecipientService = servClients[rsrvc]; recipientService = servClients[rsrvc];
} }
if(reecipientService) if(recipientService)
return reecipientService->receiveGxsMail( *received_msg, return recipientService->receiveGxsMail( authorId, decryptId,
&decrypted_data[offset], &decrypted_data[offset],
decrypted_data_size-offset ); decrypted_data_size-offset );
else else
{ {
std::cerr << "p3GxsMails::dispatchReceivedMail(...) " std::cerr << "p3GxsMails::dispatchReceivedMail(...) "
@ -625,7 +630,7 @@ void p3GxsMails::processOutgoingRecord(OutgoingRecord& pr)
<< pr.recipient << pr.recipient
<< " with cryptoType: " << " with cryptoType: "
<< static_cast<uint>(pr.mailItem.cryptoType) << static_cast<uint>(pr.mailItem.cryptoType)
<< " recipientHint: " << pr.mailItem.recipientsHint << " recipientHint: " << pr.mailItem.recipientHint
<< " receiptId: " << pr.mailItem.mailId << " receiptId: " << pr.mailItem.mailId
<< " payload size: " << pr.mailItem.payload.size() << " payload size: " << pr.mailItem.payload.size()
<< std::endl; << std::endl;

View File

@ -34,12 +34,14 @@ struct GxsMailsClient
{ {
/** /**
* This will be called by p3GxsMails to dispatch mails to the subservice * This will be called by p3GxsMails to dispatch mails to the subservice
* @param originalMessage message as received from GXS backend (encrypted) * @param authorId message sender
* @param decryptId recipient id
* @param data buffer containing the decrypted data * @param data buffer containing the decrypted data
* @param dataSize size of the buffer * @param dataSize size of the buffer
* @return true if dispatching goes fine, false otherwise * @return true if dispatching goes fine, false otherwise
*/ */
virtual bool receiveGxsMail( const RsGxsMailItem& originalMessage, virtual bool receiveGxsMail( const RsGxsId& authorId,
const RsGxsId& recipientId,
const uint8_t* data, uint32_t dataSize ) = 0; const uint8_t* data, uint32_t dataSize ) = 0;
/** /**
@ -242,7 +244,8 @@ private:
bool handleEcryptedMail(const RsGxsMailItem* mail); bool handleEcryptedMail(const RsGxsMailItem* mail);
/// Dispatch the message to the recipient service /// Dispatch the message to the recipient service
bool dispatchDecryptedMail( const RsGxsMailItem* received_msg, bool dispatchDecryptedMail( const RsGxsId& authorId,
const RsGxsId& decryptId,
const uint8_t* decrypted_data, const uint8_t* decrypted_data,
uint32_t decrypted_data_size ); uint32_t decrypted_data_size );

View File

@ -1990,11 +1990,12 @@ uint32_t p3MsgService::getDistantMessagingPermissionFlags()
return mDistantMessagePermissions ; return mDistantMessagePermissions ;
} }
bool p3MsgService::receiveGxsMail( const RsGxsMailItem& originalMessage, bool p3MsgService::receiveGxsMail( const RsGxsId& authorId,
const RsGxsId& recipientId,
const uint8_t* data, uint32_t dataSize ) const uint8_t* data, uint32_t dataSize )
{ {
std::cout << "p3MsgService::receiveGxsMail(" << originalMessage.mailId std::cout << "p3MsgService::receiveGxsMail(" << authorId
<< ",, " << dataSize << ")" << std::endl; << ", " << recipientId << ", " << dataSize << ")" << std::endl;
Sha1CheckSum hash = RsDirUtil::sha1sum(data, dataSize); Sha1CheckSum hash = RsDirUtil::sha1sum(data, dataSize);
@ -2029,7 +2030,7 @@ bool p3MsgService::receiveGxsMail( const RsGxsMailItem& originalMessage,
msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL; msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL;
// hack to pass on GXS id. // hack to pass on GXS id.
msg_item->PeerId(RsPeerId(originalMessage.meta.mAuthorId)); msg_item->PeerId(RsPeerId(authorId));
handleIncomingItem(msg_item); handleIncomingItem(msg_item);
} }
else else

View File

@ -136,7 +136,8 @@ struct p3MsgService :
uint32_t getDistantMessagingPermissionFlags() ; uint32_t getDistantMessagingPermissionFlags() ;
/// @see GxsMailsClient::receiveGxsMail(...) /// @see GxsMailsClient::receiveGxsMail(...)
virtual bool receiveGxsMail( const RsGxsMailItem& originalMessage, virtual bool receiveGxsMail( const RsGxsId& authorId,
const RsGxsId& recipientId,
const uint8_t* data, uint32_t dataSize ); const uint8_t* data, uint32_t dataSize );
/// @see GxsMailsClient::notifySendMailStatus(...) /// @see GxsMailsClient::notifySendMailStatus(...)

View File

@ -70,7 +70,7 @@
*****/ *****/
ChatWidget::ChatWidget(QWidget *parent) : ChatWidget::ChatWidget(QWidget *parent) :
QWidget(parent), sendingBlocked(false), ui(new Ui::ChatWidget) QWidget(parent), ui(new Ui::ChatWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -413,18 +413,9 @@ ChatWidget::ChatType ChatWidget::chatType()
return CHATTYPE_UNKNOWN; return CHATTYPE_UNKNOWN;
} }
void ChatWidget::blockSending(QString msg) void ChatWidget::blockSending(QString msg) { ui->sendButton->setToolTip(msg); }
{
sendingBlocked = true;
ui->sendButton->setEnabled(false);
ui->sendButton->setToolTip(msg);
}
void ChatWidget::unblockSending() void ChatWidget::unblockSending() { updateLenOfChatTextEdit(); }
{
sendingBlocked = false;
updateLenOfChatTextEdit();
}
void ChatWidget::processSettings(bool load) void ChatWidget::processSettings(bool load)
{ {
@ -1096,8 +1087,6 @@ void ChatWidget::updateStatusTyping()
void ChatWidget::updateLenOfChatTextEdit() void ChatWidget::updateLenOfChatTextEdit()
{ {
if(sendingBlocked) return;
QTextEdit *chatWidget = ui->chatTextEdit; QTextEdit *chatWidget = ui->chatTextEdit;
QString text; QString text;
RsHtml::optimizeHtml(chatWidget, text); RsHtml::optimizeHtml(chatWidget, text);

View File

@ -36,6 +36,7 @@
#include <retroshare/rsmsgs.h> #include <retroshare/rsmsgs.h>
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
#include <util/rsdeprecate.h>
class QAction; class QAction;
class QTextEdit; class QTextEdit;
@ -78,9 +79,8 @@ public:
ChatId getChatId(); ChatId getChatId();
ChatType chatType(); ChatType chatType();
// allow/disallow sendng of messages RS_DEPRECATED void blockSending(QString msg);
void blockSending(QString msg); RS_DEPRECATED void unblockSending();
void unblockSending();
bool hasNewMessages() { return newMessages; } bool hasNewMessages() { return newMessages; }
bool isTyping() { return typing; } bool isTyping() { return typing; }
@ -216,8 +216,6 @@ private:
bool typing; bool typing;
int peerStatus; int peerStatus;
bool sendingBlocked;
time_t lastStatusSendTime; time_t lastStatusSendTime;
ChatStyle chatStyle; ChatStyle chatStyle;

View File

@ -104,41 +104,52 @@ void PopupDistantChatDialog::updateDisplay()
QString msg; QString msg;
switch(tinfo.status) switch(tinfo.status)
{ {
case RS_DISTANT_CHAT_STATUS_UNKNOWN: //std::cerr << "Unknown hash. Error!" << std::endl; case RS_DISTANT_CHAT_STATUS_UNKNOWN:
_status_label->setIcon(QIcon(IMAGE_GRY_LED)) ; //std::cerr << "Unknown hash. Error!" << std::endl;
msg = tr("Chat remotely closed. Please close this window."); _status_label->setIcon(QIcon(IMAGE_GRY_LED));
_status_label->setToolTip(msg) ; msg = tr("Remote status unknown.");
getChatWidget()->updateStatusString("%1", msg, true); _status_label->setToolTip(msg);
getChatWidget()->blockSending(tr("Can't send message, because there is no tunnel.")); getChatWidget()->updateStatusString("%1", msg, true);
setPeerStatus(RS_STATUS_OFFLINE) ; getChatWidget()->blockSending(tr( "Can't send message immediately, "
break ; "because there is no tunnel "
case RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED: std::cerr << "Chat remotely closed. " << std::endl; "available." ));
_status_label->setIcon(QIcon(IMAGE_RED_LED)) ; setPeerStatus(RS_STATUS_OFFLINE);
_status_label->setToolTip(QObject::tr("Distant peer has closed the chat")) ; break ;
case RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED:
getChatWidget()->updateStatusString("%1", tr("The person you're talking to has deleted the secured chat tunnel. You may remove the chat window now."), true); std::cerr << "Chat remotely closed. " << std::endl;
getChatWidget()->blockSending(tr("Can't send message, because the chat partner deleted the secure tunnel.")); _status_label->setIcon(QIcon(IMAGE_RED_LED));
setPeerStatus(RS_STATUS_OFFLINE) ; _status_label->setToolTip(
QObject::tr("Distant peer has closed the chat") );
break ; getChatWidget()->updateStatusString(
case RS_DISTANT_CHAT_STATUS_TUNNEL_DN: //std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl; "%1", tr( "The person you're talking to has deleted the"
_status_label->setIcon(QIcon(IMAGE_RED_LED)) ; "secured chat tunnel." ), true );
msg = QObject::tr("Tunnel is pending..."); getChatWidget()->blockSending(tr( "The chat partner deleted the secure"
_status_label->setToolTip(msg) ; " tunnel, messages will be delivered"
getChatWidget()->updateStatusString("%1", msg, true); " as soon as possible"));
getChatWidget()->blockSending(msg); setPeerStatus(RS_STATUS_OFFLINE) ;
setPeerStatus(RS_STATUS_OFFLINE) ; break ;
break ; case RS_DISTANT_CHAT_STATUS_TUNNEL_DN:
case RS_DISTANT_CHAT_STATUS_CAN_TALK: //std::cerr << "Tunnel is ok and data is transmitted." << std::endl; //std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl;
_status_label->setIcon(QIcon(IMAGE_GRN_LED)) ; _status_label->setIcon(QIcon(IMAGE_RED_LED));
msg = QObject::tr("Secured tunnel is working. You can talk!"); msg = QObject::tr( "Tunnel is pending... Messages will be delivered as"
_status_label->setToolTip(msg) ; " soon as possible" );
getChatWidget()->unblockSending(); _status_label->setToolTip(msg);
setPeerStatus(RS_STATUS_ONLINE) ; getChatWidget()->updateStatusString("%1", msg, true);
break ; getChatWidget()->blockSending(msg);
} setPeerStatus(RS_STATUS_OFFLINE);
break;
case RS_DISTANT_CHAT_STATUS_CAN_TALK:
//std::cerr << "Tunnel is ok and data is transmitted." << std::endl;
_status_label->setIcon(QIcon(IMAGE_GRN_LED));
msg = QObject::tr( "Secured tunnel is working."
"Messages are delivered immediately!" );
_status_label->setToolTip(msg);
getChatWidget()->unblockSending();
setPeerStatus(RS_STATUS_ONLINE);
break;
}
} }
void PopupDistantChatDialog::closeEvent(QCloseEvent *e) void PopupDistantChatDialog::closeEvent(QCloseEvent *e)