Register incoming stream with loopy as soon as it gets created. (#2144)
This commit is contained in:
@ -84,6 +84,13 @@ func (il *itemList) isEmpty() bool {
|
|||||||
// the control buffer of transport. They represent different aspects of
|
// the control buffer of transport. They represent different aspects of
|
||||||
// control tasks, e.g., flow control, settings, streaming resetting, etc.
|
// control tasks, e.g., flow control, settings, streaming resetting, etc.
|
||||||
|
|
||||||
|
// registerStream is used to register an incoming stream with loopy writer.
|
||||||
|
type registerStream struct {
|
||||||
|
streamID uint32
|
||||||
|
wq *writeQuota
|
||||||
|
}
|
||||||
|
|
||||||
|
// headerFrame is also used to register stream on the client-side.
|
||||||
type headerFrame struct {
|
type headerFrame struct {
|
||||||
streamID uint32
|
streamID uint32
|
||||||
hf []hpack.HeaderField
|
hf []hpack.HeaderField
|
||||||
@ -457,31 +464,40 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
|
|||||||
return l.framer.fr.WriteSettingsAck()
|
return l.framer.fr.WriteSettingsAck()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopyWriter) headerHandler(h *headerFrame) error {
|
func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
|
||||||
if l.side == serverSide {
|
|
||||||
if h.endStream { // Case 1.A: Server wants to close stream.
|
|
||||||
// Make sure it's not a trailers only response.
|
|
||||||
if str, ok := l.estdStreams[h.streamID]; ok {
|
|
||||||
if str.state != empty { // either active or waiting on stream quota.
|
|
||||||
// add it str's list of items.
|
|
||||||
str.itl.enqueue(h)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return l.cleanupStreamHandler(h.cleanup)
|
|
||||||
}
|
|
||||||
// Case 1.B: Server is responding back with headers.
|
|
||||||
str := &outStream{
|
str := &outStream{
|
||||||
|
id: h.streamID,
|
||||||
state: empty,
|
state: empty,
|
||||||
itl: &itemList{},
|
itl: &itemList{},
|
||||||
wq: h.wq,
|
wq: h.wq,
|
||||||
}
|
}
|
||||||
l.estdStreams[h.streamID] = str
|
l.estdStreams[h.streamID] = str
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *loopyWriter) headerHandler(h *headerFrame) error {
|
||||||
|
if l.side == serverSide {
|
||||||
|
str, ok := l.estdStreams[h.streamID]
|
||||||
|
if !ok {
|
||||||
|
warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Case 1.A: Server is responding back with headers.
|
||||||
|
if !h.endStream {
|
||||||
return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
|
return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
|
||||||
}
|
}
|
||||||
|
// else: Case 1.B: Server wants to close stream.
|
||||||
|
|
||||||
|
if str.state != empty { // either active or waiting on stream quota.
|
||||||
|
// add it str's list of items.
|
||||||
|
str.itl.enqueue(h)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return l.cleanupStreamHandler(h.cleanup)
|
||||||
|
}
|
||||||
// Case 2: Client wants to originate stream.
|
// Case 2: Client wants to originate stream.
|
||||||
str := &outStream{
|
str := &outStream{
|
||||||
id: h.streamID,
|
id: h.streamID,
|
||||||
@ -639,6 +655,8 @@ func (l *loopyWriter) handle(i interface{}) error {
|
|||||||
return l.outgoingSettingsHandler(i)
|
return l.outgoingSettingsHandler(i)
|
||||||
case *headerFrame:
|
case *headerFrame:
|
||||||
return l.headerHandler(i)
|
return l.headerHandler(i)
|
||||||
|
case *registerStream:
|
||||||
|
return l.registerStreamHandler(i)
|
||||||
case *cleanupStream:
|
case *cleanupStream:
|
||||||
return l.cleanupStreamHandler(i)
|
return l.cleanupStreamHandler(i)
|
||||||
case *incomingGoAway:
|
case *incomingGoAway:
|
||||||
|
@ -416,6 +416,11 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
|||||||
t.updateWindow(s, uint32(n))
|
t.updateWindow(s, uint32(n))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// Register the stream with loopy.
|
||||||
|
t.controlBuf.put(®isterStream{
|
||||||
|
streamID: s.id,
|
||||||
|
wq: s.wq,
|
||||||
|
})
|
||||||
handle(s)
|
handle(s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -733,7 +738,6 @@ func (t *http2Server) writeHeaderLocked(s *Stream) {
|
|||||||
onWrite: func() {
|
onWrite: func() {
|
||||||
atomic.StoreUint32(&t.resetPingStrikes, 1)
|
atomic.StoreUint32(&t.resetPingStrikes, 1)
|
||||||
},
|
},
|
||||||
wq: s.wq,
|
|
||||||
})
|
})
|
||||||
if t.stats != nil {
|
if t.stats != nil {
|
||||||
// Note: WireLength is not set in outHeader.
|
// Note: WireLength is not set in outHeader.
|
||||||
|
Reference in New Issue
Block a user