mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-25 23:49:35 -05:00
added control for suspicious message activity in chat lobbies. Lobby items are not bounced if coming from a peer that sends more messages per seconds than a given limit. The limit is adaptive and depends on lobby count
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6751 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
11435dfd61
commit
8ffc0e05de
@ -23,6 +23,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "openssl/rand.h"
|
#include "openssl/rand.h"
|
||||||
#include "pgp/rscertificate.h"
|
#include "pgp/rscertificate.h"
|
||||||
@ -71,6 +72,8 @@ static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size
|
|||||||
// don't transfer correctly and can kill the system.
|
// don't transfer correctly and can kill the system.
|
||||||
// Images are 96x96, which makes approx. 27000 bytes uncompressed.
|
// Images are 96x96, which makes approx. 27000 bytes uncompressed.
|
||||||
static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ;
|
static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ;
|
||||||
|
static const uint32_t MAX_MESSAGES_PER_SECONDS_NUMBER = 5 ; // max number of messages from a given peer in a window for duration below
|
||||||
|
static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration window for max number of messages before messages get dropped.
|
||||||
|
|
||||||
p3ChatService::p3ChatService(p3LinkMgr *lm, p3HistoryMgr *historyMgr)
|
p3ChatService::p3ChatService(p3LinkMgr *lm, p3HistoryMgr *historyMgr)
|
||||||
:p3Service(RS_SERVICE_TYPE_CHAT), p3Config(CONFIG_TYPE_CHAT), mChatMtx("p3ChatService"), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
:p3Service(RS_SERVICE_TYPE_CHAT), p3Config(CONFIG_TYPE_CHAT), mChatMtx("p3ChatService"), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
||||||
@ -698,12 +701,71 @@ void p3ChatService::receiveChatQueue()
|
|||||||
while(NULL != (item=recvItem()))
|
while(NULL != (item=recvItem()))
|
||||||
handleIncomingItem(item) ;
|
handleIncomingItem(item) ;
|
||||||
}
|
}
|
||||||
|
class MsgCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MsgCounter() {}
|
||||||
|
|
||||||
|
void clean(time_t max_time)
|
||||||
|
{
|
||||||
|
while(!recv_times.empty() && recv_times.front() < max_time)
|
||||||
|
recv_times.pop_front() ;
|
||||||
|
}
|
||||||
|
std::list<time_t> recv_times ;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool p3ChatService::locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const std::string& peer_id,uint32_t lobby_count)
|
||||||
|
{
|
||||||
|
static std::map<std::string, std::list<time_t> > message_counts ;
|
||||||
|
|
||||||
|
std::ostringstream os ;
|
||||||
|
os << obj->lobby_id ;
|
||||||
|
|
||||||
|
std::string pid = peer_id + "_" + os.str() ;
|
||||||
|
|
||||||
|
VisibleChatLobbyRecord& rec(_visible_lobbies[obj->lobby_id]) ;
|
||||||
|
lobby_count = rec.total_number_of_peers ;
|
||||||
|
|
||||||
|
// max objects per second: lobby_count * 1/MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE objects per second.
|
||||||
|
// So in cache, there is in average that number times MAX_MESSAGES_PER_SECONDS_PERIOD
|
||||||
|
//
|
||||||
|
float max_cnt = std::max(10.0f, 4*lobby_count / (float)MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE * MAX_MESSAGES_PER_SECONDS_PERIOD) ;
|
||||||
|
|
||||||
|
#ifdef CHAT_DEBUG
|
||||||
|
std::cerr << "lobby_count=" << lobby_count << std::endl;
|
||||||
|
std::cerr << "Got msg for peer " << pid << std::dec << ". Limit is " << max_cnt << ". List is " ;
|
||||||
|
for(std::list<time_t>::const_iterator it(message_counts[pid].begin());it!=message_counts[pid].end();++it)
|
||||||
|
std::cerr << *it << " " ;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
time_t now = time(NULL) ;
|
||||||
|
|
||||||
|
std::list<time_t>& lst = message_counts[pid] ;
|
||||||
|
|
||||||
|
// Clean old messages time stamps from the list.
|
||||||
|
//
|
||||||
|
while(!lst.empty() && lst.front() + MAX_MESSAGES_PER_SECONDS_PERIOD < now)
|
||||||
|
lst.pop_front() ;
|
||||||
|
|
||||||
|
if(lst.size() > max_cnt)
|
||||||
|
{
|
||||||
|
std::cerr << "Too many messages from peer " << pid << ". Someone (name=" << obj->nick << ") is trying to flood this lobby. Message will not be forwarded." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lst.push_back(now) ;
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
void p3ChatService::handleIncomingItem(RsItem *item)
|
void p3ChatService::handleIncomingItem(RsItem *item)
|
||||||
{
|
{
|
||||||
#ifdef CHAT_DEBUG
|
#ifdef CHAT_DEBUG
|
||||||
std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ;
|
std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// RsChatMsgItems needs dynamic_cast, since they have derived siblings.
|
// RsChatMsgItems needs dynamic_cast, since they have derived siblings.
|
||||||
//
|
//
|
||||||
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
|
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
|
||||||
@ -2139,6 +2201,7 @@ bool p3ChatService::bounceLobbyObject(RsChatLobbyBouncingObject *item,const std:
|
|||||||
#endif
|
#endif
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatLobbyEntry& lobby(it->second) ;
|
ChatLobbyEntry& lobby(it->second) ;
|
||||||
|
|
||||||
// Adds the peer id to the list of friend participants, even if it's not original msg source
|
// Adds the peer id to the list of friend participants, even if it's not original msg source
|
||||||
@ -2167,6 +2230,10 @@ bool p3ChatService::bounceLobbyObject(RsChatLobbyBouncingObject *item,const std:
|
|||||||
lobby.msg_cache[item->msg_id] = now ;
|
lobby.msg_cache[item->msg_id] = now ;
|
||||||
lobby.last_activity = now ;
|
lobby.last_activity = now ;
|
||||||
|
|
||||||
|
// Check that if we have a lobby bouncing object, it's not flooding the lobby
|
||||||
|
if(!locked_bouncingObjectCheck(item,peer_id,lobby.participating_friends.size()))
|
||||||
|
return false;
|
||||||
|
|
||||||
bool is_message = (NULL != dynamic_cast<RsChatLobbyMsgItem*>(item)) ;
|
bool is_message = (NULL != dynamic_cast<RsChatLobbyMsgItem*>(item)) ;
|
||||||
|
|
||||||
// Forward to allparticipating friends, except this peer.
|
// Forward to allparticipating friends, except this peer.
|
||||||
|
@ -230,6 +230,9 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi
|
|||||||
void handleRecvChatLobbyList(RsChatLobbyListItem_deprecated2 *item) ;
|
void handleRecvChatLobbyList(RsChatLobbyListItem_deprecated2 *item) ;
|
||||||
void handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) ;
|
void handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) ;
|
||||||
|
|
||||||
|
/// Checks that the lobby object is not flooding a lobby.
|
||||||
|
bool locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const std::string& peer_id,uint32_t lobby_count) ;
|
||||||
|
|
||||||
/// Sends a request for an avatar to the peer of given id
|
/// Sends a request for an avatar to the peer of given id
|
||||||
void sendAvatarRequest(const std::string& peer_id) ;
|
void sendAvatarRequest(const std::string& peer_id) ;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user