123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package ircclient
- import (
- "log"
- "time"
- )
- // Track when the client last sent something
- type FloodTrack struct {
- Pos int // Index to store next item
- Size int // Max number of Track items
- Timeout int // Timeout in seconds
- Track []time.Time
- }
- // Initialize flood tracking
- func (F *FloodTrack) Init(size int, timeout int) {
- F.Size = size
- F.Timeout = timeout
- F.Track = make([]time.Time, size)
- }
- // Are we full?
- //
- // Expire records before checking.
- func (F *FloodTrack) Full() bool {
- if F.Pos > 0 {
- F.Expire()
- }
- return F.Pos == F.Size
- }
- // Expire Track records older then timeout
- func (F *FloodTrack) Expire() {
- var idx int
- ReCheck:
- for idx = 0; idx < F.Pos; idx++ {
- // log.Println(idx, time.Since(F.Track[idx]).Seconds())
- if time.Since(F.Track[idx]).Seconds() > float64(F.Timeout) {
- // Remove this from the list
- F.Pos--
- for pos := idx; pos < F.Pos; pos++ {
- F.Track[pos] = F.Track[pos+1]
- }
- goto ReCheck
- }
- }
- }
- // Save Now() into the tracker.
- func (F *FloodTrack) Save() {
- F.Track[F.Pos] = time.Now()
- F.Pos++
- }
- type ThrottleBuffer struct {
- buffer map[string][]string // Map of targets and strings to send
- targets []string // List of targets
- last int // Last index set
- Life_sucks bool // Is throttle active?
- }
- func (T *ThrottleBuffer) Init() {
- T.buffer = make(map[string][]string, 0)
- T.targets = make([]string, 0)
- T.last = 0
- }
- // Pop next available from buffer.
- //
- // If empty, remove from map and targets list. Adjust last if needed.
- func (T *ThrottleBuffer) pop() string {
- // Get next target
- var t string = T.targets[T.last]
- T.last++
- if T.last == len(T.targets) {
- // We're past the end, start over at the beginning.
- T.last = 0
- }
- var msg string = T.buffer[t][0]
- if len(T.buffer[t]) == 1 {
- // This is the last entry for this target.
- delete(T.buffer, t)
- if len(T.targets) == 1 {
- // This is the last entry
- T.targets = make([]string, 0)
- T.Life_sucks = false
- log.Println("Flood control off.")
- } else {
- // Remove t from targets
- for x := 0; x < len(T.targets); x++ {
- if T.targets[x] == t {
- T.targets = append(T.targets[:x], T.targets[x+1:]...)
- if x <= T.last {
- T.last--
- }
- break
- }
- }
- }
- } else {
- // Delete the first entry for t
- T.buffer[t] = append(T.buffer[t][:0], T.buffer[t][1:]...)
- }
- return msg
- }
- // Push item into the buffer, begin throttling.
- func (T *ThrottleBuffer) push(To string, Output string) {
- if len(T.targets) == 0 {
- T.Life_sucks = true
- T.last = 0
- log.Println("Flood control enabled.")
- }
- _, has := T.buffer[To]
- if !has {
- T.buffer[To] = make([]string, 0)
- T.targets = append(T.targets, To)
- }
- T.buffer[To] = append(T.buffer[To], Output)
- }
- // Delete target from buffer, if exists.
- //
- // If we're kicked from the channel we're sending to, or if the
- // nick we're sending to quits -- remove those from write queue.
- func (T *ThrottleBuffer) delete(To string) {
- _, has := T.buffer[To]
- if has {
- // Yes, the buffer has message(s) for To
- delete(T.buffer, To)
- if len(T.targets) == 1 {
- // Last entry
- T.targets = make([]string, 0)
- T.Life_sucks = false
- log.Println("Flood control off.")
- } else {
- // Remove To from targets
- for x := 0; x < len(T.targets); x++ {
- if T.targets[x] == To {
- T.targets = append(T.targets[:x], T.targets[x+1:]...)
- // Don't decrement if already at first item
- if (x <= T.last) && (T.last != 0) {
- T.last--
- }
- break
- }
- }
- }
- }
- }
|