From 81ce396229354e46a2d0a10b7d80e06f7924edc6 Mon Sep 17 00:00:00 2001 From: Maxime Piraux Date: Wed, 24 Apr 2019 13:38:16 +0200 Subject: [PATCH] Most of the scenarios are now h3-compatible --- agents/base_agent.go | 12 ++++++ agents/http09_agent.go | 23 +++++++--- agents/http3_agent.go | 25 ++++++----- agents/recovery_agent.go | 19 +++++++-- bin/http/http_get.go | 59 +++++++++----------------- bin/test_suite/scenario_runner.go | 9 ++-- bin/test_suite/test_suite.go | 7 +-- connection.go | 3 +- ietf_quic_hosts.txt | 34 +++++++-------- scenarii/ack_ecn.go | 2 +- scenarii/ack_only.go | 2 +- scenarii/connection_migration.go | 8 ++-- scenarii/connection_migration_v4_v6.go | 7 ++- scenarii/http3_encoder_stream.go | 4 +- scenarii/http3_get.go | 4 +- scenarii/http3_reserved_frames.go | 4 +- scenarii/http3_reserved_streams.go | 4 +- scenarii/http3_uni_streams_limits.go | 3 +- scenarii/http_get_and_wait.go | 4 +- scenarii/key_update.go | 10 ++--- scenarii/multi_stream.go | 8 ++-- scenarii/spin_bit.go | 7 ++- scenarii/zero_rtt.go | 11 +++-- utils.go | 11 ++++- 24 files changed, 149 insertions(+), 131 deletions(-) diff --git a/agents/base_agent.go b/agents/base_agent.go index aea78ff..4dd31ba 100644 --- a/agents/base_agent.go +++ b/agents/base_agent.go @@ -13,6 +13,7 @@ import ( . "github.com/QUIC-Tracker/quic-tracker" "log" "os" + "strings" "time" ) @@ -188,6 +189,17 @@ func (c *ConnectionAgents) CloseConnection(quicLayer bool, errorCode uint16, rea c.StopAll() } +func (c *ConnectionAgents) AddHTTPAgent() HTTPAgent { + var agent HTTPAgent + if strings.HasPrefix(c.conn.ALPN, "h3") { + agent = &HTTP3Agent{DisableQPACKStreams: true} + } else { + agent = &HTTP09Agent{} + } + c.Add(agent) + return agent +} + // Returns the agents needed for a basic QUIC connection to operate func GetDefaultAgents() []Agent { fc := &FlowControlAgent{} diff --git a/agents/http09_agent.go b/agents/http09_agent.go index 81e8125..14e0fec 100644 --- a/agents/http09_agent.go +++ b/agents/http09_agent.go @@ -1,9 +1,12 @@ package agents -import . "github.com/QUIC-Tracker/quic-tracker" +import ( + . "github.com/QUIC-Tracker/quic-tracker" +) type HTTPAgent interface { - SendRequest(path, method, authority string, headers map[string]string) + Agent + SendRequest(path, method, authority string, headers map[string]string) chan HTTPResponse HTTPResponseReceived() Broadcaster } @@ -33,23 +36,33 @@ func (a *HTTP09Agent) Run(conn *Connection) { a.Init("HTTP09Agent", conn.OriginalDestinationCID) a.httpResponseReceived = NewBroadcaster(1000) a.conn = conn + + go func() { + defer a.Logger.Println("Agent terminated") + defer close(a.closed) + <-a.close + }() } -func (a *HTTP09Agent) SendRequest(path, method, authority string, headers map[string]string) { +func (a *HTTP09Agent) SendRequest(path, method, authority string, headers map[string]string) chan HTTPResponse { streamID := a.nextRequestStream a.conn.SendHTTP09GETRequest(path, streamID) - responseChan := a.conn.Streams.Get(a.nextRequestStream).ReadChan.RegisterNewChan(1000) + responseStream := a.conn.Streams.Get(a.nextRequestStream).ReadChan.RegisterNewChan(1000) + responseChan := make(chan HTTPResponse, 1) go func() { response := HTTP09Response{streamID: streamID} - for i := range responseChan { + for i := range responseStream { data := i.([]byte) response.body = append(response.body, data...) } + a.Logger.Printf("A %d-byte long response on stream %d is complete\n", len(response.body), response.streamID) + responseChan <- &response a.httpResponseReceived.Submit(response) }() a.nextRequestStream += 4 + return responseChan } func (a *HTTP09Agent) HTTPResponseReceived() Broadcaster { return a.httpResponseReceived } diff --git a/agents/http3_agent.go b/agents/http3_agent.go index 84e0e4e..c464fef 100644 --- a/agents/http3_agent.go +++ b/agents/http3_agent.go @@ -2,7 +2,6 @@ package agents import ( "bytes" - "errors" . "github.com/QUIC-Tracker/quic-tracker" "github.com/QUIC-Tracker/quic-tracker/http3" "github.com/davecgh/go-spew/spew" @@ -17,6 +16,7 @@ type HTTP3Response struct { headersRemaining int totalProcessed uint64 totalReceived uint64 + responseChan chan HTTPResponse } func (r HTTP3Response) Complete() bool { @@ -39,10 +39,10 @@ type streamData struct { type HTTP3Agent struct { BaseAgent conn *Connection - DisableQPACKStreams bool + DisableQPACKStreams bool QPACK QPACKAgent QPACKEncoderOpts uint32 - HTTPResponseReceived Broadcaster //type: HTTP3Response + httpResponseReceived Broadcaster //type: HTTP3Response FrameReceived Broadcaster //type: HTTP3FrameReceived streamData chan streamData streamDataBuffer map[uint64]*bytes.Buffer @@ -62,7 +62,7 @@ func (a *HTTP3Agent) Run(conn *Connection) { a.QPACK = QPACKAgent{EncoderStreamID: 6, DecoderStreamID: 10, DisableStreams: a.DisableQPACKStreams} a.QPACK.Run(conn) - a.HTTPResponseReceived = NewBroadcaster(1000) + a.httpResponseReceived = NewBroadcaster(1000) a.FrameReceived = NewBroadcaster(1000) frameReceived := a.FrameReceived.RegisterNewChan(1000) @@ -211,11 +211,12 @@ func (a *HTTP3Agent) attemptDecoding(streamID uint64, buffer *bytes.Buffer) { } func (a *HTTP3Agent) checkResponse(response *HTTP3Response) { if response.Complete() { - a.HTTPResponseReceived.Submit(*response) + response.responseChan <- response + a.httpResponseReceived.Submit(*response) a.Logger.Printf("A %d-byte long response on stream %d is complete\n", response.totalProcessed, response.streamID) } } -func (a *HTTP3Agent) SendRequest(path, method, authority string, headers map[string]string) { +func (a *HTTP3Agent) SendRequest(path, method, authority string, headers map[string]string) chan HTTPResponse { if headers == nil { headers = make(map[string]string) } @@ -238,7 +239,7 @@ func (a *HTTP3Agent) SendRequest(path, method, authority string, headers map[str stream := a.conn.Streams.Get(streamID) streamChan := stream.ReadChan.RegisterNewChan(1000) a.streamDataBuffer[streamID] = new(bytes.Buffer) - response := &HTTP3Response{HTTP09Response: HTTP09Response{streamID: streamID}} + response := &HTTP3Response{HTTP09Response: HTTP09Response{streamID: streamID}, responseChan: make(chan HTTPResponse, 1)} a.responseBuffer[streamID] = response go func() { // Pipes the data from the response stream to the agent @@ -265,11 +266,9 @@ func (a *HTTP3Agent) SendRequest(path, method, authority string, headers map[str a.QPACK.EncodeHeaders <- DecodedHeaders{streamID, hdrs} a.nextRequestStream += 4 + return response.responseChan } -func peekVarInt(buffer *bytes.Buffer) (VarInt, error) { - if buffer.Len() == 0 { - return VarInt{}, errors.New("no more byte to read") - } - return ReadVarInt(bytes.NewReader(buffer.Bytes())) -} +func (a *HTTP3Agent) HTTPResponseReceived() Broadcaster { + return a.httpResponseReceived +} \ No newline at end of file diff --git a/agents/recovery_agent.go b/agents/recovery_agent.go index 42aa8fd..99ec669 100644 --- a/agents/recovery_agent.go +++ b/agents/recovery_agent.go @@ -85,9 +85,13 @@ func (a *RecoveryAgent) Run(conn *Connection) { if len(frames) > 0 { a.retransmissionBuffer[p.PNSpace()][p.Header().PacketNumber()] = *NewRetransmittableFrames(frames, p.EncryptionLevel()) } - if p.Contains(ConnectionCloseType) || p.Contains(ApplicationCloseType) { - a.Logger.Println("Connection is closing") - return + if (p.Contains(ConnectionCloseType) || p.Contains(ApplicationCloseType)) && (len(a.retransmissionBuffer[PNSpaceInitial]) > 0 || len(a.retransmissionBuffer[PNSpaceHandshake]) > 0 || len(a.retransmissionBuffer[PNSpaceAppData]) > 0) { + a.Logger.Println("Connection is closing, emptying retransmit buffers") + a.retransmissionBuffer = map[PNSpace]map[PacketNumber]RetransmittableFrames{ + PNSpaceInitial: make(map[PacketNumber]RetransmittableFrames), + PNSpaceHandshake: make(map[PacketNumber]RetransmittableFrames), + PNSpaceAppData: make(map[PacketNumber]RetransmittableFrames), + } } } case i := <-eLAvailable: @@ -98,7 +102,14 @@ func (a *RecoveryAgent) Run(conn *Connection) { a.retransmissionBuffer[PNSpaceHandshake] = make(map[PacketNumber]RetransmittableFrames) } case <-a.conn.ConnectionClosed: - return + if len(a.retransmissionBuffer[PNSpaceInitial]) > 0 || len(a.retransmissionBuffer[PNSpaceHandshake]) > 0 || len(a.retransmissionBuffer[PNSpaceAppData]) > 0 { + a.Logger.Println("Connection is closing, emptying retransmit buffers") + a.retransmissionBuffer = map[PNSpace]map[PacketNumber]RetransmittableFrames{ + PNSpaceInitial: make(map[PacketNumber]RetransmittableFrames), + PNSpaceHandshake: make(map[PacketNumber]RetransmittableFrames), + PNSpaceAppData: make(map[PacketNumber]RetransmittableFrames), + } + } case <-a.close: return } diff --git a/bin/http/http_get.go b/bin/http/http_get.go index 2c802f4..da3c91a 100644 --- a/bin/http/http_get.go +++ b/bin/http/http_get.go @@ -1,16 +1,15 @@ package main import ( - m "github.com/QUIC-Tracker/quic-tracker" - "flag" - "strings" - "fmt" "encoding/json" + "flag" + qt "github.com/QUIC-Tracker/quic-tracker" + "github.com/QUIC-Tracker/quic-tracker/agents" + "github.com/davecgh/go-spew/spew" "log" "net/http" _ "net/http/pprof" - "github.com/QUIC-Tracker/quic-tracker/agents" - "github.com/davecgh/go-spew/spew" + "strings" "time" ) @@ -28,7 +27,7 @@ func main() { flag.Parse() t := time.NewTimer(time.Duration(*timeout) * time.Second) - conn, err := m.NewDefaultConnection(*address, (*address)[:strings.LastIndex(*address, ":")], nil, *useIPv6, *h3) + conn, err := qt.NewDefaultConnection(*address, (*address)[:strings.LastIndex(*address, ":")], nil, *useIPv6, "hq", *h3) if err != nil { panic(err) } @@ -36,12 +35,12 @@ func main() { conn.TLSTPHandler.MaxUniStreams = 3 } - pcap, err := m.StartPcapCapture(conn, *netInterface) + pcap, err := qt.StartPcapCapture(conn, *netInterface) if err != nil { panic(err) } - trace := m.NewTrace("http_get", 1, *address) + trace := qt.NewTrace("http_get", 1, *address) trace.AttachTo(conn) defer func() { trace.Complete(conn) @@ -50,7 +49,7 @@ func main() { trace.Results["pcap_error"] = err.Error() } - var t []m.Trace + var t []qt.Trace t = append(t, *trace) out, err := json.Marshal(t) if err != nil { @@ -82,37 +81,19 @@ func main() { defer conn.CloseConnection(false, 0, "") - if !*h3 { - conn.Streams.Send(0, []byte(fmt.Sprintf("GET %s\r\n", *path)), true) - - incomingPackets := make(chan interface{}, 1000) - conn.IncomingPackets.Register(incomingPackets) - - for { - select { - case <-incomingPackets: - if conn.Streams.Get(0).ReadClosed { - spew.Dump(conn.Streams.Get(0).ReadData) - return - } - case <-t.C: - return - } + var httpAgent agents.HTTPAgent - } + if !*h3 { + httpAgent = &agents.HTTP09Agent{} } else { - http3 := &agents.HTTP3Agent{} - Agents.Add(http3) - - responseReceived := http3.HTTPResponseReceived.RegisterNewChan(1000) - - http3.SendRequest(*path, "GET", trace.Host, nil) + httpAgent = &agents.HTTP3Agent{} + } + Agents.Add(httpAgent) - select { - case r := <-responseReceived: - spew.Dump(r) - case <-t.C: - return - } + select { + case r := <-httpAgent.SendRequest(*path, "GET", trace.Host, nil): + spew.Dump(r) + case <-t.C: + return } } diff --git a/bin/test_suite/scenario_runner.go b/bin/test_suite/scenario_runner.go index 31704a3..b5d5eb4 100644 --- a/bin/test_suite/scenario_runner.go +++ b/bin/test_suite/scenario_runner.go @@ -1,19 +1,20 @@ package main import ( - "os" + "encoding/json" + "flag" qt "github.com/QUIC-Tracker/quic-tracker" s "github.com/QUIC-Tracker/quic-tracker/scenarii" - "flag" + "os" "os/exec" "strings" "time" - "encoding/json" ) func main() { host := flag.String("host", "", "The host endpoint to run the test against.") path := flag.String("path", "/index.html", "The path to request when performing tests that needs data to be sent.") + alpn := flag.String("alpn", "hq", "The ALPN prefix to use when connecting ot the endpoint.") scenarioName := flag.String("scenario", "", "The particular scenario to run.") outputFile := flag.String("output", "", "The file to write the output to. Output to stdout if not set.") debug := flag.Bool("debug", false, "Enables debugging information to be printed.") @@ -35,7 +36,7 @@ func main() { trace := qt.NewTrace(scenario.Name(), scenario.Version(), *host) - conn, err := qt.NewDefaultConnection(*host, strings.Split(*host, ":")[0], nil, scenario.IPv6(), scenario.HTTP3()) // Raw IPv6 are not handled correctly + conn, err := qt.NewDefaultConnection(*host, strings.Split(*host, ":")[0], nil, scenario.IPv6(), *alpn, scenario.HTTP3()) // Raw IPv6 are not handled correctly if err == nil { var pcap *exec.Cmd diff --git a/bin/test_suite/test_suite.go b/bin/test_suite/test_suite.go index b0c052d..26aa40c 100644 --- a/bin/test_suite/test_suite.go +++ b/bin/test_suite/test_suite.go @@ -96,16 +96,17 @@ func main() { for scanner.Scan() { line := strings.Split(scanner.Text(), "\t") host, path := line[0], line[1] - port, err := strconv.Atoi(line[2]) + h3port, err := strconv.Atoi(line[2]) if err != nil { println(err) continue } + preferredALPN := line[3] if scenario.HTTP3() { split := strings.Split(host, ":") host, _ = split[0], split[1] - host = fmt.Sprintf("%s:%d", host, port) + host = fmt.Sprintf("%s:%d", host, h3port) } <-semaphore @@ -135,7 +136,7 @@ func main() { crashTrace := GetCrashTrace(scenario, host) // Prepare one just in case start := time.Now() - args := []string{"run", scenarioRunnerFilename, "-host", host, "-path", path, "-scenario", id, "-interface", *netInterface, "-output", outputFile.Name(), "-timeout", strconv.Itoa(*timeout)} + args := []string{"run", scenarioRunnerFilename, "-host", host, "-path", path, "-alpn", preferredALPN, "-scenario", id, "-interface", *netInterface, "-output", outputFile.Name(), "-timeout", strconv.Itoa(*timeout)} if *debug { args = append(args, "-debug") } diff --git a/connection.go b/connection.go index a2ab04e..b90985c 100644 --- a/connection.go +++ b/connection.go @@ -254,7 +254,7 @@ func EstablishUDPConnection(addr *net.UDPAddr) (*net.UDPConn, error) { } return udpConn, nil } -func NewDefaultConnection(address string, serverName string, resumptionTicket []byte, useIPv6 bool, negotiateHTTP3 bool) (*Connection, error) { +func NewDefaultConnection(address string, serverName string, resumptionTicket []byte, useIPv6 bool, preferredALPN string, negotiateHTTP3 bool) (*Connection, error) { scid := make([]byte, 8, 8) dcid := make([]byte, 8, 8) rand.Read(scid) @@ -280,6 +280,7 @@ func NewDefaultConnection(address string, serverName string, resumptionTicket [] if negotiateHTTP3 { c = NewConnection(serverName, QuicVersion, QuicH3ALPNToken, scid, dcid, udpConn, resumptionTicket) } else { + QuicALPNToken = fmt.Sprintf("%s-%02d", preferredALPN, QuicVersion & 0xff) c = NewConnection(serverName, QuicVersion, QuicALPNToken, scid, dcid, udpConn, resumptionTicket) } diff --git a/ietf_quic_hosts.txt b/ietf_quic_hosts.txt index 59d37d0..5cef241 100644 --- a/ietf_quic_hosts.txt +++ b/ietf_quic_hosts.txt @@ -1,17 +1,17 @@ -quic.ogre.com:4433 /index.html 4433 -minq.dev.mozaws.net:4433 /index.html 4433 -mozquic.ducksong.com:4433 /index.html 4433 -nghttp2.org:4433 /index.html 4433 -quant.eggert.org:4433 /index.html 4433 -kazuhooku.com:4433 /notfound 8433 -quic.westus.cloudapp.azure.com:4433 /index.html 443 -fb.mvfst.net:4433 /index.html 4433 -pandora.cm.in.tum.de:4433 /index.html 4433 -cloudflare-quic.com:443 /index.html 443 -208.85.208.226:4433 /t1.html 4433 -test.privateoctopus.com:4433 / 4433 -quicker.edm.uhasselt.be:4433 /index.html 4433 -ralith.com:4433 /index.html 4433 -xavamedia.nl:4433 /index.html 4433 -http3-test.litespeedtech.com:4433 /index.html 4433 -quic.tech:4433 /index.html 8443 +quic.ogre.com:4433 /index.html 4433 hq +minq.dev.mozaws.net:4433 /index.html 4433 hq +mozquic.ducksong.com:4433 /index.html 4433 hq +nghttp2.org:4433 /index.html 4433 h3 +quant.eggert.org:4433 /index.html 4433 hq +kazuhooku.com:4433 /notfound 8433 hq +quic.westus.cloudapp.azure.com:4433 /index.html 443 hq +fb.mvfst.net:4433 /index.html 4433 hq +pandora.cm.in.tum.de:4433 /index.html 4433 hq +cloudflare-quic.com:443 /index.html 443 h3 +208.85.208.226:4433 /t1.html 4433 hq +test.privateoctopus.com:4433 / 4433 hq +quicker.edm.uhasselt.be:4433 /index.html 4433 hq +ralith.com:4433 /index.html 4433 hq +xavamedia.nl:4433 /index.html 4433 hq +http3-test.litespeedtech.com:4433 /index.html 4433 h3 +quic.tech:4433 /index.html 8443 hq diff --git a/scenarii/ack_ecn.go b/scenarii/ack_ecn.go index 7f3ef8e..16fc107 100644 --- a/scenarii/ack_ecn.go +++ b/scenarii/ack_ecn.go @@ -36,7 +36,7 @@ func (s *AckECNScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPath return } - conn.SendHTTP09GETRequest(preferredPath, 0) + connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = AE_NonECN for { diff --git a/scenarii/ack_only.go b/scenarii/ack_only.go index 9dfbc72..7f1b639 100644 --- a/scenarii/ack_only.go +++ b/scenarii/ack_only.go @@ -26,7 +26,7 @@ func (s *AckOnlyScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPat incPackets := conn.IncomingPackets.RegisterNewChan(1000) - conn.SendHTTP09GETRequest(preferredPath, 0) + connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) var ackOnlyPackets []qt.PacketNumber diff --git a/scenarii/connection_migration.go b/scenarii/connection_migration.go index 45fb3b6..cae59a9 100644 --- a/scenarii/connection_migration.go +++ b/scenarii/connection_migration.go @@ -46,7 +46,7 @@ func (s *ConnectionMigrationScenario) Run(conn *qt.Connection, trace *qt.Trace, incPackets := conn.IncomingPackets.RegisterNewChan(1000) - conn.SendHTTP09GETRequest(preferredPath, 0) + responseChan := connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = CM_HostDidNotMigrate // Assume it until proven wrong for { @@ -60,10 +60,8 @@ func (s *ConnectionMigrationScenario) Run(conn *qt.Connection, trace *qt.Trace, if fp, ok := p.(qt.Framer); ok && fp.Contains(qt.PathChallengeType) { trace.ErrorCode = 0 } - - if conn.Streams.Get(0).ReadClosed { - s.Finished() - } + case <-responseChan: + s.Finished() case <-conn.ConnectionClosed: return case <-s.Timeout(): diff --git a/scenarii/connection_migration_v4_v6.go b/scenarii/connection_migration_v4_v6.go index 6453d5a..7533de3 100644 --- a/scenarii/connection_migration_v4_v6.go +++ b/scenarii/connection_migration_v4_v6.go @@ -86,7 +86,7 @@ firstFlight: incPackets = conn.IncomingPackets.RegisterNewChan(1000) - conn.SendHTTP09GETRequest(preferredPath, 0) + responseChan := connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = CM46_HostDidNotMigrate // Assume it until proven wrong for { @@ -105,9 +105,8 @@ firstFlight: trace.ErrorCode = 0 } - if conn.Streams.Get(0).ReadClosed { - s.Finished() - } + case <-responseChan: + s.Finished() case <-conn.ConnectionClosed: return case <-s.Timeout(): diff --git a/scenarii/http3_encoder_stream.go b/scenarii/http3_encoder_stream.go index a8c40de..9058771 100644 --- a/scenarii/http3_encoder_stream.go +++ b/scenarii/http3_encoder_stream.go @@ -40,8 +40,6 @@ func (s *HTTP3EncoderStreamScenario) Run(conn *qt.Connection, trace *qt.Trace, p } frameReceived := http.FrameReceived.RegisterNewChan(1000) - responseReceived := http.HTTPResponseReceived.RegisterNewChan(1000) - forLoop: for { select { @@ -60,7 +58,7 @@ forLoop: } <-time.NewTimer(200 * time.Millisecond).C - http.SendRequest(preferredPath, "GET", trace.Host, nil) + responseReceived := http.SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = H3ES_RequestTimeout select { diff --git a/scenarii/http3_get.go b/scenarii/http3_get.go index be20758..a7e98e6 100644 --- a/scenarii/http3_get.go +++ b/scenarii/http3_get.go @@ -35,9 +35,7 @@ func (s *HTTP3GETScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPa return } - responseReceived := http.HTTPResponseReceived.RegisterNewChan(1000) - - http.SendRequest(preferredPath, "GET", trace.Host, nil) + responseReceived := http.SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = H3G_RequestTimeout select { diff --git a/scenarii/http3_reserved_frames.go b/scenarii/http3_reserved_frames.go index 2bce899..61fd689 100644 --- a/scenarii/http3_reserved_frames.go +++ b/scenarii/http3_reserved_frames.go @@ -47,9 +47,7 @@ func (s *HTTP3ReservedFramesScenario) Run(conn *qt.Connection, trace *qt.Trace, conn.Streams.Send(0, buf.Bytes(), false) - responseReceived := http.HTTPResponseReceived.RegisterNewChan(1000) - - http.SendRequest(preferredPath, "GET", trace.Host, nil) + responseReceived := http.SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = H3RF_RequestTimeout select { diff --git a/scenarii/http3_reserved_streams.go b/scenarii/http3_reserved_streams.go index eebcefe..84ea513 100644 --- a/scenarii/http3_reserved_streams.go +++ b/scenarii/http3_reserved_streams.go @@ -50,9 +50,7 @@ func (s *HTTP3ReservedStreamsScenario) Run(conn *qt.Connection, trace *qt.Trace, conn.Streams.Send(6, buf.Bytes(), false) conn.Streams.Send(10, buf.Bytes(), false) - responseReceived := http.HTTPResponseReceived.RegisterNewChan(1000) - - http.SendRequest(preferredPath, "GET", trace.Host, nil) + responseReceived := http.SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = H3RS_RequestTimeout select { diff --git a/scenarii/http3_uni_streams_limits.go b/scenarii/http3_uni_streams_limits.go index c236dff..fe905f4 100644 --- a/scenarii/http3_uni_streams_limits.go +++ b/scenarii/http3_uni_streams_limits.go @@ -36,8 +36,7 @@ func (s *HTTP3UniStreamsLimitsScenario) Run(conn *qt.Connection, trace *qt.Trace return } - responseReceived := http.HTTPResponseReceived.RegisterNewChan(1000) - http.SendRequest(preferredPath, "GET", trace.Host, nil) + responseReceived := http.SendRequest(preferredPath, "GET", trace.Host, nil) trace.ErrorCode = H3USFC_RequestTimeout select { diff --git a/scenarii/http_get_and_wait.go b/scenarii/http_get_and_wait.go index 661ead2..34bf700 100644 --- a/scenarii/http_get_and_wait.go +++ b/scenarii/http_get_and_wait.go @@ -44,7 +44,7 @@ func (s *SimpleGetAndWaitScenario) Run(conn *qt.Connection, trace *qt.Trace, pre errors := make(map[uint8]string) incomingPackets := conn.IncomingPackets.RegisterNewChan(1000) - conn.SendHTTP09GETRequest(preferredPath, 0) + responseChan := connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) var connectionCloseReceived bool @@ -71,6 +71,8 @@ forLoop: } } } + case <-responseChan: + break forLoop case <-conn.ConnectionClosed: break forLoop case <-s.Timeout(): diff --git a/scenarii/key_update.go b/scenarii/key_update.go index 0efb6ab..a73efb1 100644 --- a/scenarii/key_update.go +++ b/scenarii/key_update.go @@ -24,8 +24,6 @@ func (s *KeyUpdateScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredP } defer connAgents.CloseConnection(false, 0, "") - incomingPackets := conn.IncomingPackets.RegisterNewChan(1000) - // TODO: Move this to crypto.go readSecret := conn.Tls.HkdfExpandLabel(conn.Tls.ProtectedReadSecret(), "traffic upd", nil, conn.Tls.HashDigestSize(), pigotls.BaseLabel) writeSecret := conn.Tls.HkdfExpandLabel(conn.Tls.ProtectedWriteSecret(), "traffic upd", nil, conn.Tls.HashDigestSize(), pigotls.BaseLabel) @@ -37,15 +35,13 @@ func (s *KeyUpdateScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredP conn.CryptoStates[qt.EncryptionLevel1RTT].HeaderWrite = oldState.HeaderWrite conn.KeyPhaseIndex++ - conn.SendHTTP09GETRequest(preferredPath, 0) + responseChan := connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) forLoop: for { select { - case <-incomingPackets: - if conn.Streams.Get(0).ReadClosed { - s.Finished() - } + case <-responseChan: + s.Finished() case <-conn.ConnectionClosed: break forLoop case <-s.Timeout(): diff --git a/scenarii/multi_stream.go b/scenarii/multi_stream.go index c87588d..694dc1f 100644 --- a/scenarii/multi_stream.go +++ b/scenarii/multi_stream.go @@ -33,15 +33,15 @@ func (s *MultiStreamScenario) Run(conn *qt.Connection, trace *qt.Trace, preferre incPackets := conn.IncomingPackets.RegisterNewChan(1000) for i := uint64(0); i < conn.TLSTPHandler.ReceivedParameters.MaxBidiStreams && i < 4; i++ { - conn.SendHTTP09GETRequest(preferredPath, uint64(i*4)) + connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) } forLoop: for { select { case <-incPackets: - for _, stream := range conn.Streams.GetAll() { - if !stream.ReadClosed { + for streamId, stream := range conn.Streams.GetAll() { + if qt.IsBidi(streamId) && !stream.ReadClosed { allClosed = false break } @@ -59,7 +59,7 @@ forLoop: allClosed = true for streamId, stream := range conn.Streams.GetAll() { - if streamId != 0 && !stream.ReadClosed { + if qt.IsBidi(streamId) && streamId != 0 && !stream.ReadClosed { allClosed = false break } diff --git a/scenarii/spin_bit.go b/scenarii/spin_bit.go index 55e0f06..aa78340 100644 --- a/scenarii/spin_bit.go +++ b/scenarii/spin_bit.go @@ -25,7 +25,8 @@ func (s *SpinBitScenario) Run(conn *Connection, trace *Trace, preferredPath stri incomingPackets := conn.IncomingPackets.RegisterNewChan(1000) - conn.SendHTTP09GETRequest(preferredPath, 0) + http := connAgents.AddHTTPAgent() + responseChan := http.SendRequest(preferredPath, "GET", trace.Host, nil) var lastServerSpin SpinBit spins := 0 @@ -49,6 +50,10 @@ forLoop: conn.SendHTTP09GETRequest(preferredPath, 4) } } + case r := <-responseChan: + if r != nil { + http.SendRequest(preferredPath, "GET", trace.Host, nil) + } case <-conn.ConnectionClosed: break forLoop case <-s.Timeout(): diff --git a/scenarii/zero_rtt.go b/scenarii/zero_rtt.go index 148433a..98cb908 100644 --- a/scenarii/zero_rtt.go +++ b/scenarii/zero_rtt.go @@ -58,7 +58,7 @@ func (s *ZeroRTTScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPat rh, sh, token := conn.ReceivedPacketHandler, conn.SentPacketHandler, conn.Token var err error - conn, err = qt.NewDefaultConnection(conn.Host.String(), conn.ServerName, ticket, s.ipv6, false) + conn, err = qt.NewDefaultConnection(conn.Host.String(), conn.ServerName, ticket, s.ipv6, conn.ALPN, false) conn.ReceivedPacketHandler = rh conn.SentPacketHandler = sh conn.Token = token @@ -86,7 +86,7 @@ func (s *ZeroRTTScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPat // TODO: Handle stateless connection - conn.SendHTTP09GETRequest(preferredPath, 0) // TODO: Verify that this get sent in a 0-RTT packet + responseChan := connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) // TODO: Verify that this get sent in a 0-RTT packet trace.ErrorCode = ZR_DidntReceiveTheRequestedData for { @@ -97,11 +97,10 @@ func (s *ZeroRTTScenario) Run(conn *qt.Connection, trace *qt.Trace, preferredPat if !s.waitFor0RTT(conn, trace, encryptionLevelsAvailable) { return } - conn.SendHTTP09GETRequest(preferredPath, 0) - } - if conn.Streams.Get(0).ReadClosed { - trace.ErrorCode = 0 + responseChan = connAgents.AddHTTPAgent().SendRequest(preferredPath, "GET", trace.Host, nil) } + case <-responseChan: + trace.ErrorCode = 0 case <-conn.ConnectionClosed: return case <-s.Timeout(): diff --git a/utils.go b/utils.go index 241bede..e3b8e1b 100644 --- a/utils.go +++ b/utils.go @@ -4,14 +4,23 @@ import "github.com/dustin/go-broadcast" type Broadcaster struct { broadcast.Broadcaster + channels []chan interface{} } func NewBroadcaster(buflen int) Broadcaster { - return Broadcaster{broadcast.NewBroadcaster(buflen)} + return Broadcaster{Broadcaster: broadcast.NewBroadcaster(buflen)} } func (b *Broadcaster) RegisterNewChan(size int) chan interface{} { c := make(chan interface{}, size) + b.channels = append(b.channels, c) b.Register(c) return c +} + +func (b *Broadcaster) Close() error { + for _, c := range b.channels { + close(c) + } + return b.Broadcaster.Close() } \ No newline at end of file