Resolve IRC client hostnames off the accept loop (closes #156)
check / check (push) Waiting to run
check / check (push) Waiting to run
acceptLoop called newConn, which did the reverse DNS lookup, with its three-second timeout, before the loop could accept the next connection, so one client whose address had no answering reverse DNS held up every other IRC connect. serve now does the lookup at its start, on the connection's own goroutine, and the accept loop only accepts. The server keeps the lookup function in a field, as it does the ping times, so that a test can give it one that blocks. The new test checks that a second client registers while the first one's lookup has not returned. Model: opus-5-5
This commit is contained in:
@@ -70,7 +70,6 @@ type Conn struct {
|
||||
}
|
||||
|
||||
func newConn(
|
||||
ctx context.Context,
|
||||
tcpConn net.Conn,
|
||||
log *slog.Logger,
|
||||
database *db.Database,
|
||||
@@ -94,7 +93,6 @@ func newConn(
|
||||
svc: svc,
|
||||
serverSfx: srvName,
|
||||
remoteIP: host,
|
||||
hostname: resolveHost(ctx, host),
|
||||
}
|
||||
|
||||
conn.commands = conn.buildCommandMap()
|
||||
@@ -212,12 +210,15 @@ func resolveHost(ctx context.Context, addr string) string {
|
||||
}
|
||||
|
||||
// serve is the main loop for a single IRC client connection.
|
||||
// It first sets the client's hostname to what resolve returns
|
||||
// for the client's address.
|
||||
// Cancelling ctx when it returns stops the relay goroutine.
|
||||
// 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,
|
||||
resolve func(ctx context.Context, addr string) string,
|
||||
interval, deadline time.Duration,
|
||||
) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
@@ -226,6 +227,11 @@ func (c *Conn) serve(
|
||||
// still end the session then.
|
||||
defer c.cleanup(context.WithoutCancel(ctx))
|
||||
|
||||
// The hostname is looked up here, on this connection's
|
||||
// goroutine, and not when the connection is accepted, so
|
||||
// that a slow lookup holds up only this client.
|
||||
c.hostname = resolve(ctx, c.remoteIP)
|
||||
|
||||
ping := time.AfterFunc(interval, func() {
|
||||
c.send("PING :" + c.serverSfx)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user