Skip to content

Commit

Permalink
update dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
birneee committed Nov 2, 2022
1 parent c01979e commit 09dfcbf
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 362 deletions.
16 changes: 8 additions & 8 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,16 @@ func Run(addr net.UDPAddr, timeToFirstByteOnly bool, printRaw bool, createQLog b

c.state.SetStartTime()

var session quic.Session
var connection quic.Connection
if use0RTT {
var err error
session, err = quic.DialAddrEarly(addr.String(), tlsConf, &conf)
connection, err = quic.DialAddrEarly(addr.String(), tlsConf, &conf)
if err != nil {
panic(fmt.Errorf("failed to establish connection: %w", err))
}
} else {
var err error
session, err = quic.DialAddr(addr.String(), tlsConf, &conf)
connection, err = quic.DialAddr(addr.String(), tlsConf, &conf)
if err != nil {
panic(fmt.Errorf("failed to establish connection: %w", err))
}
Expand All @@ -140,15 +140,15 @@ func Run(addr net.UDPAddr, timeToFirstByteOnly bool, printRaw bool, createQLog b
c.state.SetEstablishmentTime()
c.reportEstablishmentTime(&c.state)

if session.ExtraStreamEncrypted() {
if connection.ExtraStreamEncrypted() {
c.logger.Infof("use XSE-QUIC")
}

// migrate
if migrateAfter.Nanoseconds() != 0 {
go func() {
time.Sleep(migrateAfter)
addr, err := session.MigrateUDPSocket()
addr, err := connection.MigrateUDPSocket()
if err != nil {
panic(fmt.Errorf("failed to migrate UDP socket: %w", err))
}
Expand All @@ -161,11 +161,11 @@ func Run(addr net.UDPAddr, timeToFirstByteOnly bool, printRaw bool, createQLog b
signal.Notify(intChan, os.Interrupt)
go func() {
<-intChan
_ = session.CloseWithError(quic.ApplicationErrorCode(quic.NoError), "client_closed")
_ = connection.CloseWithError(quic.ApplicationErrorCode(quic.NoError), "client_closed")
os.Exit(0)
}()

stream, err := session.OpenStream()
stream, err := connection.OpenStream()
if err != nil {
panic(fmt.Errorf("failed to open stream: %w", err))
}
Expand Down Expand Up @@ -199,7 +199,7 @@ func Run(addr net.UDPAddr, timeToFirstByteOnly bool, printRaw bool, createQLog b
}
}

err = session.CloseWithError(common.RuntimeReachedErrorCode, "runtime_reached")
err = connection.CloseWithError(common.RuntimeReachedErrorCode, "runtime_reached")
if err != nil {
panic(fmt.Errorf("failed to close connection: %w", err))
}
Expand Down
56 changes: 14 additions & 42 deletions common/0rtt_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,67 +4,39 @@ import (
"crypto/tls"
"errors"
"github.com/lucas-clemente/quic-go"
"net"
"time"
)

// PingToGatherSessionTicketAndToken establishes a new QUIC connection.
// As soon as the session ticket and the token is received, the connection is closed.
// This function can be used to prepare for 0-RTT
// TODO add timeout
func PingToGatherSessionTicketAndToken(addr string, tlsConf *tls.Config, config *quic.Config) error {
if tlsConf.ClientSessionCache == nil {
return errors.New("session cache is nil")
}
if config.TokenStore == nil {
panic("session cache is nil")
}
session, err := quic.DialAddr(addr, tlsConf, config)

singleSessionCache := NewSingleSessionCache()
singleTokenStore := NewSingleTokenStore()

tmpTlsConf := tlsConf.Clone()
tmpTlsConf.ClientSessionCache = singleSessionCache
tmpConfig := config.Clone()
tmpConfig.TokenStore = singleTokenStore

connection, err := quic.DialAddr(addr, tmpTlsConf, tmpConfig)
if err != nil {
return err
}

sessionCacheKey := sessionCacheKey(session.RemoteAddr(), tlsConf)
tokenStoreKey := tokenStoreKey(session.RemoteAddr(), tlsConf)
tlsConf.ClientSessionCache.Put(singleSessionCache.Await())
config.TokenStore.Put(singleTokenStore.Await())

// await session ticket
for {
time.Sleep(time.Millisecond)
_, ok := tlsConf.ClientSessionCache.Get(sessionCacheKey)
if ok {
break
}
}
// await token
for {
time.Sleep(time.Millisecond)
token := config.TokenStore.Pop(tokenStoreKey)
if token != nil {
config.TokenStore.Put(tokenStoreKey, token) // put back again
break
}
}
err = session.CloseWithError(quic.ApplicationErrorCode(0), "cancel")
err = connection.CloseWithError(quic.ApplicationErrorCode(0), "cancel")
if err != nil {
return err
}
return nil
}

// inspired by qtls.clientSessionCacheKey implementation
// TODO avoid duplicate code
func sessionCacheKey(serverAddr net.Addr, tlsConf *tls.Config) string {
if len(tlsConf.ServerName) > 0 {
return "qtls-" + tlsConf.ServerName
}
return "qtls-" + serverAddr.String()
}

// inspired by quic.newClientSession implementation
// TODO avoid duplicate code
func tokenStoreKey(serverAddr net.Addr, tlsConf *tls.Config) string {
if len(tlsConf.ServerName) > 0 {
return tlsConf.ServerName
} else {
return serverAddr.String()
}
}
121 changes: 3 additions & 118 deletions common/migration_tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"context"
"github.com/lucas-clemente/quic-go/logging"
"net"
"time"
)

type migrationTracer struct {
logging.NullTracer
onMigration func(addr net.Addr)
}

func NewMigrationTracer(onMigration func(addr net.Addr)) *migrationTracer {
func NewMigrationTracer(onMigration func(addr net.Addr)) logging.Tracer {
return &migrationTracer{
onMigration: onMigration,
}
Expand All @@ -23,126 +23,11 @@ func (a migrationTracer) TracerForConnection(ctx context.Context, p logging.Pers
}
}

func (a migrationTracer) SentPacket(addr net.Addr, header *logging.Header, count logging.ByteCount, frames []logging.Frame) {
// ignore
}

func (a migrationTracer) DroppedPacket(addr net.Addr, packetType logging.PacketType, count logging.ByteCount, reason logging.PacketDropReason) {
// ignore
}

type connectionTracer struct {
logging.NullConnectionTracer
onMigration func(addr net.Addr)
}

func (a connectionTracer) StartedConnection(local, remote net.Addr, srcConnID, destConnID logging.ConnectionID) {
// ignore
}

func (a connectionTracer) NegotiatedVersion(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) {
// ignore
}

func (a connectionTracer) ClosedConnection(err error) {
// ignore
}

func (a connectionTracer) SentTransportParameters(parameters *logging.TransportParameters) {
// ignore
}

func (a connectionTracer) ReceivedTransportParameters(parameters *logging.TransportParameters) {
// ignore
}

func (a connectionTracer) RestoredTransportParameters(parameters *logging.TransportParameters) {
// ignore
}

func (a connectionTracer) SentPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, ack *logging.AckFrame, frames []logging.Frame) {
// ignore
}

func (a connectionTracer) ReceivedVersionNegotiationPacket(header *logging.Header, numbers []logging.VersionNumber) {
// ignore
}

func (a connectionTracer) ReceivedRetry(header *logging.Header) {
// ignore
}

func (a connectionTracer) ReceivedPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, frames []logging.Frame) {
// ignore
}

func (a connectionTracer) BufferedPacket(packetType logging.PacketType) {
// ignore
}

func (a connectionTracer) DroppedPacket(packetType logging.PacketType, count logging.ByteCount, reason logging.PacketDropReason) {
// ignore
}

func (a connectionTracer) UpdatedMetrics(rttStats *logging.RTTStats, cwnd, bytesInFlight logging.ByteCount, packetsInFlight int) {
// ignore
}

func (a connectionTracer) AcknowledgedPacket(level logging.EncryptionLevel, number logging.PacketNumber) {
// ignore
}

func (a connectionTracer) LostPacket(level logging.EncryptionLevel, number logging.PacketNumber, reason logging.PacketLossReason) {
// ignore
}

func (a connectionTracer) UpdatedCongestionState(state logging.CongestionState) {
// ignore
}

func (a connectionTracer) UpdatedPTOCount(value uint32) {
// ignore
}

func (a connectionTracer) UpdatedKeyFromTLS(level logging.EncryptionLevel, perspective logging.Perspective) {
// ignore
}

func (a connectionTracer) UpdatedKey(generation logging.KeyPhase, remote bool) {
// ignore
}

func (a connectionTracer) DroppedEncryptionLevel(level logging.EncryptionLevel) {
// ignore
}

func (a connectionTracer) DroppedKey(generation logging.KeyPhase) {
// ignore
}

func (a connectionTracer) SetLossTimer(timerType logging.TimerType, level logging.EncryptionLevel, time time.Time) {
// ignore
}

func (a connectionTracer) LossTimerExpired(timerType logging.TimerType, level logging.EncryptionLevel) {
// ignore
}

func (a connectionTracer) LossTimerCanceled() {
// ignore
}

func (a connectionTracer) Close() {
// ignore
}

func (a connectionTracer) Debug(name, msg string) {
// ignore
}

func (a connectionTracer) UpdatedPath(newRemote net.Addr) {
a.onMigration(newRemote)
}

func (a connectionTracer) XseReceiveRecord(_ logging.StreamID, _ int, _ int) {
// ignore
}
54 changes: 54 additions & 0 deletions common/single_session_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package common

import (
"context"
"crypto/tls"
"github.com/marten-seemann/qtls-go1-19"
)

type SingleSessionCache struct {
emptyContext context.Context
emptyContextCancel context.CancelFunc
sessionKey *string
session *tls.ClientSessionState
}

var _ qtls.ClientSessionCache = (*SingleSessionCache)(nil)

func (s *SingleSessionCache) Get(sessionKey string) (session *tls.ClientSessionState, ok bool) {
select {
case <-s.emptyContext.Done():
if sessionKey == *s.sessionKey {
return session, true
}
default: // do not wait
}
return nil, false
}

func (s *SingleSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
select {
case <-s.emptyContext.Done():
return // already set
default:
//TODO make thread safe
s.sessionKey = &sessionKey
s.session = cs
s.emptyContextCancel()
}
}

func (s *SingleSessionCache) Await() (string, *tls.ClientSessionState) {
<-s.emptyContext.Done()
return *s.sessionKey, s.session
}

func NewSingleSessionCache() *SingleSessionCache {
emptyContext, emptyContextCancel := context.WithCancel(context.Background())
return &SingleSessionCache{
emptyContext,
emptyContextCancel,
nil,
nil,
}
}
53 changes: 53 additions & 0 deletions common/single_token_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package common

import (
"context"
"github.com/lucas-clemente/quic-go"
)

type SingleTokenStore struct {
emptyContext context.Context
emptyContextCancel context.CancelFunc
key *string
token *quic.ClientToken
}

var _ quic.TokenStore = (*SingleTokenStore)(nil)

// Pop does not remove the token
func (s *SingleTokenStore) Pop(key string) (token *quic.ClientToken) {
select {
case <-s.emptyContext.Done():
if key == *s.key {
return s.token
}
default: // do not wait
}
return nil
}

func (s *SingleTokenStore) Put(key string, token *quic.ClientToken) {
select {
case <-s.emptyContext.Done():
return // already set
default:
//TODO make thread safe
s.key = &key
s.token = token
s.emptyContextCancel()
}
}

func (s *SingleTokenStore) Await() (string, *quic.ClientToken) {
<-s.emptyContext.Done()
return *s.key, s.token
}
func NewSingleTokenStore() *SingleTokenStore {
emptyContext, emptyContextCancel := context.WithCancel(context.Background())
return &SingleTokenStore{
emptyContext,
emptyContextCancel,
nil,
nil,
}
}
Loading

0 comments on commit 09dfcbf

Please sign in to comment.