PING a quiet IRC listener client before closing it (closes #155)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
serve closed a connection after five minutes with nothing read and never sent a PING, so a quiet registered client lost its session. It now sends PING :<server> after pingInterval with nothing read, and closes the connection when nothing is read within pongDeadline after that. Every line read starts both waits again. readTimeout is removed. Unregistered connections are sent the PING too, so a PONG before registration is now ignored instead of answered with ERR_NOTREGISTERED. Model: opus-5-5
This commit is contained in:
@@ -20,7 +20,6 @@ import (
|
||||
|
||||
const (
|
||||
maxLineLen = 512
|
||||
readTimeout = 5 * time.Minute
|
||||
writeTimeout = 30 * time.Second
|
||||
killWriteWindow = 2 * time.Second
|
||||
dnsTimeout = 3 * time.Second
|
||||
@@ -214,17 +213,31 @@ func resolveHost(ctx context.Context, addr string) string {
|
||||
|
||||
// serve is the main loop for a single IRC client connection.
|
||||
// Cancelling ctx when it returns stops the relay goroutine.
|
||||
func (c *Conn) serve(ctx context.Context) {
|
||||
// When nothing has been read for interval the client is sent
|
||||
// a PING, and when nothing is read within deadline after that
|
||||
// the connection is closed.
|
||||
func (c *Conn) serve(
|
||||
ctx context.Context,
|
||||
interval, deadline time.Duration,
|
||||
) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
defer c.cleanup(ctx)
|
||||
|
||||
ping := time.AfterFunc(interval, func() {
|
||||
c.send("PING :" + c.serverSfx)
|
||||
})
|
||||
defer ping.Stop()
|
||||
|
||||
scanner := bufio.NewScanner(c.conn)
|
||||
scanner.Buffer(make([]byte, maxLineLen), maxLineLen)
|
||||
|
||||
for {
|
||||
// Every line read starts both waits again.
|
||||
ping.Reset(interval)
|
||||
|
||||
_ = c.conn.SetReadDeadline(
|
||||
time.Now().Add(readTimeout),
|
||||
time.Now().Add(interval + deadline),
|
||||
)
|
||||
|
||||
if !scanner.Scan() {
|
||||
@@ -366,7 +379,7 @@ func (c *Conn) handleMessage(
|
||||
msg *Message,
|
||||
) {
|
||||
// Before registration, only NICK, USER, PASS, PING,
|
||||
// QUIT, and CAP are accepted.
|
||||
// PONG, QUIT, and CAP are accepted.
|
||||
if !c.registered {
|
||||
c.handlePreRegistration(ctx, msg)
|
||||
|
||||
@@ -452,6 +465,10 @@ func (c *Conn) handlePreRegistration(
|
||||
case irc.CmdPing:
|
||||
c.handlePing(msg)
|
||||
|
||||
return
|
||||
case irc.CmdPong:
|
||||
// The answer to serve's PING, which unregistered
|
||||
// clients are sent too.
|
||||
return
|
||||
case irc.CmdQuit:
|
||||
c.handleQuit(msg)
|
||||
|
||||
Reference in New Issue
Block a user