1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-28 14:56:33 -04:00
v2fly/vendor/github.com/lucas-clemente/quic-go/server_tls.go
2018-11-21 10:49:41 +01:00

179 lines
5.1 KiB
Go

package quic
import (
"bytes"
"crypto/tls"
"errors"
"net"
"github.com/bifurcation/mint"
"github.com/lucas-clemente/quic-go/internal/handshake"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/internal/wire"
)
type tlsSession struct {
connID protocol.ConnectionID
sess quicSession
}
type serverTLS struct {
conn net.PacketConn
config *Config
mintConf *mint.Config
params *handshake.TransportParameters
cookieGenerator *handshake.CookieGenerator
newSession func(connection, sessionRunner, protocol.ConnectionID, protocol.ConnectionID, protocol.ConnectionID, protocol.PacketNumber, *Config, *mint.Config, *handshake.TransportParameters, utils.Logger, protocol.VersionNumber) (quicSession, error)
sessionRunner sessionRunner
sessionChan chan<- tlsSession
logger utils.Logger
}
func newServerTLS(
conn net.PacketConn,
config *Config,
runner sessionRunner,
tlsConf *tls.Config,
logger utils.Logger,
) (*serverTLS, <-chan tlsSession, error) {
cookieGenerator, err := handshake.NewCookieGenerator()
if err != nil {
return nil, nil, err
}
params := &handshake.TransportParameters{
StreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
ConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
IdleTimeout: config.IdleTimeout,
MaxBidiStreams: uint16(config.MaxIncomingStreams),
MaxUniStreams: uint16(config.MaxIncomingUniStreams),
DisableMigration: true,
// TODO(#855): generate a real token
StatelessResetToken: bytes.Repeat([]byte{42}, 16),
}
mconf, err := tlsToMintConfig(tlsConf, protocol.PerspectiveServer)
if err != nil {
return nil, nil, err
}
sessionChan := make(chan tlsSession)
s := &serverTLS{
conn: conn,
config: config,
mintConf: mconf,
sessionRunner: runner,
sessionChan: sessionChan,
cookieGenerator: cookieGenerator,
params: params,
newSession: newTLSServerSession,
logger: logger,
}
return s, sessionChan, nil
}
func (s *serverTLS) HandleInitial(p *receivedPacket) {
// TODO: add a check that DestConnID == SrcConnID
s.logger.Debugf("<- Received Initial packet.")
sess, connID, err := s.handleInitialImpl(p)
if err != nil {
s.logger.Errorf("Error occurred handling initial packet: %s", err)
return
}
if sess == nil { // a stateless reset was done
return
}
s.sessionChan <- tlsSession{
connID: connID,
sess: sess,
}
}
func (s *serverTLS) handleInitialImpl(p *receivedPacket) (quicSession, protocol.ConnectionID, error) {
hdr := p.header
if len(hdr.Token) == 0 && hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
return nil, nil, errors.New("dropping Initial packet with too short connection ID")
}
if len(hdr.Raw)+len(p.data) < protocol.MinInitialPacketSize {
return nil, nil, errors.New("dropping too small Initial packet")
}
var cookie *handshake.Cookie
if len(hdr.Token) > 0 {
c, err := s.cookieGenerator.DecodeToken(hdr.Token)
if err == nil {
cookie = c
}
}
if !s.config.AcceptCookie(p.remoteAddr, cookie) {
// Log the Initial packet now.
// If no Retry is sent, the packet will be logged by the session.
p.header.Log(s.logger)
return nil, nil, s.sendRetry(p.remoteAddr, hdr)
}
extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, hdr.Version, s.logger)
mconf := s.mintConf.Clone()
mconf.ExtensionHandler = extHandler
// A server is allowed to perform multiple Retries.
// It doesn't make much sense, but it's something that our API allows.
// In that case it must use a source connection ID of at least 8 bytes.
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
if err != nil {
return nil, nil, err
}
s.logger.Debugf("Changing connection ID to %s.", connID)
sess, err := s.newSession(
&conn{pconn: s.conn, currentAddr: p.remoteAddr},
s.sessionRunner,
hdr.DestConnectionID,
hdr.SrcConnectionID,
connID,
1,
s.config,
mconf,
s.params,
s.logger,
hdr.Version,
)
if err != nil {
return nil, nil, err
}
go sess.run()
sess.handlePacket(p)
return sess, connID, nil
}
func (s *serverTLS) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
token, err := s.cookieGenerator.NewToken(remoteAddr)
if err != nil {
return err
}
connID, err := protocol.GenerateConnectionIDForInitial()
if err != nil {
return err
}
replyHdr := &wire.Header{
IsLongHeader: true,
Type: protocol.PacketTypeRetry,
Version: hdr.Version,
SrcConnectionID: connID,
DestConnectionID: hdr.SrcConnectionID,
OrigDestConnectionID: hdr.DestConnectionID,
Token: token,
}
s.logger.Debugf("Changing connection ID to %s.\n-> Sending Retry", connID)
replyHdr.Log(s.logger)
buf := &bytes.Buffer{}
if err := replyHdr.Write(buf, protocol.PerspectiveServer, hdr.Version); err != nil {
return err
}
if _, err := s.conn.WriteTo(buf.Bytes(), remoteAddr); err != nil {
s.logger.Debugf("Error sending Retry: %s", err)
}
return nil
}