blob: 4d971c451b7f8f7f6c15b1d9bf85889313745783 [file] [log] [blame]
// Copyright (c) 2019, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package runner
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"net"
)
const tagHandshake = byte('H')
const tagApplication = byte('A')
type mockQUICTransport struct {
net.Conn
readSecret, writeSecret []byte
}
func newMockQUICTransport(conn net.Conn) *mockQUICTransport {
return &mockQUICTransport{Conn: conn}
}
func (m *mockQUICTransport) read() (byte, []byte, error) {
header := make([]byte, 5)
if _, err := io.ReadFull(m.Conn, header); err != nil {
return 0, nil, err
}
var length uint32
binary.Read(bytes.NewBuffer(header[1:]), binary.BigEndian, &length)
secret := make([]byte, len(m.readSecret))
if _, err := io.ReadFull(m.Conn, secret); err != nil {
return 0, nil, err
}
if !bytes.Equal(secret, m.readSecret) {
return 0, nil, fmt.Errorf("secrets don't match")
}
out := make([]byte, int(length))
if _, err := io.ReadFull(m.Conn, out); err != nil {
return 0, nil, err
}
return header[0], out, nil
}
func (m *mockQUICTransport) readRecord(want recordType) (recordType, *block, error) {
typ, contents, err := m.read()
if err != nil {
return 0, nil, err
}
var returnType recordType
if typ == tagHandshake {
returnType = recordTypeHandshake
} else if typ == tagApplication {
returnType = recordTypeApplicationData
} else {
return 0, nil, fmt.Errorf("unknown type %d\n", typ)
}
return returnType, &block{contents, 0, nil}, nil
}
func (m *mockQUICTransport) writeRecord(typ recordType, data []byte) (int, error) {
tag := tagHandshake
if typ == recordTypeApplicationData {
tag = tagApplication
} else if typ != recordTypeHandshake {
return 0, fmt.Errorf("unsupported record type %d\n", typ)
}
payload := make([]byte, 1+4+len(m.writeSecret)+len(data))
payload[0] = tag
binary.BigEndian.PutUint32(payload[1:5], uint32(len(data)))
copy(payload[5:], m.writeSecret)
copy(payload[5+len(m.writeSecret):], data)
if _, err := m.Conn.Write(payload); err != nil {
return 0, err
}
return len(data), nil
}
func (m *mockQUICTransport) Write(b []byte) (int, error) {
panic("unexpected call to Write")
}
func (m *mockQUICTransport) Read(b []byte) (int, error) {
panic("unexpected call to Read")
}