Skip to content

Commit

Permalink
MaxIdle from fasthttp
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrr committed Feb 1, 2022
1 parent 58ac8cf commit b021d00
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
1 change: 1 addition & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (s *Server) ServeConn(c net.Conn) error {
writer: make(chan *FrameHeader, 128),
reader: make(chan *FrameHeader, 128),
maxRequestTime: s.s.ReadTimeout,
maxIdleTime: s.s.IdleTimeout,
pingInterval: s.cnf.PingInterval,
logger: s.s.Logger,
debug: s.cnf.Debug,
Expand Down
39 changes: 37 additions & 2 deletions serverConn.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,47 @@ type serverConn struct {
// maxRequestTime is the max time of a request over one single stream
maxRequestTime time.Duration
pingInterval time.Duration
// maxIdleTime is the max time a client can be connected without sending any REQUEST.
// As highlighted, PING/PONG frames are completely excluded.
//
// Therefore, a client that didn't send a request for more than `maxIdleTime` will see it's connection closed.
maxIdleTime time.Duration

st Settings
clientS Settings

// pingTimer
pingTimer *time.Timer
maxRequestTimer *time.Timer
maxIdleTimer *time.Timer

closer chan struct{}

debug bool
logger fasthttp.Logger
}

func (sc *serverConn) closeIdleConn() {
sc.writeGoAway(0, NoError, "connection has been idle for a long time")
if sc.debug {
sc.logger.Printf("Connection is idle. Closing\n")
}
close(sc.closer)
}

func (sc *serverConn) Handshake() error {
return Handshake(false, sc.bw, &sc.st, sc.maxWindow)
}

func (sc *serverConn) Serve() error {
sc.closer = make(chan struct{}, 1)
sc.maxRequestTimer = time.NewTimer(0)
sc.clientWindow = int64(sc.clientS.MaxWindowSize())

if sc.maxIdleTime > 0 {
sc.maxIdleTimer = time.AfterFunc(sc.maxIdleTime, sc.closeIdleConn)
}

defer func() {
if err := recover(); err != nil {
sc.logger.Printf("Serve panicked: %s:\n%s\n", err, debug.Stack())
Expand Down Expand Up @@ -120,13 +141,21 @@ func (sc *serverConn) Serve() error {
err = nil
}

sc.close()

return err
}

func (sc *serverConn) close() {
if sc.pingTimer != nil {
sc.pingTimer.Stop()
}

sc.maxRequestTimer.Stop()
if sc.maxIdleTimer != nil {
sc.maxIdleTimer.Stop()
}

return err
sc.maxRequestTimer.Stop()
}

func (sc *serverConn) handlePing(ping *Ping) {
Expand Down Expand Up @@ -271,6 +300,8 @@ func (sc *serverConn) handleStreams() {
loop:
for {
select {
case <-sc.closer:
break loop
case <-sc.maxRequestTimer.C:
reqTimerArmed = false

Expand Down Expand Up @@ -433,6 +464,10 @@ loop:

break
}

if sc.maxIdleTimer != nil {
sc.maxIdleTimer.Reset(sc.maxIdleTime)
}
}

if err := sc.handleFrame(strm, fr); err != nil {
Expand Down
62 changes: 62 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,65 @@ func TestIssue27(t *testing.T) {
id += 2
}
}

func TestIdleConnection(t *testing.T) {
s := &Server{
s: &fasthttp.Server{
Handler: func(ctx *fasthttp.RequestCtx) {
io.WriteString(ctx, "Hello world")
},
ReadTimeout: time.Second * 5,
IdleTimeout: time.Second * 2,
},
cnf: ServerConfig{
Debug: false,
},
}

c, ln, err := getConn(s)
if err != nil {
t.Fatal(err)
}
defer c.Close()
defer ln.Close()

h1 := makeHeaders(3, c.enc, true, true, map[string]string{
string(StringAuthority): "localhost",
string(StringMethod): "GET",
string(StringPath): "/hello/world",
string(StringScheme): "https",
})

c.writeFrame(h1)

expect := []FrameType{
FrameHeaders, FrameData,
}

for i := 0; i < 2; i++ {
fr, err := c.readNext()
if err != nil {
t.Fatal(err)
}

if fr.Stream() != 3 {
t.Fatalf("Expecting update on stream %d, got %d", 3, fr.Stream())
}

if fr.Type() != expect[i] {
t.Fatalf("Expecting %s, got %s", expect[i], fr.Type())
}
}

_, err = c.readNext()
if err != nil {
if _, ok := err.(*GoAway); !ok {
t.Fatal(err)
}
}

_, err = c.readNext()
if err == nil {
t.Fatal("Expecting error")
}
}

0 comments on commit b021d00

Please sign in to comment.