fix deadlock when handling packets

This commit is contained in:
Marten Seemann
2018-11-27 14:58:49 +07:00
parent 3f9831a93d
commit afdf9680e1

View File

@@ -162,8 +162,6 @@ func (h *packetHandlerMap) listen() {
} }
func (h *packetHandlerMap) handlePacket(addr net.Addr, data []byte) error { func (h *packetHandlerMap) handlePacket(addr net.Addr, data []byte) error {
rcvTime := time.Now()
r := bytes.NewReader(data) r := bytes.NewReader(data)
hdr, err := wire.ParseHeader(r, h.connIDLen) hdr, err := wire.ParseHeader(r, h.connIDLen)
// drop the packet if we can't parse the header // drop the packet if we can't parse the header
@@ -171,22 +169,29 @@ func (h *packetHandlerMap) handlePacket(addr net.Addr, data []byte) error {
return fmt.Errorf("error parsing header: %s", err) return fmt.Errorf("error parsing header: %s", err)
} }
h.mutex.RLock() p := &receivedPacket{
handlerEntry, handlerFound := h.handlers[string(hdr.DestConnectionID)] remoteAddr: addr,
server := h.server hdr: hdr,
data: data,
rcvTime: time.Now(),
}
h.mutex.RLock()
defer h.mutex.RUnlock()
handlerEntry, handlerFound := h.handlers[string(hdr.DestConnectionID)]
var handlePacket func(*receivedPacket)
if handlerFound { // existing session if handlerFound { // existing session
handler := handlerEntry.handler handlerEntry.handler.handlePacket(p)
handlePacket = handler.handlePacket return nil
} else { // no session found }
// this might be a stateless reset // No session found.
// This might be a stateless reset.
if !hdr.IsLongHeader { if !hdr.IsLongHeader {
if len(data) >= protocol.MinStatelessResetSize { if len(data) >= protocol.MinStatelessResetSize {
var token [16]byte var token [16]byte
copy(token[:], data[len(data)-16:]) copy(token[:], data[len(data)-16:])
if sess, ok := h.resetTokens[token]; ok { if sess, ok := h.resetTokens[token]; ok {
h.mutex.RUnlock()
sess.destroy(errors.New("received a stateless reset")) sess.destroy(errors.New("received a stateless reset"))
return nil return nil
} }
@@ -194,19 +199,9 @@ func (h *packetHandlerMap) handlePacket(addr net.Addr, data []byte) error {
// TODO(#943): send a stateless reset // TODO(#943): send a stateless reset
return fmt.Errorf("received a short header packet with an unexpected connection ID %s", hdr.DestConnectionID) return fmt.Errorf("received a short header packet with an unexpected connection ID %s", hdr.DestConnectionID)
} }
if server == nil { // no server set if h.server == nil { // no server set
h.mutex.RUnlock()
return fmt.Errorf("received a packet with an unexpected connection ID %s", hdr.DestConnectionID) return fmt.Errorf("received a packet with an unexpected connection ID %s", hdr.DestConnectionID)
} }
handlePacket = server.handlePacket h.server.handlePacket(p)
}
h.mutex.RUnlock()
handlePacket(&receivedPacket{
remoteAddr: addr,
hdr: hdr,
data: data,
rcvTime: rcvTime,
})
return nil return nil
} }