add support for the connection_started event

This commit is contained in:
Marten Seemann
2020-02-17 15:44:24 +07:00
parent 81cf5ba409
commit 14a5cc8ab4
5 changed files with 93 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ import (
"net"
"strings"
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
@@ -259,6 +260,9 @@ func populateClientConfig(config *Config, createdPacketConn bool) *Config {
func (c *client) dial(ctx context.Context, qlogger qlog.Tracer) error {
c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
if qlogger != nil {
qlogger.StartedConnection(time.Now(), c.conn.LocalAddr(), c.conn.LocalAddr(), c.version, c.srcConnID, c.destConnID)
}
c.mutex.Lock()
c.session = newClientSession(

View File

@@ -1,6 +1,7 @@
package qlog
import (
"net"
"sort"
"time"
@@ -59,6 +60,42 @@ func (e event) MarshalJSONArray(enc *gojay.Encoder) {
enc.Object(e.eventDetails)
}
type eventConnectionStarted struct {
SrcAddr *net.UDPAddr
DestAddr *net.UDPAddr
Version protocol.VersionNumber
SrcConnectionID protocol.ConnectionID
DestConnectionID protocol.ConnectionID
// TODO: add ALPN
}
var _ eventDetails = &eventConnectionStarted{}
func (e eventConnectionStarted) Category() category { return categoryTransport }
func (e eventConnectionStarted) Name() string { return "connection_started" }
func (e eventConnectionStarted) IsNil() bool { return false }
func (e eventConnectionStarted) MarshalJSONObject(enc *gojay.Encoder) {
// If ip is not an IPv4 address, To4 returns nil.
// Note that there might be some corner cases, where this is not correct.
// See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6.
isIPv6 := e.SrcAddr.IP.To4() == nil
if isIPv6 {
enc.StringKey("ip_version", "ipv6")
} else {
enc.StringKey("ip_version", "ipv4")
}
enc.StringKey("src_ip", e.SrcAddr.IP.String())
enc.IntKey("src_port", e.SrcAddr.Port)
enc.StringKey("dst_ip", e.DestAddr.IP.String())
enc.IntKey("dst_port", e.DestAddr.Port)
enc.StringKey("quic_version", versionNumber(e.Version).String())
enc.StringKey("src_cid", connectionID(e.SrcConnectionID).String())
enc.StringKey("dst_cid", connectionID(e.DestConnectionID).String())
}
type eventPacketSent struct {
PacketType packetType
Header packetHeader

View File

@@ -2,6 +2,7 @@ package qlog
import (
"io"
"net"
"time"
"github.com/lucas-clemente/quic-go/internal/congestion"
@@ -14,6 +15,7 @@ import (
// A Tracer records events to be exported to a qlog.
type Tracer interface {
Export() error
StartedConnection(t time.Time, local, remote net.Addr, version protocol.VersionNumber, srcConnID, destConnID protocol.ConnectionID)
SentPacket(t time.Time, hdr *wire.ExtendedHeader, packetSize protocol.ByteCount, ack *wire.AckFrame, frames []wire.Frame)
ReceivedRetry(time.Time, *wire.Header)
ReceivedPacket(t time.Time, hdr *wire.ExtendedHeader, packetSize protocol.ByteCount, frames []wire.Frame)
@@ -60,6 +62,28 @@ func (t *tracer) Export() error {
return t.w.Close()
}
func (t *tracer) StartedConnection(time time.Time, local, remote net.Addr, version protocol.VersionNumber, srcConnID, destConnID protocol.ConnectionID) {
// ignore this event if we're not dealing with UDP addresses here
localAddr, ok := local.(*net.UDPAddr)
if !ok {
return
}
remoteAddr, ok := remote.(*net.UDPAddr)
if !ok {
return
}
t.events = append(t.events, event{
Time: time,
eventDetails: eventConnectionStarted{
SrcAddr: localAddr,
DestAddr: remoteAddr,
Version: version,
SrcConnectionID: srcConnID,
DestConnectionID: destConnID,
},
})
}
func (t *tracer) SentPacket(time time.Time, hdr *wire.ExtendedHeader, packetSize protocol.ByteCount, ack *wire.AckFrame, frames []wire.Frame) {
numFrames := len(frames)
if ack != nil {

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"io"
"net"
"time"
"github.com/lucas-clemente/quic-go/internal/congestion"
@@ -79,6 +80,30 @@ var _ = Describe("Tracer", func() {
return time.Unix(0, int64(1e6*ev[0].(float64))), ev[1].(string), ev[2].(string), ev[3].(map[string]interface{})
}
It("records connection starts", func() {
now := time.Now()
tracer.StartedConnection(
now,
&net.UDPAddr{IP: net.IPv4(192, 168, 13, 37), Port: 42},
&net.UDPAddr{IP: net.IPv4(192, 168, 12, 34), Port: 24},
0xdeadbeef,
protocol.ConnectionID{1, 2, 3, 4},
protocol.ConnectionID{5, 6, 7, 8},
)
t, category, eventName, ev := exportAndParse()
Expect(t).To(BeTemporally("~", now, time.Millisecond))
Expect(category).To(Equal("transport"))
Expect(eventName).To(Equal("connection_started"))
Expect(ev).To(HaveKeyWithValue("ip_version", "ipv4"))
Expect(ev).To(HaveKeyWithValue("src_ip", "192.168.13.37"))
Expect(ev).To(HaveKeyWithValue("src_port", float64(42)))
Expect(ev).To(HaveKeyWithValue("dst_ip", "192.168.12.34"))
Expect(ev).To(HaveKeyWithValue("dst_port", float64(24)))
Expect(ev).To(HaveKeyWithValue("quic_version", "deadbeef"))
Expect(ev).To(HaveKeyWithValue("src_cid", "01020304"))
Expect(ev).To(HaveKeyWithValue("dst_cid", "05060708"))
})
It("records a sent packet, without an ACK", func() {
now := time.Now()
tracer.SentPacket(

View File

@@ -402,6 +402,9 @@ func (s *baseServer) createNewSession(
qlogger = qlog.NewTracer(w, protocol.PerspectiveServer, origDestConnID)
}
}
if qlogger != nil {
qlogger.StartedConnection(time.Now(), s.conn.LocalAddr(), remoteAddr, version, srcConnID, destConnID)
}
sess := s.newSession(
&conn{pconn: s.conn, currentAddr: remoteAddr},
s.sessionHandler,