Skip to content

Commit

Permalink
Most of the scenarios are now h3-compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
mpiraux committed Apr 24, 2019
1 parent 728f1a0 commit 81ce396
Show file tree
Hide file tree
Showing 24 changed files with 149 additions and 131 deletions.
12 changes: 12 additions & 0 deletions agents/base_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
. "github.com/QUIC-Tracker/quic-tracker"
"log"
"os"
"strings"
"time"
)

Expand Down Expand Up @@ -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{}
Expand Down
23 changes: 18 additions & 5 deletions agents/http09_agent.go
Original file line number Diff line number Diff line change
@@ -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
}

Expand Down Expand Up @@ -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 }
25 changes: 12 additions & 13 deletions agents/http3_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -17,6 +16,7 @@ type HTTP3Response struct {
headersRemaining int
totalProcessed uint64
totalReceived uint64
responseChan chan HTTPResponse
}

func (r HTTP3Response) Complete() bool {
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
}
Expand All @@ -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
Expand All @@ -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
}
19 changes: 15 additions & 4 deletions agents/recovery_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
}
Expand Down
59 changes: 20 additions & 39 deletions bin/http/http_get.go
Original file line number Diff line number Diff line change
@@ -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"
)

Expand All @@ -28,20 +27,20 @@ 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)
}
if *h3 {
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)
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
}
9 changes: 5 additions & 4 deletions bin/test_suite/scenario_runner.go
Original file line number Diff line number Diff line change
@@ -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.")
Expand All @@ -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
Expand Down
7 changes: 4 additions & 3 deletions bin/test_suite/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
}
Expand Down
3 changes: 2 additions & 1 deletion connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
}

Expand Down
Loading

0 comments on commit 81ce396

Please sign in to comment.