1package quic
2
3import (
4	"fmt"
5
6	"github.com/lucas-clemente/quic-go/internal/protocol"
7	"github.com/lucas-clemente/quic-go/internal/wire"
8)
9
10type cryptoDataHandler interface {
11	HandleMessage([]byte, protocol.EncryptionLevel) bool
12}
13
14type cryptoStreamManager struct {
15	cryptoHandler cryptoDataHandler
16
17	initialStream   cryptoStream
18	handshakeStream cryptoStream
19	oneRTTStream    cryptoStream
20}
21
22func newCryptoStreamManager(
23	cryptoHandler cryptoDataHandler,
24	initialStream cryptoStream,
25	handshakeStream cryptoStream,
26	oneRTTStream cryptoStream,
27) *cryptoStreamManager {
28	return &cryptoStreamManager{
29		cryptoHandler:   cryptoHandler,
30		initialStream:   initialStream,
31		handshakeStream: handshakeStream,
32		oneRTTStream:    oneRTTStream,
33	}
34}
35
36func (m *cryptoStreamManager) HandleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel) (bool /* encryption level changed */, error) {
37	var str cryptoStream
38	//nolint:exhaustive // CRYPTO frames cannot be sent in 0-RTT packets.
39	switch encLevel {
40	case protocol.EncryptionInitial:
41		str = m.initialStream
42	case protocol.EncryptionHandshake:
43		str = m.handshakeStream
44	case protocol.Encryption1RTT:
45		str = m.oneRTTStream
46	default:
47		return false, fmt.Errorf("received CRYPTO frame with unexpected encryption level: %s", encLevel)
48	}
49	if err := str.HandleCryptoFrame(frame); err != nil {
50		return false, err
51	}
52	for {
53		data := str.GetCryptoData()
54		if data == nil {
55			return false, nil
56		}
57		if encLevelFinished := m.cryptoHandler.HandleMessage(data, encLevel); encLevelFinished {
58			return true, str.Finish()
59		}
60	}
61}
62