84 lines
1.5 KiB
Go
84 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type DiscardedHost struct {
|
|
*Connection
|
|
Host string
|
|
Tries int
|
|
}
|
|
|
|
type DiscardedHostHandler struct {
|
|
mu sync.RWMutex
|
|
port int
|
|
hosts []*DiscardedHost
|
|
onConnection *func(string)
|
|
}
|
|
|
|
func (d *DiscardedHostHandler) run() {
|
|
for range time.Tick(time.Second) {
|
|
d.mu.RLock()
|
|
lst := make([]*DiscardedHost, 0, len(d.hosts))
|
|
for _, host := range d.hosts {
|
|
if host.Tries >= 0 || host.Tries < 5 {
|
|
go d.testConnection(host)
|
|
lst = append(lst, host)
|
|
} else {
|
|
if host.Tries > 0 {
|
|
log.Printf("Host %s discarded after %d tries", host.Host, host.Tries)
|
|
}
|
|
}
|
|
}
|
|
d.mu.RUnlock()
|
|
d.mu.Lock()
|
|
d.hosts = lst
|
|
d.mu.Unlock()
|
|
}
|
|
|
|
}
|
|
|
|
func (d *DiscardedHostHandler) testConnection(host *DiscardedHost) {
|
|
addr := fmt.Sprintf("%s:%d", host.Host, d.port)
|
|
conn, err := net.Dial("tcp", addr)
|
|
|
|
if err != nil {
|
|
host.Tries++
|
|
host.Tries = -1
|
|
} else {
|
|
conn.Close()
|
|
if d.onConnection != nil {
|
|
fn := *d.onConnection
|
|
fn(host.Host)
|
|
}
|
|
}
|
|
}
|
|
|
|
func NewDiscardedHostHandler(port int) *DiscardedHostHandler {
|
|
ret := &DiscardedHostHandler{
|
|
hosts: make([]*DiscardedHost, 0),
|
|
port: port,
|
|
}
|
|
go ret.run()
|
|
return ret
|
|
}
|
|
|
|
func (d *DiscardedHostHandler) SetReconnectHandler(fn func(string)) {
|
|
d.onConnection = &fn
|
|
}
|
|
|
|
func (d *DiscardedHostHandler) AppendHost(host string) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
log.Printf("Adding host %s to retry list", host)
|
|
d.hosts = append(d.hosts, &DiscardedHost{
|
|
Host: host,
|
|
Tries: 0,
|
|
})
|
|
}
|