mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-25 07:29:33 -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 <sstream>
|
||||
|
||||
#include "openssl/rand.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.
|
||||
// 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_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)
|
||||
: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()))
|
||||
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)
|
||||
{
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ;
|
||||
#endif
|
||||
|
||||
// RsChatMsgItems needs dynamic_cast, since they have derived siblings.
|
||||
//
|
||||
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
|
||||
@ -2139,6 +2201,7 @@ bool p3ChatService::bounceLobbyObject(RsChatLobbyBouncingObject *item,const std:
|
||||
#endif
|
||||
return false ;
|
||||
}
|
||||
|
||||
ChatLobbyEntry& lobby(it->second) ;
|
||||
|
||||
// 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.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)) ;
|
||||
|
||||
// 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 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
|
||||
void sendAvatarRequest(const std::string& peer_id) ;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user