forked from quic-go/quic-go
create CryptoSetup for the client, use it in the Session
This commit is contained in:
91
handshake/crypto_setup_client.go
Normal file
91
handshake/crypto_setup_client.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package handshake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type cryptoSetupClient struct {
|
||||
connID protocol.ConnectionID
|
||||
version protocol.VersionNumber
|
||||
|
||||
cryptoStream utils.Stream
|
||||
|
||||
hasServerConfig bool
|
||||
}
|
||||
|
||||
var _ crypto.AEAD = &cryptoSetupClient{}
|
||||
var _ CryptoSetup = &cryptoSetupClient{}
|
||||
|
||||
// NewCryptoSetupClient creates a new CryptoSetup instance for a client
|
||||
func NewCryptoSetupClient(
|
||||
connID protocol.ConnectionID,
|
||||
version protocol.VersionNumber,
|
||||
cryptoStream utils.Stream,
|
||||
) (CryptoSetup, error) {
|
||||
return &cryptoSetupClient{
|
||||
connID: connID,
|
||||
version: version,
|
||||
cryptoStream: cryptoStream,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) HandleCryptoStream() error {
|
||||
h.sendInchoateCHLO()
|
||||
|
||||
for {
|
||||
var chloData bytes.Buffer
|
||||
messageTag, cryptoData, err := ParseHandshakeMessage(io.TeeReader(h.cryptoStream, &chloData))
|
||||
_ = cryptoData
|
||||
utils.Debugf("Received message on Crypto Stream. MessageTag: %#v", messageTag)
|
||||
if err != nil {
|
||||
return qerr.HandshakeFailed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
|
||||
return (&crypto.NullAEAD{}).Open(dst, src, packetNumber, associatedData)
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
|
||||
return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData)
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) DiversificationNonce() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) LockForSealing() {
|
||||
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) UnlockForSealing() {
|
||||
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) HandshakeComplete() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) sendInchoateCHLO() error {
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
tags := make(map[Tag][]byte)
|
||||
tags[TagSNI] = []byte("quic.clemente.io") // TODO: use real SNI here
|
||||
tags[TagPDMD] = []byte("X509")
|
||||
tags[TagPAD] = bytes.Repeat([]byte("0"), 1000)
|
||||
|
||||
WriteHandshakeMessage(b, TagCHLO, tags)
|
||||
|
||||
_, err := h.cryptoStream.Write(b.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
handshake/crypto_setup_client_test.go
Normal file
1
handshake/crypto_setup_client_test.go
Normal file
@@ -0,0 +1 @@
|
||||
package handshake
|
||||
@@ -46,7 +46,7 @@ type cryptoSetupServer struct {
|
||||
|
||||
var _ crypto.AEAD = &cryptoSetupServer{}
|
||||
|
||||
// NewCryptoSetup creates a new CryptoSetup instance
|
||||
// NewCryptoSetup creates a new CryptoSetup instance for a server
|
||||
func NewCryptoSetup(
|
||||
connID protocol.ConnectionID,
|
||||
ip net.IP,
|
||||
|
||||
94
session.go
94
session.go
@@ -43,6 +43,7 @@ type closeCallback func(id protocol.ConnectionID)
|
||||
// A Session is a QUIC session
|
||||
type Session struct {
|
||||
connectionID protocol.ConnectionID
|
||||
perspective protocol.Perspective
|
||||
version protocol.VersionNumber
|
||||
|
||||
streamCallback StreamCallback
|
||||
@@ -95,56 +96,89 @@ type Session struct {
|
||||
|
||||
// newSession makes a new session
|
||||
func newSession(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, streamCallback StreamCallback, closeCallback closeCallback) (packetHandler, error) {
|
||||
connectionParameters := handshake.NewConnectionParamatersManager(v)
|
||||
|
||||
var sentPacketHandler ackhandler.SentPacketHandler
|
||||
rttStats := &congestion.RTTStats{}
|
||||
|
||||
sentPacketHandler = ackhandler.NewSentPacketHandler(rttStats)
|
||||
flowControlManager := flowcontrol.NewFlowControlManager(connectionParameters, rttStats)
|
||||
|
||||
now := time.Now()
|
||||
session := &Session{
|
||||
conn: conn,
|
||||
connectionID: connectionID,
|
||||
perspective: protocol.PerspectiveServer,
|
||||
version: v,
|
||||
|
||||
streamCallback: streamCallback,
|
||||
closeCallback: closeCallback,
|
||||
|
||||
connectionParameters: connectionParameters,
|
||||
sentPacketHandler: sentPacketHandler,
|
||||
flowControlManager: flowControlManager,
|
||||
|
||||
receivedPackets: make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets),
|
||||
closeChan: make(chan *qerr.QuicError, 1),
|
||||
sendingScheduled: make(chan struct{}, 1),
|
||||
undecryptablePackets: make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets),
|
||||
aeadChanged: make(chan struct{}, 1),
|
||||
runClosed: make(chan struct{}, 1), // this channel will receive once the run loop has been stopped
|
||||
|
||||
timer: time.NewTimer(0),
|
||||
lastNetworkActivityTime: now,
|
||||
sessionCreationTime: now,
|
||||
}
|
||||
|
||||
session.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(session.ackAlarmChanged)
|
||||
session.streamsMap = newStreamsMap(session.newStream, session.connectionParameters)
|
||||
|
||||
session.setup()
|
||||
cryptoStream, _ := session.GetOrOpenStream(1)
|
||||
|
||||
var err error
|
||||
session.cryptoSetup, err = handshake.NewCryptoSetup(connectionID, conn.RemoteAddr().IP, v, sCfg, cryptoStream, session.connectionParameters, session.aeadChanged)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
session.streamFramer = newStreamFramer(session.streamsMap, flowControlManager)
|
||||
session.packer = newPacketPacker(connectionID, session.cryptoSetup, session.connectionParameters, session.streamFramer, v)
|
||||
session.unpacker = &packetUnpacker{aead: session.cryptoSetup, version: v}
|
||||
session.packer = newPacketPacker(connectionID, session.cryptoSetup, session.connectionParameters, session.streamFramer, session.version)
|
||||
session.unpacker = &packetUnpacker{aead: session.cryptoSetup, version: session.version}
|
||||
|
||||
return session, err
|
||||
}
|
||||
|
||||
func newClientSession(conn *net.UDPConn, addr *net.UDPAddr, v protocol.VersionNumber, connectionID protocol.ConnectionID, streamCallback StreamCallback, closeCallback closeCallback) (*Session, error) {
|
||||
session := &Session{
|
||||
conn: &udpConn{conn: conn, currentAddr: addr},
|
||||
connectionID: connectionID,
|
||||
perspective: protocol.PerspectiveClient,
|
||||
version: v,
|
||||
|
||||
streamCallback: streamCallback,
|
||||
closeCallback: closeCallback,
|
||||
}
|
||||
|
||||
session.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(session.ackAlarmChanged)
|
||||
session.setup()
|
||||
|
||||
cryptoStream, _ := session.GetOrOpenStream(1)
|
||||
var err error
|
||||
session.cryptoSetup, err = handshake.NewCryptoSetupClient(connectionID, v, cryptoStream)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
session.packer = newPacketPacker(connectionID, session.cryptoSetup, session.connectionParameters, session.streamFramer, session.version)
|
||||
session.unpacker = &packetUnpacker{aead: session.cryptoSetup, version: session.version}
|
||||
|
||||
return session, err
|
||||
}
|
||||
|
||||
// setup is called from newSession and newClientSession and initializes values that are independent of the perspective
|
||||
func (s *Session) setup() {
|
||||
s.rttStats = &congestion.RTTStats{}
|
||||
connectionParameters := handshake.NewConnectionParamatersManager(s.version)
|
||||
flowControlManager := flowcontrol.NewFlowControlManager(connectionParameters, s.rttStats)
|
||||
|
||||
var sentPacketHandler ackhandler.SentPacketHandler
|
||||
sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats)
|
||||
|
||||
now := time.Now()
|
||||
|
||||
s.connectionParameters = connectionParameters
|
||||
s.sentPacketHandler = sentPacketHandler
|
||||
s.flowControlManager = flowControlManager
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.ackAlarmChanged)
|
||||
|
||||
s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets)
|
||||
s.closeChan = make(chan *qerr.QuicError, 1)
|
||||
s.sendingScheduled = make(chan struct{}, 1)
|
||||
s.undecryptablePackets = make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets)
|
||||
s.aeadChanged = make(chan struct{}, 1)
|
||||
s.runClosed = make(chan struct{}, 1)
|
||||
|
||||
s.timer = time.NewTimer(0)
|
||||
s.lastNetworkActivityTime = now
|
||||
s.sessionCreationTime = now
|
||||
|
||||
s.streamsMap = newStreamsMap(s.newStream, s.connectionParameters)
|
||||
s.streamFramer = newStreamFramer(s.streamsMap, s.flowControlManager)
|
||||
}
|
||||
|
||||
// run the session main loop
|
||||
func (s *Session) run() {
|
||||
// Start the crypto stream handler
|
||||
|
||||
Reference in New Issue
Block a user