hid: figured out how to port timeouts
This commit is contained in:
parent
a6e6c3aaff
commit
e0b46a8cff
84
hid/main.go
84
hid/main.go
|
@ -761,7 +761,7 @@ var (
|
|||
|
||||
config simpleConfig // server configuration
|
||||
serverName string // our server name
|
||||
pingInterval uint // ping interval in seconds
|
||||
pingInterval time.Duration // ping interval
|
||||
maxConnections int // max connections allowed or 0
|
||||
motd []string // MOTD (none if empty)
|
||||
operators = make(map[string]bool) // TLS cert. fingerprints for IRCops
|
||||
|
@ -773,7 +773,7 @@ var (
|
|||
prepared = make(chan preparedEvent)
|
||||
reads = make(chan readEvent)
|
||||
writes = make(chan writeEvent)
|
||||
timeouts = make(chan *client)
|
||||
timers = make(chan func())
|
||||
|
||||
tlsConf *tls.Config
|
||||
clients = make(map[*client]bool)
|
||||
|
@ -962,12 +962,7 @@ func (c *client) kill(reason string) {
|
|||
_ = c.transport.Close()
|
||||
}
|
||||
|
||||
// Clean up the goroutine, although a spurious event may still be sent.
|
||||
// TODO: Other timers if needed.
|
||||
if c.killTimer != nil {
|
||||
c.killTimer.Stop()
|
||||
}
|
||||
|
||||
c.cancelTimers()
|
||||
delete(clients, c)
|
||||
}
|
||||
|
||||
|
@ -994,9 +989,7 @@ func (c *client) closeLink(reason string) {
|
|||
c.closing = true
|
||||
|
||||
c.unregister(reason)
|
||||
c.killTimer = time.AfterFunc(3*time.Second, func() {
|
||||
timeouts <- c
|
||||
})
|
||||
c.setKillTimer()
|
||||
}
|
||||
|
||||
func (c *client) inMaskList(masks []string) bool {
|
||||
|
@ -1025,7 +1018,57 @@ func (c *client) getTLSCertFingerprint() string {
|
|||
|
||||
// --- Timers ------------------------------------------------------------------
|
||||
|
||||
// TODO
|
||||
// Free the resources of timers that haven't fired yet and for timers that are
|
||||
// in between firing and being collected by the event loop, mark that the event
|
||||
// should not be acted upon.
|
||||
func (c *client) cancelTimers() {
|
||||
for _, timer := range []**time.Timer{
|
||||
&c.killTimer, &c.timeoutTimer, &c.pingTimer,
|
||||
} {
|
||||
if *timer != nil {
|
||||
(*timer).Stop()
|
||||
*timer = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Arrange for a function to be called later from the main goroutine.
|
||||
func (c *client) setTimer(timer **time.Timer, delay time.Duration, cb func()) {
|
||||
c.cancelTimers()
|
||||
|
||||
var identityCapture *time.Timer
|
||||
identityCapture = time.AfterFunc(delay, func() {
|
||||
timers <- func() {
|
||||
// The timer might have been cancelled or even replaced.
|
||||
// When the client is killed, this will be nil.
|
||||
if *timer == identityCapture {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
*timer = identityCapture
|
||||
}
|
||||
|
||||
func (c *client) setKillTimer() {
|
||||
c.setTimer(&c.killTimer, pingInterval, func() {
|
||||
c.kill("Timeout")
|
||||
})
|
||||
}
|
||||
|
||||
func (c *client) setTimeoutTimer() {
|
||||
c.setTimer(&c.timeoutTimer, pingInterval, func() {
|
||||
c.closeLink(fmt.Sprintf("Ping timeout: >%d seconds",
|
||||
pingInterval/time.Second))
|
||||
})
|
||||
}
|
||||
|
||||
func (c *client) setPingTimer() {
|
||||
c.setTimer(&c.pingTimer, pingInterval, func() {
|
||||
c.sendf("PING :%s", serverName)
|
||||
c.setTimeoutTimer()
|
||||
})
|
||||
}
|
||||
|
||||
// --- IRC command handling ----------------------------------------------------
|
||||
|
||||
|
@ -1451,7 +1494,7 @@ func ircHandlePONG(msg *message, c *client) {
|
|||
}
|
||||
|
||||
// Set a new timer to send another PING
|
||||
// TODO
|
||||
c.setPingTimer()
|
||||
}
|
||||
|
||||
func ircHandleQUIT(msg *message, c *client) {
|
||||
|
@ -2817,6 +2860,7 @@ func (c *client) onPrepared(host string, isTLS bool) {
|
|||
// If we tried to send any data before now, we would need to flushSendQ.
|
||||
go read(c)
|
||||
c.reading = true
|
||||
c.setPingTimer()
|
||||
}
|
||||
|
||||
// Handle the results from trying to read from the client connection.
|
||||
|
@ -2996,6 +3040,9 @@ func processOneEvent() {
|
|||
case <-quitTimer:
|
||||
forceQuit("timeout")
|
||||
|
||||
case callback := <-timers:
|
||||
callback()
|
||||
|
||||
case conn := <-conns:
|
||||
if maxConnections > 0 && len(clients) >= maxConnections {
|
||||
log.Println("connection limit reached, refusing connection")
|
||||
|
@ -3026,6 +3073,9 @@ func processOneEvent() {
|
|||
clients[c] = true
|
||||
go prepare(c)
|
||||
|
||||
// The TLS autodetection in prepare needs to have a timeout.
|
||||
c.setKillTimer()
|
||||
|
||||
case ev := <-prepared:
|
||||
log.Println("client is ready:", ev.host)
|
||||
if _, ok := clients[ev.client]; ok {
|
||||
|
@ -3043,12 +3093,6 @@ func processOneEvent() {
|
|||
if _, ok := clients[ev.client]; ok {
|
||||
ev.client.onWrite(ev.written, ev.err)
|
||||
}
|
||||
|
||||
case c := <-timeouts:
|
||||
if _, ok := clients[c]; ok {
|
||||
log.Println("client timeouted")
|
||||
c.kill("TODO")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3147,7 +3191,7 @@ func ircParseConfig() error {
|
|||
} else if u < 1 {
|
||||
return "the value is out of range"
|
||||
} else {
|
||||
pingInterval = uint(u)
|
||||
pingInterval = time.Second * time.Duration(u)
|
||||
}
|
||||
return ""
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue