// handleWindowUpdate performs the processing of WINDOW_UPDATE frames. func (c *Conn) handleWindowUpdate(frame *frames.WINDOW_UPDATE) { sid := frame.StreamID if c.criticalCheck(!sid.Valid(), sid, "Received WINDOW_UPDATE with excessive Stream ID %d", sid) { return } delta := frame.DeltaWindowSize bad := delta > common.MAX_DELTA_WINDOW_SIZE || delta < 1 if c.criticalCheck(bad, sid, "Received WINDOW_UPDATE with invalid delta window size %d", delta) { return } // Handle connection-level flow control. if sid.Zero() && c.Subversion > 0 { c.connectionWindowLock.Lock() defer c.connectionWindowLock.Unlock() if int64(delta)+c.connectionWindowSize > common.MAX_TRANSFER_WINDOW_SIZE { goaway := new(frames.GOAWAY) if c.server != nil { c.lastRequestStreamIDLock.Lock() goaway.LastGoodStreamID = c.lastRequestStreamID c.lastRequestStreamIDLock.Unlock() } else { c.lastPushStreamIDLock.Lock() goaway.LastGoodStreamID = c.lastPushStreamID c.lastPushStreamIDLock.Unlock() } goaway.Status = common.GOAWAY_FLOW_CONTROL_ERROR c.output[0] <- goaway return } c.connectionWindowSize += int64(delta) return } // Check stream is open. c.streamsLock.Lock() stream := c.streams[sid] c.streamsLock.Unlock() if stream == nil || stream.State().ClosedHere() { // This is almost certainly benign return } // Stream ID is fine. stream.ReceiveFrame(frame) }
func (c *Conn) _GOAWAY(status common.StatusCode) { goaway := new(frames.GOAWAY) goaway.Status = status c.output[0] <- goaway c.Close() }