mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 16:01:55 +03:00
Add doppel and tls packages
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package doppel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/9seconds/mtg/v2/essentials"
|
||||
)
|
||||
|
||||
const (
|
||||
DoppelGangerMaxDurations = 4096
|
||||
DoppelGangerScoutMissionEach = 30 * time.Minute
|
||||
DoppelGangerScoutRepeats = 10
|
||||
)
|
||||
|
||||
type gangerConnRequest struct {
|
||||
ret chan Conn
|
||||
payload essentials.Conn
|
||||
}
|
||||
|
||||
type Ganger struct {
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
logger Logger
|
||||
wg sync.WaitGroup
|
||||
|
||||
scout Scout
|
||||
scoutMissionEach time.Duration
|
||||
scoutMissionRepeats int
|
||||
|
||||
stats *Stats
|
||||
durations []time.Duration
|
||||
|
||||
connRequests chan gangerConnRequest
|
||||
}
|
||||
|
||||
func (g *Ganger) Shutdown() {
|
||||
g.ctxCancel()
|
||||
g.wg.Wait()
|
||||
}
|
||||
|
||||
func (g *Ganger) Run() {
|
||||
g.wg.Go(func() {
|
||||
g.run()
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Ganger) NewConn(conn essentials.Conn) (Conn, error) {
|
||||
req := gangerConnRequest{
|
||||
ret: make(chan Conn),
|
||||
payload: conn,
|
||||
}
|
||||
defer close(req.ret)
|
||||
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
return Conn{}, context.Cause(g.ctx)
|
||||
case g.connRequests <- req:
|
||||
}
|
||||
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
return Conn{}, context.Cause(g.ctx)
|
||||
case conn := <-req.ret:
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Ganger) run() {
|
||||
scoutTicker := time.NewTicker(g.scoutMissionEach)
|
||||
defer func() {
|
||||
scoutTicker.Stop()
|
||||
|
||||
select {
|
||||
case <-scoutTicker.C:
|
||||
default:
|
||||
}
|
||||
}()
|
||||
|
||||
scoutCollectedChan := make(chan []time.Duration)
|
||||
currentScoutCollectedChan := scoutCollectedChan
|
||||
|
||||
updatedStatsChan := make(chan *Stats)
|
||||
|
||||
g.wg.Go(func() {
|
||||
g.runScoutMission(scoutCollectedChan)
|
||||
})
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
return
|
||||
case durations := <-currentScoutCollectedChan:
|
||||
g.durations = append(g.durations, durations...)
|
||||
if len(g.durations) > DoppelGangerMaxDurations {
|
||||
g.durations = g.durations[len(g.durations)-DoppelGangerMaxDurations:]
|
||||
}
|
||||
|
||||
currentScoutCollectedChan = nil
|
||||
g.wg.Go(func() {
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
case updatedStatsChan <- NewStats(durations):
|
||||
}
|
||||
})
|
||||
case stats := <-updatedStatsChan:
|
||||
g.stats = stats
|
||||
currentScoutCollectedChan = scoutCollectedChan
|
||||
case <-scoutTicker.C:
|
||||
g.wg.Go(func() {
|
||||
g.runScoutMission(scoutCollectedChan)
|
||||
})
|
||||
case req := <-g.connRequests:
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
case req.ret <- NewConn(g.ctx, req.payload, g.stats):
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Ganger) runScoutMission(rvChan chan<- []time.Duration) {
|
||||
durations := []time.Duration{}
|
||||
|
||||
for range g.scoutMissionRepeats {
|
||||
learned, err := g.scout.Learn(g.ctx)
|
||||
if err != nil {
|
||||
g.logger.WarningError("cannot learn", err)
|
||||
continue
|
||||
}
|
||||
durations = append(durations, learned...)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
return
|
||||
case rvChan <- durations:
|
||||
}
|
||||
}
|
||||
|
||||
func NewGanger(
|
||||
ctx context.Context,
|
||||
network Network,
|
||||
logger Logger,
|
||||
scoutEach time.Duration,
|
||||
scoutRepeats int,
|
||||
urls []string,
|
||||
) *Ganger {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
if scoutEach == 0 {
|
||||
scoutEach = DoppelGangerScoutMissionEach
|
||||
}
|
||||
|
||||
if scoutRepeats == 0 {
|
||||
scoutRepeats = DoppelGangerScoutRepeats
|
||||
}
|
||||
|
||||
return &Ganger{
|
||||
ctx: ctx,
|
||||
ctxCancel: cancel,
|
||||
logger: logger,
|
||||
scoutMissionEach: scoutEach,
|
||||
scoutMissionRepeats: scoutRepeats,
|
||||
stats: &Stats{
|
||||
k: StatsDefaultK,
|
||||
lambda: StatsDefaultLambda,
|
||||
},
|
||||
scout: NewScout(network, urls),
|
||||
connRequests: make(chan gangerConnRequest),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user