\ 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 ;