Skip to content
Snippets Groups Projects
Commit 55b2333e authored by Atanamo's avatar Atanamo
Browse files

Renamed and refactored flooding protection helper

parent 5cde61b0
No related branches found
No related tags found
No related merge requests found
## Abstraction to store and recognize flooding by a client.
##
class ClientFloodingProtection
rating: [] # Array of: [*{'timestamp', 'size'}]
# Describes a rate limit of 1mb/s:
limit: 1048576 # Maximum number of bytes/characters
interval: 1000 # Interval in milliseconds
addRatingEntry: (size) ->
newEntry =
timestamp: Date.now()
size: size
@rating.push(newEntry)
return newEntry
# Removes outdated entries, computes combined size, and compares with limit variable.
# Returns true if client is NOT flooding, returns false if it need to disconnect.
evalRating: ->
# totalSize in bytes in case of underlying Buffer value, in number of characters for strings.
# Actual byte size in case of strings might be variable => not reliable.
totalSize = null
newRating = []
# loop
i = @rating.length - 1
while i >= 0
if Date.now() - @rating[i].timestamp < @interval
newRating.push @rating[i]
i -= 1
@rating = newRating
# loop
totalSize = 0
i = newRating.length - 1
while i >= 0
totalSize += newRating[i].timestamp
i -= 1
return (totalSize <= @limit)
_example: ->
# Assume connection variable already exists and has a readable stream interface
connection.on 'data', (chunk) =>
@addRatingEntry chunk.length
if @evalRating()
# Continue processing chunk.
else
# Disconnect due to flooding.
return
## Export class
module.exports = ClientFloodingProtection
## Abstraction to store and recognize flooding by a client.
##
class ClientFloodingRating
clientSocket: null
ratingEntries: null # Array of: [*{'timestamp', 'size'}]
# Describes a rate limit of 1mb/s:
LIMIT_SIZE = 1048576 # Maximum number of bytes/characters
TIME_INTERVAL = 1000 # Interval in milliseconds
constructor: (@clientSocket) ->
@ratingEntries = []
_addRatingEntry: (size) ->
newEntry =
timestamp: Date.now()
size: size
@ratingEntries.push(newEntry)
return newEntry
_getEntriesWithinInterval: ->
# Collect entries created within interval
intervalEntries = []
nowTimestamp = Date.now()
for currEntry in @ratingEntries by -1
if nowTimestamp - currEntry.timestamp < TIME_INTERVAL # Must be younger than interval time
intervalEntries.push(currEntry)
return intervalEntries
_getCalculatedTotalSize: (entries) ->
totalSize = 0
for currEntry in entries by 1
totalSize += currEntry.size
return totalSize
checkForFlooding: (chunk) ->
@_addRatingEntry(chunk.length)
# Remove outdated entries / update array
@ratingEntries = @_getEntriesWithinInterval()
# Sum up size of entries in interval
totalSize = @_getCalculatedTotalSize(@ratingEntries)
# Check limit
if totalSize > LIMIT_SIZE
clientSocket.disconnect() # TODO: Disconnect due to flooding.
return false
return true
destroy: ->
@clientSocket = null
@ratingEntries = null
## Export class
module.exports = ClientFloodingProtection
 
# Controller class to handle communication with server
class this.ChatController
socketHandler: null
 
CHANNEL_NAME_MIN_LENGTH = 4
CHANNEL_NAME_MAX_LENGTH = 20
CHANNEL_PASSWORD_MIN_LENGTH = 5
serverIP: ''
serverPort: 0
instanceData: {}
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment