1cbc620a4SEd Maste /* 2cbc620a4SEd Maste * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 3cbc620a4SEd Maste * 4cbc620a4SEd Maste * Redistribution and use in source and binary forms, with or without 5cbc620a4SEd Maste * modification, are permitted provided that the following conditions 6cbc620a4SEd Maste * are met: 7cbc620a4SEd Maste * 1. Redistributions of source code must retain the above copyright 8cbc620a4SEd Maste * notice, this list of conditions and the following disclaimer. 9cbc620a4SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 10cbc620a4SEd Maste * notice, this list of conditions and the following disclaimer in the 11cbc620a4SEd Maste * documentation and/or other materials provided with the distribution. 12cbc620a4SEd Maste * 3. The name of the author may not be used to endorse or promote products 13cbc620a4SEd Maste * derived from this software without specific prior written permission. 14cbc620a4SEd Maste * 15cbc620a4SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16cbc620a4SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17cbc620a4SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18cbc620a4SEd Maste * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19cbc620a4SEd Maste * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20cbc620a4SEd Maste * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21cbc620a4SEd Maste * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22cbc620a4SEd Maste * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23cbc620a4SEd Maste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24cbc620a4SEd Maste * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25cbc620a4SEd Maste */ 26cbc620a4SEd Maste #ifndef RATELIM_INTERNAL_H_INCLUDED_ 27cbc620a4SEd Maste #define RATELIM_INTERNAL_H_INCLUDED_ 28cbc620a4SEd Maste 29cbc620a4SEd Maste #ifdef __cplusplus 30cbc620a4SEd Maste extern "C" { 31cbc620a4SEd Maste #endif 32cbc620a4SEd Maste 33cbc620a4SEd Maste #include "event2/util.h" 34cbc620a4SEd Maste 35cbc620a4SEd Maste /** A token bucket is an internal structure that tracks how many bytes we are 36cbc620a4SEd Maste * currently willing to read or write on a given bufferevent or group of 37cbc620a4SEd Maste * bufferevents */ 38cbc620a4SEd Maste struct ev_token_bucket { 39cbc620a4SEd Maste /** How many bytes are we willing to read or write right now? These 40cbc620a4SEd Maste * values are signed so that we can do "defecit spending" */ 41cbc620a4SEd Maste ev_ssize_t read_limit, write_limit; 42cbc620a4SEd Maste /** When was this bucket last updated? Measured in abstract 'ticks' 43cbc620a4SEd Maste * relative to the token bucket configuration. */ 44cbc620a4SEd Maste ev_uint32_t last_updated; 45cbc620a4SEd Maste }; 46cbc620a4SEd Maste 47cbc620a4SEd Maste /** Configuration info for a token bucket or set of token buckets. */ 48cbc620a4SEd Maste struct ev_token_bucket_cfg { 49cbc620a4SEd Maste /** How many bytes are we willing to read on average per tick? */ 50cbc620a4SEd Maste size_t read_rate; 51cbc620a4SEd Maste /** How many bytes are we willing to read at most in any one tick? */ 52cbc620a4SEd Maste size_t read_maximum; 53cbc620a4SEd Maste /** How many bytes are we willing to write on average per tick? */ 54cbc620a4SEd Maste size_t write_rate; 55cbc620a4SEd Maste /** How many bytes are we willing to write at most in any one tick? */ 56cbc620a4SEd Maste size_t write_maximum; 57cbc620a4SEd Maste 58cbc620a4SEd Maste /* How long is a tick? Note that fractions of a millisecond are 59cbc620a4SEd Maste * ignored. */ 60cbc620a4SEd Maste struct timeval tick_timeout; 61cbc620a4SEd Maste 62cbc620a4SEd Maste /* How long is a tick, in milliseconds? Derived from tick_timeout. */ 63cbc620a4SEd Maste unsigned msec_per_tick; 64cbc620a4SEd Maste }; 65cbc620a4SEd Maste 66cbc620a4SEd Maste /** The current tick is 'current_tick': add bytes to 'bucket' as specified in 67cbc620a4SEd Maste * 'cfg'. */ 68cbc620a4SEd Maste int ev_token_bucket_update_(struct ev_token_bucket *bucket, 69cbc620a4SEd Maste const struct ev_token_bucket_cfg *cfg, 70cbc620a4SEd Maste ev_uint32_t current_tick); 71cbc620a4SEd Maste 72cbc620a4SEd Maste /** In which tick does 'tv' fall according to 'cfg'? Note that ticks can 73cbc620a4SEd Maste * overflow easily; your code needs to handle this. */ 74cbc620a4SEd Maste ev_uint32_t ev_token_bucket_get_tick_(const struct timeval *tv, 75cbc620a4SEd Maste const struct ev_token_bucket_cfg *cfg); 76cbc620a4SEd Maste 77cbc620a4SEd Maste /** Adjust 'bucket' to respect 'cfg', and note that it was last updated in 78cbc620a4SEd Maste * 'current_tick'. If 'reinitialize' is true, we are changing the 79cbc620a4SEd Maste * configuration of 'bucket'; otherwise, we are setting it up for the first 80cbc620a4SEd Maste * time. 81cbc620a4SEd Maste */ 82cbc620a4SEd Maste int ev_token_bucket_init_(struct ev_token_bucket *bucket, 83cbc620a4SEd Maste const struct ev_token_bucket_cfg *cfg, 84cbc620a4SEd Maste ev_uint32_t current_tick, 85cbc620a4SEd Maste int reinitialize); 86cbc620a4SEd Maste 87cbc620a4SEd Maste int bufferevent_remove_from_rate_limit_group_internal_(struct bufferevent *bev, 88cbc620a4SEd Maste int unsuspend); 89cbc620a4SEd Maste 90cbc620a4SEd Maste /** Decrease the read limit of 'b' by 'n' bytes */ 91cbc620a4SEd Maste #define ev_token_bucket_decrement_read(b,n) \ 92cbc620a4SEd Maste do { \ 93cbc620a4SEd Maste (b)->read_limit -= (n); \ 94cbc620a4SEd Maste } while (0) 95cbc620a4SEd Maste /** Decrease the write limit of 'b' by 'n' bytes */ 96cbc620a4SEd Maste #define ev_token_bucket_decrement_write(b,n) \ 97cbc620a4SEd Maste do { \ 98cbc620a4SEd Maste (b)->write_limit -= (n); \ 99cbc620a4SEd Maste } while (0) 100cbc620a4SEd Maste 101cbc620a4SEd Maste #ifdef __cplusplus 102cbc620a4SEd Maste } 103cbc620a4SEd Maste #endif 104cbc620a4SEd Maste 105cbc620a4SEd Maste #endif 106