moontalk/server/eventloop-server-experiment/dos.4th
2024-02-17 18:26:14 +00:00

124 lines
3.5 KiB
Forth

\ Denial of service protection.
\ TODO: Use hash table instead?
require util.4th
[UNDEFINED] MAX_CONNECTIONS [IF] 32 constant MAX_CONNECTIONS [THEN]
10 constant DOS_UPDATE_INTERVAL
1024 constant DOS_BYTES_PER_INTERVAL
10 constant DOS_LINES_PER_INTERVAL
3 constant DOS_MAX_CONNECTIONS
MAX_CONNECTIONS constant DOS_MAX_MAPPINGS
\ TODO: is 0 a valid circuit id?
\ TODO: if not, then we could use the circuit id instead of dos.set
0
cell +field dos.set
cell +field dos.circuit-id
cell +field dos.handled
cell +field dos.connections
cell +field dos.total-bytes
cell +field dos.total-lines
cell +field dos.bytes
cell +field dos.lines
constant /DOS
/DOS DOS_MAX_MAPPINGS * constant DOS_ARRAY_SIZE
create dos DOS_ARRAY_SIZE alloterase
\ Lookup table: connection index -> dos stats
create doslt DOS_MAX_MAPPINGS cells alloterase
: (translate) ( index-n -- dos-addr )
/DOS * dos + ;
: (init-dos) ( free-addr circuit-id-n -- dos-addr )
over dos.circuit-id !
true over dos.set ! ;
: (find) ( circuit-id-n -- dos-addr )
0 swap dos DOS_ARRAY_SIZE + dos DO ( -- free-addr circuit-id-n )
I dos.set @ IF
dup I dos.circuit-id @ = IF
2drop I UNLOOP EXIT
THEN
ELSE
over 0= IF
nip I swap
THEN
THEN
/DOS +LOOP
(init-dos) ;
: (lttranslate) ( connection-index-n -- lookup-addr )
cells doslt + ;
: (lookup) ( connection-index-n -- dos-addr )
(lttranslate) @ ;
: (mod-connections) ( n dos-addr -- ) dos.connections +! ;
: (inc-connections) ( dos-addr -- ) 1 swap (mod-connections) ;
: (dec-connections) ( dos-addr -- ) -1 swap (mod-connections) ;
: dos-add-connection ( circuit-id-n connection-index-n -- )
(lttranslate) dup @ 0= IF
swap (find) tuck (inc-connections) !
ELSE
2drop EXIT
THEN ;
: dos-remove-connection ( connection-index-n -- )
\ erase if last connection
(lttranslate) dup 0<> IF
dup @ >r 0 swap ! r>
dup (dec-connections)
dup dos.connections @ 0= IF
/DOS erase
ELSE
drop
THEN
ELSE
drop
THEN ;
: dos-add-bytes ( bytes-n connection-index-n -- )
(lookup) dos.bytes +! ;
: dos-add-lines ( lines-n connection-index-n -- )
(lookup) dos.lines +! ;
: (update) ( dos-addr -- )
dup dos.bytes @ over dos.total-bytes +!
dup dos.lines @ over dos.total-lines +!
0 over dos.bytes !
0 over dos.lines !
drop ;
: dos-update ( -- )
\ add time interval bytes and lines to total and set to 0
dos DOS_ARRAY_SIZE + dos DO
I dos.set @ IF
I (update)
THEN
/DOS +LOOP ;
: (check-bytes) ( dos-addr -- flag ) dos.bytes @ DOS_BYTES_PER_INTERVAL > ;
: (check-lines) ( dos-addr -- flag ) dos.lines @ DOS_LINES_PER_INTERVAL > ;
: (check-connections) ( dos-addr -- flag ) dos.connections @ DOS_MAX_CONNECTIONS > ;
: dos-handled! ( flag connection-index-n -- )
(lttranslate) @ dos.handled ! ;
: dos-handled? ( connection-index-n -- flag )
(lttranslate) @ dos.handled @ ;
: dos? ( connection-index-n -- flag )
(lttranslate) @
dup (check-bytes) over (check-lines)
rot (check-connections) or or ;
: (.dos-info) ( dos-addr -- )
dup ." CircuitID: " dos.circuit-id @ . cr
dup ." Connections: " dos.connections @ . cr
dup ." Total bytes: " dos.total-bytes @ . cr
dup ." Total lines: " dos.total-lines @ . cr
dup ." Bytes: " dos.bytes @ . cr
dup ." Lines: " dos.lines @ . cr
drop ;
: .dos-info ( connection-index-u -- )
(lttranslate) @ (.dos-info) ;
: .dos ( -- )
dos DOS_ARRAY_SIZE + dos DO
I dos.set @ IF
cr I (.dos-info)
THEN
/DOS +LOOP ;