mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-04-04 21:57:44 +03:00
Update dep and deps
This commit is contained in:
parent
33bcff7d4a
commit
7740e9d3bc
358 changed files with 2620 additions and 75501 deletions
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
# Treat all files in this repo as binary, with no git magic updating
|
||||
# line endings. Windows users contributing to Go will need to use a
|
||||
# modern version of git and editors capable of LF line endings.
|
||||
#
|
||||
# We'll prevent accidental CRLF line endings from entering the repo
|
||||
# via the git-review gofmt checks.
|
||||
#
|
||||
# See golang.org/issue/9281
|
||||
|
||||
* -text
|
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
# Add no patterns to .hgignore except for files generated by the build.
|
||||
last-change
|
26
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
26
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
# Contributing to Go
|
||||
|
||||
Go is an open source project.
|
||||
|
||||
It is the work of hundreds of contributors. We appreciate your help!
|
||||
|
||||
## Filing issues
|
||||
|
||||
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
|
||||
|
||||
1. What version of Go are you using (`go version`)?
|
||||
2. What operating system and processor architecture are you using?
|
||||
3. What did you do?
|
||||
4. What did you expect to see?
|
||||
5. What did you see instead?
|
||||
|
||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
||||
|
||||
## Contributing code
|
||||
|
||||
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
||||
before sending patches.
|
||||
|
||||
Unless otherwise noted, the Go source files are distributed under
|
||||
the BSD-style license found in the LICENSE file.
|
21
vendor/golang.org/x/crypto/README.md
generated
vendored
21
vendor/golang.org/x/crypto/README.md
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
# Go Cryptography
|
||||
|
||||
This repository holds supplementary Go cryptography libraries.
|
||||
|
||||
## Download/Install
|
||||
|
||||
The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You
|
||||
can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`.
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
||||
this repository, see https://golang.org/doc/contribute.html.
|
||||
|
||||
The main issue tracker for the crypto repository is located at
|
||||
https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the
|
||||
subject line, so it is easy to find.
|
||||
|
||||
Note that contributions to the cryptography package receive additional scrutiny
|
||||
due to their sensitive nature. Patches may take longer than normal to receive
|
||||
feedback.
|
1
vendor/golang.org/x/crypto/codereview.cfg
generated
vendored
1
vendor/golang.org/x/crypto/codereview.cfg
generated
vendored
|
@ -1 +0,0 @@
|
|||
issuerepo: golang/go
|
39
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
39
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
|
@ -1,39 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
||||
|
||||
func TestBaseScalarMult(t *testing.T) {
|
||||
var a, b [32]byte
|
||||
in := &a
|
||||
out := &b
|
||||
a[0] = 1
|
||||
|
||||
for i := 0; i < 200; i++ {
|
||||
ScalarBaseMult(out, in)
|
||||
in, out = out, in
|
||||
}
|
||||
|
||||
result := fmt.Sprintf("%x", in[:])
|
||||
if result != expectedHex {
|
||||
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkScalarBaseMult(b *testing.B) {
|
||||
var in, out [32]byte
|
||||
in[0] = 1
|
||||
|
||||
b.SetBytes(32)
|
||||
for i := 0; i < b.N; i++ {
|
||||
ScalarBaseMult(&out, &in)
|
||||
}
|
||||
}
|
220
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
220
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
|
@ -1,220 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
||||
)
|
||||
|
||||
type zeroReader struct{}
|
||||
|
||||
func (zeroReader) Read(buf []byte) (int, error) {
|
||||
for i := range buf {
|
||||
buf[i] = 0
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
func TestUnmarshalMarshal(t *testing.T) {
|
||||
pub, _, _ := GenerateKey(rand.Reader)
|
||||
|
||||
var A edwards25519.ExtendedGroupElement
|
||||
var pubBytes [32]byte
|
||||
copy(pubBytes[:], pub)
|
||||
if !A.FromBytes(&pubBytes) {
|
||||
t.Fatalf("ExtendedGroupElement.FromBytes failed")
|
||||
}
|
||||
|
||||
var pub2 [32]byte
|
||||
A.ToBytes(&pub2)
|
||||
|
||||
if pubBytes != pub2 {
|
||||
t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignVerify(t *testing.T) {
|
||||
var zero zeroReader
|
||||
public, private, _ := GenerateKey(zero)
|
||||
|
||||
message := []byte("test message")
|
||||
sig := Sign(private, message)
|
||||
if !Verify(public, message, sig) {
|
||||
t.Errorf("valid signature rejected")
|
||||
}
|
||||
|
||||
wrongMessage := []byte("wrong message")
|
||||
if Verify(public, wrongMessage, sig) {
|
||||
t.Errorf("signature of different message accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptoSigner(t *testing.T) {
|
||||
var zero zeroReader
|
||||
public, private, _ := GenerateKey(zero)
|
||||
|
||||
signer := crypto.Signer(private)
|
||||
|
||||
publicInterface := signer.Public()
|
||||
public2, ok := publicInterface.(PublicKey)
|
||||
if !ok {
|
||||
t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
|
||||
}
|
||||
|
||||
if !bytes.Equal(public, public2) {
|
||||
t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
|
||||
}
|
||||
|
||||
message := []byte("message")
|
||||
var noHash crypto.Hash
|
||||
signature, err := signer.Sign(zero, message, noHash)
|
||||
if err != nil {
|
||||
t.Fatalf("error from Sign(): %s", err)
|
||||
}
|
||||
|
||||
if !Verify(public, message, signature) {
|
||||
t.Errorf("Verify failed on signature from Sign()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
// sign.input.gz is a selection of test cases from
|
||||
// https://ed25519.cr.yp.to/python/sign.input
|
||||
testDataZ, err := os.Open("testdata/sign.input.gz")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testDataZ.Close()
|
||||
testData, err := gzip.NewReader(testDataZ)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testData.Close()
|
||||
|
||||
scanner := bufio.NewScanner(testData)
|
||||
lineNo := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
lineNo++
|
||||
|
||||
line := scanner.Text()
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 5 {
|
||||
t.Fatalf("bad number of parts on line %d", lineNo)
|
||||
}
|
||||
|
||||
privBytes, _ := hex.DecodeString(parts[0])
|
||||
pubKey, _ := hex.DecodeString(parts[1])
|
||||
msg, _ := hex.DecodeString(parts[2])
|
||||
sig, _ := hex.DecodeString(parts[3])
|
||||
// The signatures in the test vectors also include the message
|
||||
// at the end, but we just want R and S.
|
||||
sig = sig[:SignatureSize]
|
||||
|
||||
if l := len(pubKey); l != PublicKeySize {
|
||||
t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
|
||||
}
|
||||
|
||||
var priv [PrivateKeySize]byte
|
||||
copy(priv[:], privBytes)
|
||||
copy(priv[32:], pubKey)
|
||||
|
||||
sig2 := Sign(priv[:], msg)
|
||||
if !bytes.Equal(sig, sig2[:]) {
|
||||
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
|
||||
}
|
||||
|
||||
if !Verify(pubKey, msg, sig2) {
|
||||
t.Errorf("signature failed to verify on line %d", lineNo)
|
||||
}
|
||||
|
||||
priv2 := NewKeyFromSeed(priv[:32])
|
||||
if !bytes.Equal(priv[:], priv2) {
|
||||
t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
|
||||
}
|
||||
|
||||
if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
|
||||
t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
|
||||
}
|
||||
|
||||
if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
|
||||
t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
t.Fatalf("error reading test data: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMalleability(t *testing.T) {
|
||||
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
|
||||
// that s be in [0, order). This prevents someone from adding a multiple of
|
||||
// order to s and obtaining a second valid signature for the same message.
|
||||
msg := []byte{0x54, 0x65, 0x73, 0x74}
|
||||
sig := []byte{
|
||||
0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
|
||||
0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
|
||||
0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
|
||||
0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
|
||||
0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
|
||||
0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
|
||||
}
|
||||
publicKey := []byte{
|
||||
0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
|
||||
0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
|
||||
0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
|
||||
}
|
||||
|
||||
if Verify(publicKey, msg, sig) {
|
||||
t.Fatal("non-canonical signature accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkKeyGeneration(b *testing.B) {
|
||||
var zero zeroReader
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, _, err := GenerateKey(zero); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSigning(b *testing.B) {
|
||||
var zero zeroReader
|
||||
_, priv, err := GenerateKey(zero)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
message := []byte("Hello, world!")
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Sign(priv, message)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerification(b *testing.B) {
|
||||
var zero zeroReader
|
||||
pub, priv, err := GenerateKey(zero)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
message := []byte("Hello, world!")
|
||||
signature := Sign(priv, message)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Verify(pub, message, signature)
|
||||
}
|
||||
}
|
50
vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go
generated
vendored
50
vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package subtle_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/internal/subtle"
|
||||
)
|
||||
|
||||
var a, b [100]byte
|
||||
|
||||
var aliasingTests = []struct {
|
||||
x, y []byte
|
||||
anyOverlap, inexactOverlap bool
|
||||
}{
|
||||
{a[:], b[:], false, false},
|
||||
{a[:], b[:0], false, false},
|
||||
{a[:], b[:50], false, false},
|
||||
{a[40:50], a[50:60], false, false},
|
||||
{a[40:50], a[60:70], false, false},
|
||||
{a[:51], a[50:], true, true},
|
||||
{a[:], a[:], true, false},
|
||||
{a[:50], a[:60], true, false},
|
||||
{a[:], nil, false, false},
|
||||
{nil, nil, false, false},
|
||||
{a[:], a[:0], false, false},
|
||||
{a[:10], a[:10:20], true, false},
|
||||
{a[:10], a[5:10:20], true, true},
|
||||
}
|
||||
|
||||
func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) {
|
||||
any := subtle.AnyOverlap(x, y)
|
||||
if any != anyOverlap {
|
||||
t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any)
|
||||
}
|
||||
inexact := subtle.InexactOverlap(x, y)
|
||||
if inexact != inexactOverlap {
|
||||
t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasing(t *testing.T) {
|
||||
for i, tt := range aliasingTests {
|
||||
testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap)
|
||||
testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap)
|
||||
}
|
||||
}
|
78
vendor/golang.org/x/crypto/nacl/box/box_test.go
generated
vendored
78
vendor/golang.org/x/crypto/nacl/box/box_test.go
generated
vendored
|
@ -1,78 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package box
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
func TestSealOpen(t *testing.T) {
|
||||
publicKey1, privateKey1, _ := GenerateKey(rand.Reader)
|
||||
publicKey2, privateKey2, _ := GenerateKey(rand.Reader)
|
||||
|
||||
if *privateKey1 == *privateKey2 {
|
||||
t.Fatalf("private keys are equal!")
|
||||
}
|
||||
if *publicKey1 == *publicKey2 {
|
||||
t.Fatalf("public keys are equal!")
|
||||
}
|
||||
message := []byte("test message")
|
||||
var nonce [24]byte
|
||||
|
||||
box := Seal(nil, message, &nonce, publicKey1, privateKey2)
|
||||
opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
||||
if !ok {
|
||||
t.Fatalf("failed to open box")
|
||||
}
|
||||
|
||||
if !bytes.Equal(opened, message) {
|
||||
t.Fatalf("got %x, want %x", opened, message)
|
||||
}
|
||||
|
||||
for i := range box {
|
||||
box[i] ^= 0x40
|
||||
_, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
||||
if ok {
|
||||
t.Fatalf("opened box with byte %d corrupted", i)
|
||||
}
|
||||
box[i] ^= 0x40
|
||||
}
|
||||
}
|
||||
|
||||
func TestBox(t *testing.T) {
|
||||
var privateKey1, privateKey2 [32]byte
|
||||
for i := range privateKey1[:] {
|
||||
privateKey1[i] = 1
|
||||
}
|
||||
for i := range privateKey2[:] {
|
||||
privateKey2[i] = 2
|
||||
}
|
||||
|
||||
var publicKey1 [32]byte
|
||||
curve25519.ScalarBaseMult(&publicKey1, &privateKey1)
|
||||
var message [64]byte
|
||||
for i := range message[:] {
|
||||
message[i] = 3
|
||||
}
|
||||
|
||||
var nonce [24]byte
|
||||
for i := range nonce[:] {
|
||||
nonce[i] = 4
|
||||
}
|
||||
|
||||
box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2)
|
||||
|
||||
// expected was generated using the C implementation of NaCl.
|
||||
expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc")
|
||||
|
||||
if !bytes.Equal(box, expected) {
|
||||
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
||||
}
|
||||
}
|
95
vendor/golang.org/x/crypto/nacl/box/example_test.go
generated
vendored
95
vendor/golang.org/x/crypto/nacl/box/example_test.go
generated
vendored
|
@ -1,95 +0,0 @@
|
|||
package box_test
|
||||
|
||||
import (
|
||||
crypto_rand "crypto/rand" // Custom so it's clear which rand we're using.
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/nacl/box"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// You must use a different nonce for each message you encrypt with the
|
||||
// same key. Since the nonce here is 192 bits long, a random value
|
||||
// provides a sufficiently small probability of repeats.
|
||||
var nonce [24]byte
|
||||
if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msg := []byte("Alas, poor Yorick! I knew him, Horatio")
|
||||
// This encrypts msg and appends the result to the nonce.
|
||||
encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey)
|
||||
|
||||
// The recipient can decrypt the message using their private key and the
|
||||
// sender's public key. When you decrypt, you must use the same nonce you
|
||||
// used to encrypt the message. One way to achieve this is to store the
|
||||
// nonce alongside the encrypted message. Above, we stored the nonce in the
|
||||
// first 24 bytes of the encrypted text.
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], encrypted[:24])
|
||||
decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
|
||||
if !ok {
|
||||
panic("decryption error")
|
||||
}
|
||||
fmt.Println(string(decrypted))
|
||||
// Output: Alas, poor Yorick! I knew him, Horatio
|
||||
}
|
||||
|
||||
func Example_precompute() {
|
||||
senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// The shared key can be used to speed up processing when using the same
|
||||
// pair of keys repeatedly.
|
||||
sharedEncryptKey := new([32]byte)
|
||||
box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey)
|
||||
|
||||
// You must use a different nonce for each message you encrypt with the
|
||||
// same key. Since the nonce here is 192 bits long, a random value
|
||||
// provides a sufficiently small probability of repeats.
|
||||
var nonce [24]byte
|
||||
if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msg := []byte("A fellow of infinite jest, of most excellent fancy")
|
||||
// This encrypts msg and appends the result to the nonce.
|
||||
encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey)
|
||||
|
||||
// The shared key can be used to speed up processing when using the same
|
||||
// pair of keys repeatedly.
|
||||
var sharedDecryptKey [32]byte
|
||||
box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey)
|
||||
|
||||
// The recipient can decrypt the message using the shared key. When you
|
||||
// decrypt, you must use the same nonce you used to encrypt the message.
|
||||
// One way to achieve this is to store the nonce alongside the encrypted
|
||||
// message. Above, we stored the nonce in the first 24 bytes of the
|
||||
// encrypted text.
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], encrypted[:24])
|
||||
decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey)
|
||||
if !ok {
|
||||
panic("decryption error")
|
||||
}
|
||||
fmt.Println(string(decrypted))
|
||||
// Output: A fellow of infinite jest, of most excellent fancy
|
||||
}
|
53
vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
generated
vendored
53
vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
generated
vendored
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package secretbox_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
// Load your secret key from a safe place and reuse it across multiple
|
||||
// Seal calls. (Obviously don't use this example key for anything
|
||||
// real.) If you want to convert a passphrase to a key, use a suitable
|
||||
// package like bcrypt or scrypt.
|
||||
secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var secretKey [32]byte
|
||||
copy(secretKey[:], secretKeyBytes)
|
||||
|
||||
// You must use a different nonce for each message you encrypt with the
|
||||
// same key. Since the nonce here is 192 bits long, a random value
|
||||
// provides a sufficiently small probability of repeats.
|
||||
var nonce [24]byte
|
||||
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// This encrypts "hello world" and appends the result to the nonce.
|
||||
encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey)
|
||||
|
||||
// When you decrypt, you must use the same nonce and key you used to
|
||||
// encrypt the message. One way to achieve this is to store the nonce
|
||||
// alongside the encrypted message. Above, we stored the nonce in the first
|
||||
// 24 bytes of the encrypted text.
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], encrypted[:24])
|
||||
decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey)
|
||||
if !ok {
|
||||
panic("decryption error")
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
// Output: hello world
|
||||
}
|
154
vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
generated
vendored
154
vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
generated
vendored
|
@ -1,154 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package secretbox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSealOpen(t *testing.T) {
|
||||
var key [32]byte
|
||||
var nonce [24]byte
|
||||
|
||||
rand.Reader.Read(key[:])
|
||||
rand.Reader.Read(nonce[:])
|
||||
|
||||
var box, opened []byte
|
||||
|
||||
for msgLen := 0; msgLen < 128; msgLen += 17 {
|
||||
message := make([]byte, msgLen)
|
||||
rand.Reader.Read(message)
|
||||
|
||||
box = Seal(box[:0], message, &nonce, &key)
|
||||
var ok bool
|
||||
opened, ok = Open(opened[:0], box, &nonce, &key)
|
||||
if !ok {
|
||||
t.Errorf("%d: failed to open box", msgLen)
|
||||
continue
|
||||
}
|
||||
|
||||
if !bytes.Equal(opened, message) {
|
||||
t.Errorf("%d: got %x, expected %x", msgLen, opened, message)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for i := range box {
|
||||
box[i] ^= 0x20
|
||||
_, ok := Open(opened[:0], box, &nonce, &key)
|
||||
if ok {
|
||||
t.Errorf("box was opened after corrupting byte %d", i)
|
||||
}
|
||||
box[i] ^= 0x20
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretBox(t *testing.T) {
|
||||
var key [32]byte
|
||||
var nonce [24]byte
|
||||
var message [64]byte
|
||||
|
||||
for i := range key[:] {
|
||||
key[i] = 1
|
||||
}
|
||||
for i := range nonce[:] {
|
||||
nonce[i] = 2
|
||||
}
|
||||
for i := range message[:] {
|
||||
message[i] = 3
|
||||
}
|
||||
|
||||
box := Seal(nil, message[:], &nonce, &key)
|
||||
// expected was generated using the C implementation of NaCl.
|
||||
expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad")
|
||||
|
||||
if !bytes.Equal(box, expected) {
|
||||
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppend(t *testing.T) {
|
||||
var key [32]byte
|
||||
var nonce [24]byte
|
||||
var message [8]byte
|
||||
|
||||
out := make([]byte, 4)
|
||||
box := Seal(out, message[:], &nonce, &key)
|
||||
if !bytes.Equal(box[:4], out[:4]) {
|
||||
t.Fatalf("Seal didn't correctly append")
|
||||
}
|
||||
|
||||
out = make([]byte, 4, 100)
|
||||
box = Seal(out, message[:], &nonce, &key)
|
||||
if !bytes.Equal(box[:4], out[:4]) {
|
||||
t.Fatalf("Seal didn't correctly append with sufficient capacity.")
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkSealSize(b *testing.B, size int) {
|
||||
message := make([]byte, size)
|
||||
out := make([]byte, size+Overhead)
|
||||
var nonce [24]byte
|
||||
var key [32]byte
|
||||
|
||||
b.SetBytes(int64(size))
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
out = Seal(out[:0], message, &nonce, &key)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSeal8Bytes(b *testing.B) {
|
||||
benchmarkSealSize(b, 8)
|
||||
}
|
||||
|
||||
func BenchmarkSeal100Bytes(b *testing.B) {
|
||||
benchmarkSealSize(b, 100)
|
||||
}
|
||||
|
||||
func BenchmarkSeal1K(b *testing.B) {
|
||||
benchmarkSealSize(b, 1024)
|
||||
}
|
||||
|
||||
func BenchmarkSeal8K(b *testing.B) {
|
||||
benchmarkSealSize(b, 8192)
|
||||
}
|
||||
|
||||
func benchmarkOpenSize(b *testing.B, size int) {
|
||||
msg := make([]byte, size)
|
||||
result := make([]byte, size)
|
||||
var nonce [24]byte
|
||||
var key [32]byte
|
||||
box := Seal(nil, msg, &nonce, &key)
|
||||
|
||||
b.SetBytes(int64(size))
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, ok := Open(result[:0], box, &nonce, &key); !ok {
|
||||
panic("Open failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkOpen8Bytes(b *testing.B) {
|
||||
benchmarkOpenSize(b, 8)
|
||||
}
|
||||
|
||||
func BenchmarkOpen100Bytes(b *testing.B) {
|
||||
benchmarkOpenSize(b, 100)
|
||||
}
|
||||
|
||||
func BenchmarkOpen1K(b *testing.B) {
|
||||
benchmarkOpenSize(b, 1024)
|
||||
}
|
||||
|
||||
func BenchmarkOpen8K(b *testing.B) {
|
||||
benchmarkOpenSize(b, 8192)
|
||||
}
|
132
vendor/golang.org/x/crypto/poly1305/poly1305_test.go
generated
vendored
132
vendor/golang.org/x/crypto/poly1305/poly1305_test.go
generated
vendored
|
@ -1,132 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package poly1305
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var stressFlag = flag.Bool("stress", false, "run slow stress tests")
|
||||
|
||||
type test struct {
|
||||
in string
|
||||
key string
|
||||
tag string
|
||||
}
|
||||
|
||||
func (t *test) Input() []byte {
|
||||
in, err := hex.DecodeString(t.in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (t *test) Key() [32]byte {
|
||||
buf, err := hex.DecodeString(t.key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var key [32]byte
|
||||
copy(key[:], buf[:32])
|
||||
return key
|
||||
}
|
||||
|
||||
func (t *test) Tag() [16]byte {
|
||||
buf, err := hex.DecodeString(t.tag)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var tag [16]byte
|
||||
copy(tag[:], buf[:16])
|
||||
return tag
|
||||
}
|
||||
|
||||
func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) {
|
||||
var tag [16]byte
|
||||
for i, v := range testData {
|
||||
in := v.Input()
|
||||
if unaligned {
|
||||
in = unalignBytes(in)
|
||||
}
|
||||
key := v.Key()
|
||||
sumImpl(&tag, in, &key)
|
||||
if tag != v.Tag() {
|
||||
t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBurnin(t *testing.T) {
|
||||
// This test can be used to sanity-check significant changes. It can
|
||||
// take about many minutes to run, even on fast machines. It's disabled
|
||||
// by default.
|
||||
if !*stressFlag {
|
||||
t.Skip("skipping without -stress")
|
||||
}
|
||||
|
||||
var key [32]byte
|
||||
var input [25]byte
|
||||
var output [16]byte
|
||||
|
||||
for i := range key {
|
||||
key[i] = 1
|
||||
}
|
||||
for i := range input {
|
||||
input[i] = 2
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 1e10; i++ {
|
||||
Sum(&output, input[:], &key)
|
||||
copy(key[0:], output[:])
|
||||
copy(key[16:], output[:])
|
||||
copy(input[:], output[:])
|
||||
copy(input[16:], output[:])
|
||||
}
|
||||
|
||||
const expected = "5e3b866aea0b636d240c83c428f84bfa"
|
||||
if got := hex.EncodeToString(output[:]); got != expected {
|
||||
t.Errorf("expected %s, got %s", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSum(t *testing.T) { testSum(t, false, Sum) }
|
||||
func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) }
|
||||
func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) }
|
||||
func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
|
||||
|
||||
func benchmark(b *testing.B, size int, unaligned bool) {
|
||||
var out [16]byte
|
||||
var key [32]byte
|
||||
in := make([]byte, size)
|
||||
if unaligned {
|
||||
in = unalignBytes(in)
|
||||
}
|
||||
b.SetBytes(int64(len(in)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Sum(&out, in, &key)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
|
||||
func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
|
||||
func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
|
||||
func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
|
||||
func Benchmark2M(b *testing.B) { benchmark(b, 2097152, true) }
|
||||
|
||||
func unalignBytes(in []byte) []byte {
|
||||
out := make([]byte, len(in)+1)
|
||||
if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
|
||||
out = out[1:]
|
||||
} else {
|
||||
out = out[:len(in)]
|
||||
}
|
||||
copy(out, in)
|
||||
return out
|
||||
}
|
2943
vendor/golang.org/x/crypto/poly1305/vectors_test.go
generated
vendored
2943
vendor/golang.org/x/crypto/poly1305/vectors_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
54
vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
generated
vendored
54
vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
generated
vendored
|
@ -1,54 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package salsa
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCore208(t *testing.T) {
|
||||
in := [64]byte{
|
||||
0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86,
|
||||
0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26,
|
||||
0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5,
|
||||
0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d,
|
||||
0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85,
|
||||
0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32,
|
||||
0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29,
|
||||
0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e}
|
||||
|
||||
out := [64]byte{
|
||||
0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99,
|
||||
0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05,
|
||||
0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d,
|
||||
0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29,
|
||||
0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc,
|
||||
0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba,
|
||||
0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c,
|
||||
0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81,
|
||||
}
|
||||
|
||||
Core208(&in, &in)
|
||||
if in != out {
|
||||
t.Errorf("expected %x, got %x", out, in)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutOfBoundsWrite(t *testing.T) {
|
||||
// encrypted "0123456789"
|
||||
cipherText := []byte{170, 166, 196, 104, 175, 121, 68, 44, 174, 51}
|
||||
var counter [16]byte
|
||||
var key [32]byte
|
||||
want := "abcdefghij"
|
||||
plainText := []byte(want)
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't")
|
||||
}
|
||||
if plainText[3] == '3' {
|
||||
t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText))
|
||||
}
|
||||
}()
|
||||
XORKeyStream(plainText[:3], cipherText, &counter, &key)
|
||||
}
|
58
vendor/golang.org/x/crypto/salsa20/salsa20.go
generated
vendored
58
vendor/golang.org/x/crypto/salsa20/salsa20.go
generated
vendored
|
@ -1,58 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf.
|
||||
|
||||
Salsa20 differs from many other stream ciphers in that it is message orientated
|
||||
rather than byte orientated. Keystream blocks are not preserved between calls,
|
||||
therefore each side must encrypt/decrypt data with the same segmentation.
|
||||
|
||||
Another aspect of this difference is that part of the counter is exposed as
|
||||
a nonce in each call. Encrypting two different messages with the same (key,
|
||||
nonce) pair leads to trivial plaintext recovery. This is analogous to
|
||||
encrypting two different messages with the same key with a traditional stream
|
||||
cipher.
|
||||
|
||||
This package also implements XSalsa20: a version of Salsa20 with a 24-byte
|
||||
nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply
|
||||
passing a 24-byte slice as the nonce triggers XSalsa20.
|
||||
*/
|
||||
package salsa20 // import "golang.org/x/crypto/salsa20"
|
||||
|
||||
// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20.
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/internal/subtle"
|
||||
"golang.org/x/crypto/salsa20/salsa"
|
||||
)
|
||||
|
||||
// XORKeyStream crypts bytes from in to out using the given key and nonce.
|
||||
// In and out must overlap entirely or not at all. Nonce must
|
||||
// be either 8 or 24 bytes long.
|
||||
func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) {
|
||||
if len(out) < len(in) {
|
||||
panic("salsa20: output smaller than input")
|
||||
}
|
||||
if subtle.InexactOverlap(out[:len(in)], in) {
|
||||
panic("salsa20: invalid buffer overlap")
|
||||
}
|
||||
|
||||
var subNonce [16]byte
|
||||
|
||||
if len(nonce) == 24 {
|
||||
var subKey [32]byte
|
||||
var hNonce [16]byte
|
||||
copy(hNonce[:], nonce[:16])
|
||||
salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma)
|
||||
copy(subNonce[:], nonce[16:])
|
||||
key = &subKey
|
||||
} else if len(nonce) == 8 {
|
||||
copy(subNonce[:], nonce[:])
|
||||
} else {
|
||||
panic("salsa20: nonce must be 8 or 24 bytes")
|
||||
}
|
||||
|
||||
salsa.XORKeyStream(out, in, &subNonce, key)
|
||||
}
|
139
vendor/golang.org/x/crypto/salsa20/salsa20_test.go
generated
vendored
139
vendor/golang.org/x/crypto/salsa20/salsa20_test.go
generated
vendored
|
@ -1,139 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package salsa20
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func fromHex(s string) []byte {
|
||||
ret, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// testVectors was taken from set 6 of the ECRYPT test vectors:
|
||||
// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup
|
||||
var testVectors = []struct {
|
||||
key []byte
|
||||
iv []byte
|
||||
numBytes int
|
||||
xor []byte
|
||||
}{
|
||||
{
|
||||
fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"),
|
||||
fromHex("0D74DB42A91077DE"),
|
||||
131072,
|
||||
fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"),
|
||||
},
|
||||
{
|
||||
fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"),
|
||||
fromHex("167DE44BB21980E7"),
|
||||
131072,
|
||||
fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"),
|
||||
},
|
||||
{
|
||||
fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"),
|
||||
fromHex("1F86ED54BB2289F0"),
|
||||
131072,
|
||||
fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"),
|
||||
},
|
||||
{
|
||||
fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"),
|
||||
fromHex("288FF65DC42B92F9"),
|
||||
131072,
|
||||
fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"),
|
||||
},
|
||||
}
|
||||
|
||||
func TestSalsa20(t *testing.T) {
|
||||
var inBuf, outBuf []byte
|
||||
var key [32]byte
|
||||
|
||||
for i, test := range testVectors {
|
||||
if test.numBytes%64 != 0 {
|
||||
t.Errorf("#%d: numBytes is not a multiple of 64", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if test.numBytes > len(inBuf) {
|
||||
inBuf = make([]byte, test.numBytes)
|
||||
outBuf = make([]byte, test.numBytes)
|
||||
}
|
||||
in := inBuf[:test.numBytes]
|
||||
out := outBuf[:test.numBytes]
|
||||
copy(key[:], test.key)
|
||||
XORKeyStream(out, in, test.iv, &key)
|
||||
|
||||
var xor [64]byte
|
||||
for len(out) > 0 {
|
||||
for i := 0; i < 64; i++ {
|
||||
xor[i] ^= out[i]
|
||||
}
|
||||
out = out[64:]
|
||||
}
|
||||
|
||||
if !bytes.Equal(xor[:], test.xor) {
|
||||
t.Errorf("#%d: bad result", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var xSalsa20TestData = []struct {
|
||||
in, nonce, key, out []byte
|
||||
}{
|
||||
{
|
||||
[]byte("Hello world!"),
|
||||
[]byte("24-byte nonce for xsalsa"),
|
||||
[]byte("this is 32-byte key for xsalsa20"),
|
||||
[]byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41},
|
||||
},
|
||||
{
|
||||
make([]byte, 64),
|
||||
[]byte("24-byte nonce for xsalsa"),
|
||||
[]byte("this is 32-byte key for xsalsa20"),
|
||||
[]byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6,
|
||||
0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70,
|
||||
0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf,
|
||||
0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26,
|
||||
0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40,
|
||||
0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f,
|
||||
0x3a, 0x58, 0xe4, 0x76, 0x48},
|
||||
},
|
||||
}
|
||||
|
||||
func TestXSalsa20(t *testing.T) {
|
||||
var key [32]byte
|
||||
|
||||
for i, test := range xSalsa20TestData {
|
||||
out := make([]byte, len(test.in))
|
||||
copy(key[:], test.key)
|
||||
XORKeyStream(out, test.in, test.nonce, &key)
|
||||
if !bytes.Equal(out, test.out) {
|
||||
t.Errorf("%d: expected %x, got %x", i, test.out, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
keyArray [32]byte
|
||||
key = &keyArray
|
||||
nonce [8]byte
|
||||
msg = make([]byte, 1<<10)
|
||||
)
|
||||
|
||||
func BenchmarkXOR1K(b *testing.B) {
|
||||
b.StopTimer()
|
||||
out := make([]byte, 1024)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
XORKeyStream(out, msg[:1024], nonce[:], key)
|
||||
}
|
||||
b.SetBytes(1024)
|
||||
}
|
10
vendor/golang.org/x/net/.gitattributes
generated
vendored
10
vendor/golang.org/x/net/.gitattributes
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
# Treat all files in this repo as binary, with no git magic updating
|
||||
# line endings. Windows users contributing to Go will need to use a
|
||||
# modern version of git and editors capable of LF line endings.
|
||||
#
|
||||
# We'll prevent accidental CRLF line endings from entering the repo
|
||||
# via the git-review gofmt checks.
|
||||
#
|
||||
# See golang.org/issue/9281
|
||||
|
||||
* -text
|
2
vendor/golang.org/x/net/.gitignore
generated
vendored
2
vendor/golang.org/x/net/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
# Add no patterns to .hgignore except for files generated by the build.
|
||||
last-change
|
26
vendor/golang.org/x/net/CONTRIBUTING.md
generated
vendored
26
vendor/golang.org/x/net/CONTRIBUTING.md
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
# Contributing to Go
|
||||
|
||||
Go is an open source project.
|
||||
|
||||
It is the work of hundreds of contributors. We appreciate your help!
|
||||
|
||||
## Filing issues
|
||||
|
||||
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
|
||||
|
||||
1. What version of Go are you using (`go version`)?
|
||||
2. What operating system and processor architecture are you using?
|
||||
3. What did you do?
|
||||
4. What did you expect to see?
|
||||
5. What did you see instead?
|
||||
|
||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
||||
|
||||
## Contributing code
|
||||
|
||||
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
||||
before sending patches.
|
||||
|
||||
Unless otherwise noted, the Go source files are distributed under
|
||||
the BSD-style license found in the LICENSE file.
|
16
vendor/golang.org/x/net/README.md
generated
vendored
16
vendor/golang.org/x/net/README.md
generated
vendored
|
@ -1,16 +0,0 @@
|
|||
# Go Networking
|
||||
|
||||
This repository holds supplementary Go networking libraries.
|
||||
|
||||
## Download/Install
|
||||
|
||||
The easiest way to install is to run `go get -u golang.org/x/net`. You can
|
||||
also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit
|
||||
changes to this repository, see https://golang.org/doc/contribute.html.
|
||||
The main issue tracker for the net repository is located at
|
||||
https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
|
||||
subject line, so it is easy to find.
|
525
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
525
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
|
@ -1,525 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// This is a direct translation of the program in
|
||||
// testdata/all_instructions.txt.
|
||||
var allInstructions = []Instruction{
|
||||
LoadConstant{Dst: RegA, Val: 42},
|
||||
LoadConstant{Dst: RegX, Val: 42},
|
||||
|
||||
LoadScratch{Dst: RegA, N: 3},
|
||||
LoadScratch{Dst: RegX, N: 3},
|
||||
|
||||
LoadAbsolute{Off: 42, Size: 1},
|
||||
LoadAbsolute{Off: 42, Size: 2},
|
||||
LoadAbsolute{Off: 42, Size: 4},
|
||||
|
||||
LoadIndirect{Off: 42, Size: 1},
|
||||
LoadIndirect{Off: 42, Size: 2},
|
||||
LoadIndirect{Off: 42, Size: 4},
|
||||
|
||||
LoadMemShift{Off: 42},
|
||||
|
||||
LoadExtension{Num: ExtLen},
|
||||
LoadExtension{Num: ExtProto},
|
||||
LoadExtension{Num: ExtType},
|
||||
LoadExtension{Num: ExtRand},
|
||||
|
||||
StoreScratch{Src: RegA, N: 3},
|
||||
StoreScratch{Src: RegX, N: 3},
|
||||
|
||||
ALUOpConstant{Op: ALUOpAdd, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpSub, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpMul, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpDiv, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpOr, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpAnd, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpMod, Val: 42},
|
||||
ALUOpConstant{Op: ALUOpXor, Val: 42},
|
||||
|
||||
ALUOpX{Op: ALUOpAdd},
|
||||
ALUOpX{Op: ALUOpSub},
|
||||
ALUOpX{Op: ALUOpMul},
|
||||
ALUOpX{Op: ALUOpDiv},
|
||||
ALUOpX{Op: ALUOpOr},
|
||||
ALUOpX{Op: ALUOpAnd},
|
||||
ALUOpX{Op: ALUOpShiftLeft},
|
||||
ALUOpX{Op: ALUOpShiftRight},
|
||||
ALUOpX{Op: ALUOpMod},
|
||||
ALUOpX{Op: ALUOpXor},
|
||||
|
||||
NegateA{},
|
||||
|
||||
Jump{Skip: 10},
|
||||
JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
|
||||
JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
|
||||
JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
|
||||
JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
|
||||
JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
|
||||
JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
|
||||
JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||
|
||||
TAX{},
|
||||
TXA{},
|
||||
|
||||
RetA{},
|
||||
RetConstant{Val: 42},
|
||||
}
|
||||
var allInstructionsExpected = "testdata/all_instructions.bpf"
|
||||
|
||||
// Check that we produce the same output as the canonical bpf_asm
|
||||
// linux kernel tool.
|
||||
func TestInterop(t *testing.T) {
|
||||
out, err := Assemble(allInstructions)
|
||||
if err != nil {
|
||||
t.Fatalf("assembly of allInstructions program failed: %s", err)
|
||||
}
|
||||
t.Logf("Assembled program is %d instructions long", len(out))
|
||||
|
||||
bs, err := ioutil.ReadFile(allInstructionsExpected)
|
||||
if err != nil {
|
||||
t.Fatalf("reading %s: %s", allInstructionsExpected, err)
|
||||
}
|
||||
// First statement is the number of statements, last statement is
|
||||
// empty. We just ignore both and rely on slice length.
|
||||
stmts := strings.Split(string(bs), ",")
|
||||
if len(stmts)-2 != len(out) {
|
||||
t.Fatalf("test program lengths don't match: %s has %d, Go implementation has %d", allInstructionsExpected, len(stmts)-2, len(allInstructions))
|
||||
}
|
||||
|
||||
for i, stmt := range stmts[1 : len(stmts)-2] {
|
||||
nums := strings.Split(stmt, " ")
|
||||
if len(nums) != 4 {
|
||||
t.Fatalf("malformed instruction %d in %s: %s", i+1, allInstructionsExpected, stmt)
|
||||
}
|
||||
|
||||
actual := out[i]
|
||||
|
||||
op, err := strconv.ParseUint(nums[0], 10, 16)
|
||||
if err != nil {
|
||||
t.Fatalf("malformed opcode %s in instruction %d of %s", nums[0], i+1, allInstructionsExpected)
|
||||
}
|
||||
if actual.Op != uint16(op) {
|
||||
t.Errorf("opcode mismatch on instruction %d (%#v): got 0x%02x, want 0x%02x", i+1, allInstructions[i], actual.Op, op)
|
||||
}
|
||||
|
||||
jt, err := strconv.ParseUint(nums[1], 10, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("malformed jt offset %s in instruction %d of %s", nums[1], i+1, allInstructionsExpected)
|
||||
}
|
||||
if actual.Jt != uint8(jt) {
|
||||
t.Errorf("jt mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jt, jt)
|
||||
}
|
||||
|
||||
jf, err := strconv.ParseUint(nums[2], 10, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("malformed jf offset %s in instruction %d of %s", nums[2], i+1, allInstructionsExpected)
|
||||
}
|
||||
if actual.Jf != uint8(jf) {
|
||||
t.Errorf("jf mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jf, jf)
|
||||
}
|
||||
|
||||
k, err := strconv.ParseUint(nums[3], 10, 32)
|
||||
if err != nil {
|
||||
t.Fatalf("malformed constant %s in instruction %d of %s", nums[3], i+1, allInstructionsExpected)
|
||||
}
|
||||
if actual.K != uint32(k) {
|
||||
t.Errorf("constant mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.K, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that assembly and disassembly match each other.
|
||||
func TestAsmDisasm(t *testing.T) {
|
||||
prog1, err := Assemble(allInstructions)
|
||||
if err != nil {
|
||||
t.Fatalf("assembly of allInstructions program failed: %s", err)
|
||||
}
|
||||
t.Logf("Assembled program is %d instructions long", len(prog1))
|
||||
|
||||
got, allDecoded := Disassemble(prog1)
|
||||
if !allDecoded {
|
||||
t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:")
|
||||
for i, inst := range got {
|
||||
if r, ok := inst.(RawInstruction); ok {
|
||||
t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(allInstructions) != len(got) {
|
||||
t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(allInstructions), len(got))
|
||||
}
|
||||
if !reflect.DeepEqual(allInstructions, got) {
|
||||
t.Errorf("program mutated by disassembly:")
|
||||
for i := range got {
|
||||
if !reflect.DeepEqual(allInstructions[i], got[i]) {
|
||||
t.Logf(" insn %d, s: %#v, p1: %#v, got: %#v", i+1, allInstructions[i], prog1[i], got[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type InvalidInstruction struct{}
|
||||
|
||||
func (a InvalidInstruction) Assemble() (RawInstruction, error) {
|
||||
return RawInstruction{}, fmt.Errorf("Invalid Instruction")
|
||||
}
|
||||
|
||||
func (a InvalidInstruction) String() string {
|
||||
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
instruction Instruction
|
||||
assembler string
|
||||
}{
|
||||
{
|
||||
instruction: LoadConstant{Dst: RegA, Val: 42},
|
||||
assembler: "ld #42",
|
||||
},
|
||||
{
|
||||
instruction: LoadConstant{Dst: RegX, Val: 42},
|
||||
assembler: "ldx #42",
|
||||
},
|
||||
{
|
||||
instruction: LoadConstant{Dst: 0xffff, Val: 42},
|
||||
assembler: "unknown instruction: bpf.LoadConstant{Dst:0xffff, Val:0x2a}",
|
||||
},
|
||||
{
|
||||
instruction: LoadScratch{Dst: RegA, N: 3},
|
||||
assembler: "ld M[3]",
|
||||
},
|
||||
{
|
||||
instruction: LoadScratch{Dst: RegX, N: 3},
|
||||
assembler: "ldx M[3]",
|
||||
},
|
||||
{
|
||||
instruction: LoadScratch{Dst: 0xffff, N: 3},
|
||||
assembler: "unknown instruction: bpf.LoadScratch{Dst:0xffff, N:3}",
|
||||
},
|
||||
{
|
||||
instruction: LoadAbsolute{Off: 42, Size: 1},
|
||||
assembler: "ldb [42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadAbsolute{Off: 42, Size: 2},
|
||||
assembler: "ldh [42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadAbsolute{Off: 42, Size: 4},
|
||||
assembler: "ld [42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadAbsolute{Off: 42, Size: -1},
|
||||
assembler: "unknown instruction: bpf.LoadAbsolute{Off:0x2a, Size:-1}",
|
||||
},
|
||||
{
|
||||
instruction: LoadIndirect{Off: 42, Size: 1},
|
||||
assembler: "ldb [x + 42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadIndirect{Off: 42, Size: 2},
|
||||
assembler: "ldh [x + 42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadIndirect{Off: 42, Size: 4},
|
||||
assembler: "ld [x + 42]",
|
||||
},
|
||||
{
|
||||
instruction: LoadIndirect{Off: 42, Size: -1},
|
||||
assembler: "unknown instruction: bpf.LoadIndirect{Off:0x2a, Size:-1}",
|
||||
},
|
||||
{
|
||||
instruction: LoadMemShift{Off: 42},
|
||||
assembler: "ldx 4*([42]&0xf)",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtLen},
|
||||
assembler: "ld #len",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtProto},
|
||||
assembler: "ld #proto",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtType},
|
||||
assembler: "ld #type",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtPayloadOffset},
|
||||
assembler: "ld #poff",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtInterfaceIndex},
|
||||
assembler: "ld #ifidx",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtNetlinkAttr},
|
||||
assembler: "ld #nla",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtNetlinkAttrNested},
|
||||
assembler: "ld #nlan",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtMark},
|
||||
assembler: "ld #mark",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtQueue},
|
||||
assembler: "ld #queue",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtLinkLayerType},
|
||||
assembler: "ld #hatype",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtRXHash},
|
||||
assembler: "ld #rxhash",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtCPUID},
|
||||
assembler: "ld #cpu",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtVLANTag},
|
||||
assembler: "ld #vlan_tci",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtVLANTagPresent},
|
||||
assembler: "ld #vlan_avail",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtVLANProto},
|
||||
assembler: "ld #vlan_tpid",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: ExtRand},
|
||||
assembler: "ld #rand",
|
||||
},
|
||||
{
|
||||
instruction: LoadAbsolute{Off: 0xfffff038, Size: 4},
|
||||
assembler: "ld #rand",
|
||||
},
|
||||
{
|
||||
instruction: LoadExtension{Num: 0xfff},
|
||||
assembler: "unknown instruction: bpf.LoadExtension{Num:4095}",
|
||||
},
|
||||
{
|
||||
instruction: StoreScratch{Src: RegA, N: 3},
|
||||
assembler: "st M[3]",
|
||||
},
|
||||
{
|
||||
instruction: StoreScratch{Src: RegX, N: 3},
|
||||
assembler: "stx M[3]",
|
||||
},
|
||||
{
|
||||
instruction: StoreScratch{Src: 0xffff, N: 3},
|
||||
assembler: "unknown instruction: bpf.StoreScratch{Src:0xffff, N:3}",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpAdd, Val: 42},
|
||||
assembler: "add #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpSub, Val: 42},
|
||||
assembler: "sub #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpMul, Val: 42},
|
||||
assembler: "mul #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpDiv, Val: 42},
|
||||
assembler: "div #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpOr, Val: 42},
|
||||
assembler: "or #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpAnd, Val: 42},
|
||||
assembler: "and #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
|
||||
assembler: "lsh #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
|
||||
assembler: "rsh #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpMod, Val: 42},
|
||||
assembler: "mod #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: ALUOpXor, Val: 42},
|
||||
assembler: "xor #42",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpConstant{Op: 0xffff, Val: 42},
|
||||
assembler: "unknown instruction: bpf.ALUOpConstant{Op:0xffff, Val:0x2a}",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpAdd},
|
||||
assembler: "add x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpSub},
|
||||
assembler: "sub x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpMul},
|
||||
assembler: "mul x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpDiv},
|
||||
assembler: "div x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpOr},
|
||||
assembler: "or x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpAnd},
|
||||
assembler: "and x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpShiftLeft},
|
||||
assembler: "lsh x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpShiftRight},
|
||||
assembler: "rsh x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpMod},
|
||||
assembler: "mod x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: ALUOpXor},
|
||||
assembler: "xor x",
|
||||
},
|
||||
{
|
||||
instruction: ALUOpX{Op: 0xffff},
|
||||
assembler: "unknown instruction: bpf.ALUOpX{Op:0xffff}",
|
||||
},
|
||||
{
|
||||
instruction: NegateA{},
|
||||
assembler: "neg",
|
||||
},
|
||||
{
|
||||
instruction: Jump{Skip: 10},
|
||||
assembler: "ja 10",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
|
||||
assembler: "jeq #42,8,9",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8},
|
||||
assembler: "jeq #42,8",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipFalse: 8},
|
||||
assembler: "jneq #42,8",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
|
||||
assembler: "jneq #42,8",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
|
||||
assembler: "jlt #42,7",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
|
||||
assembler: "jle #42,6",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
|
||||
assembler: "jgt #42,4,5",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4},
|
||||
assembler: "jgt #42,4",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
|
||||
assembler: "jge #42,3,4",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3},
|
||||
assembler: "jge #42,3",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||
assembler: "jset #42,2,3",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2},
|
||||
assembler: "jset #42,2",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||
assembler: "jset #42,3,2",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2},
|
||||
assembler: "jset #42,0,2",
|
||||
},
|
||||
{
|
||||
instruction: JumpIf{Cond: 0xffff, Val: 42, SkipTrue: 1, SkipFalse: 2},
|
||||
assembler: "unknown instruction: bpf.JumpIf{Cond:0xffff, Val:0x2a, SkipTrue:0x1, SkipFalse:0x2}",
|
||||
},
|
||||
{
|
||||
instruction: TAX{},
|
||||
assembler: "tax",
|
||||
},
|
||||
{
|
||||
instruction: TXA{},
|
||||
assembler: "txa",
|
||||
},
|
||||
{
|
||||
instruction: RetA{},
|
||||
assembler: "ret a",
|
||||
},
|
||||
{
|
||||
instruction: RetConstant{Val: 42},
|
||||
assembler: "ret #42",
|
||||
},
|
||||
// Invalid instruction
|
||||
{
|
||||
instruction: InvalidInstruction{},
|
||||
assembler: "unknown instruction: bpf.InvalidInstruction{}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
if input, ok := testCase.instruction.(fmt.Stringer); ok {
|
||||
got := input.String()
|
||||
if got != testCase.assembler {
|
||||
t.Errorf("String did not return expected assembler notation, expected: %s, got: %s", testCase.assembler, got)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Instruction %#v is not a fmt.Stringer", testCase.instruction)
|
||||
}
|
||||
}
|
||||
}
|
512
vendor/golang.org/x/net/bpf/vm_aluop_test.go
generated
vendored
512
vendor/golang.org/x/net/bpf/vm_aluop_test.go
generated
vendored
|
@ -1,512 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func TestVMALUOpAdd(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpAdd,
|
||||
Val: 3,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
8, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 3, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpSub(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.TAX{},
|
||||
bpf.ALUOpX{
|
||||
Op: bpf.ALUOpSub,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpMul(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpMul,
|
||||
Val: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
6, 2, 3, 4,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpDiv(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpDiv,
|
||||
Val: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
20, 2, 3, 4,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpDiv,
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "cannot divide by zero using ALUOpConstant" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpDivByZeroALUOpX(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
// Load byte 0 into X
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.TAX{},
|
||||
// Load byte 1 into A
|
||||
bpf.LoadAbsolute{
|
||||
Off: 9,
|
||||
Size: 1,
|
||||
},
|
||||
// Attempt to perform 1/0
|
||||
bpf.ALUOpX{
|
||||
Op: bpf.ALUOpDiv,
|
||||
},
|
||||
// Return 4 bytes if program does not terminate
|
||||
bpf.LoadConstant{
|
||||
Val: 12,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 3, 4,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpOr(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpOr,
|
||||
Val: 0x01,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x10, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0xff,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 9, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpAnd(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpAnd,
|
||||
Val: 0x0019,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xaa, 0x09,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpShiftLeft(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpShiftLeft,
|
||||
Val: 0x01,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 0x02,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x01, 0xaa,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpShiftRight(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpShiftRight,
|
||||
Val: 0x01,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 0x04,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x08, 0xff, 0xff,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpMod(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpMod,
|
||||
Val: 20,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
30, 0, 0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpModByZeroALUOpConstant(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpMod,
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "cannot divide by zero using ALUOpConstant" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpModByZeroALUOpX(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
// Load byte 0 into X
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.TAX{},
|
||||
// Load byte 1 into A
|
||||
bpf.LoadAbsolute{
|
||||
Off: 9,
|
||||
Size: 1,
|
||||
},
|
||||
// Attempt to perform 1%0
|
||||
bpf.ALUOpX{
|
||||
Op: bpf.ALUOpMod,
|
||||
},
|
||||
// Return 4 bytes if program does not terminate
|
||||
bpf.LoadConstant{
|
||||
Val: 12,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 3, 4,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpXor(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpXor,
|
||||
Val: 0x0a,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 0x01,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x0b, 0x00, 0x00, 0x00,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMALUOpUnknown(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.ALUOpConstant{
|
||||
Op: bpf.ALUOpAdd,
|
||||
Val: 1,
|
||||
},
|
||||
// Verify that an unknown operation is a no-op
|
||||
bpf.ALUOpConstant{
|
||||
Op: 100,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 0x02,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
192
vendor/golang.org/x/net/bpf/vm_bpf_test.go
generated
vendored
192
vendor/golang.org/x/net/bpf/vm_bpf_test.go
generated
vendored
|
@ -1,192 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// A virtualMachine is a BPF virtual machine which can process an
|
||||
// input packet against a BPF program and render a verdict.
|
||||
type virtualMachine interface {
|
||||
Run(in []byte) (int, error)
|
||||
}
|
||||
|
||||
// canUseOSVM indicates if the OS BPF VM is available on this platform.
|
||||
func canUseOSVM() bool {
|
||||
// OS BPF VM can only be used on platforms where x/net/ipv4 supports
|
||||
// attaching a BPF program to a socket.
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// All BPF tests against both the Go VM and OS VM are assumed to
|
||||
// be used with a UDP socket. As a result, the entire contents
|
||||
// of a UDP datagram is sent through the BPF program, but only
|
||||
// the body after the UDP header will ever be returned in output.
|
||||
|
||||
// testVM sets up a Go BPF VM, and if available, a native OS BPF VM
|
||||
// for integration testing.
|
||||
func testVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func(), error) {
|
||||
goVM, err := bpf.NewVM(filter)
|
||||
if err != nil {
|
||||
// Some tests expect an error, so this error must be returned
|
||||
// instead of fatally exiting the test
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
mvm := &multiVirtualMachine{
|
||||
goVM: goVM,
|
||||
|
||||
t: t,
|
||||
}
|
||||
|
||||
// If available, add the OS VM for tests which verify that both the Go
|
||||
// VM and OS VM have exactly the same output for the same input program
|
||||
// and packet.
|
||||
done := func() {}
|
||||
if canUseOSVM() {
|
||||
osVM, osVMDone := testOSVM(t, filter)
|
||||
done = func() { osVMDone() }
|
||||
mvm.osVM = osVM
|
||||
}
|
||||
|
||||
return mvm, done, nil
|
||||
}
|
||||
|
||||
// udpHeaderLen is the length of a UDP header.
|
||||
const udpHeaderLen = 8
|
||||
|
||||
// A multiVirtualMachine is a virtualMachine which can call out to both the Go VM
|
||||
// and the native OS VM, if the OS VM is available.
|
||||
type multiVirtualMachine struct {
|
||||
goVM virtualMachine
|
||||
osVM virtualMachine
|
||||
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (mvm *multiVirtualMachine) Run(in []byte) (int, error) {
|
||||
if len(in) < udpHeaderLen {
|
||||
mvm.t.Fatalf("input must be at least length of UDP header (%d), got: %d",
|
||||
udpHeaderLen, len(in))
|
||||
}
|
||||
|
||||
// All tests have a UDP header as part of input, because the OS VM
|
||||
// packets always will. For the Go VM, this output is trimmed before
|
||||
// being sent back to tests.
|
||||
goOut, goErr := mvm.goVM.Run(in)
|
||||
if goOut >= udpHeaderLen {
|
||||
goOut -= udpHeaderLen
|
||||
}
|
||||
|
||||
// If Go output is larger than the size of the packet, packet filtering
|
||||
// interop tests must trim the output bytes to the length of the packet.
|
||||
// The BPF VM should not do this on its own, as other uses of it do
|
||||
// not trim the output byte count.
|
||||
trim := len(in) - udpHeaderLen
|
||||
if goOut > trim {
|
||||
goOut = trim
|
||||
}
|
||||
|
||||
// When the OS VM is not available, process using the Go VM alone
|
||||
if mvm.osVM == nil {
|
||||
return goOut, goErr
|
||||
}
|
||||
|
||||
// The OS VM will apply its own UDP header, so remove the pseudo header
|
||||
// that the Go VM needs.
|
||||
osOut, err := mvm.osVM.Run(in[udpHeaderLen:])
|
||||
if err != nil {
|
||||
mvm.t.Fatalf("error while running OS VM: %v", err)
|
||||
}
|
||||
|
||||
// Verify both VMs return same number of bytes
|
||||
var mismatch bool
|
||||
if goOut != osOut {
|
||||
mismatch = true
|
||||
mvm.t.Logf("output byte count does not match:\n- go: %v\n- os: %v", goOut, osOut)
|
||||
}
|
||||
|
||||
if mismatch {
|
||||
mvm.t.Fatal("Go BPF and OS BPF packet outputs do not match")
|
||||
}
|
||||
|
||||
return goOut, goErr
|
||||
}
|
||||
|
||||
// An osVirtualMachine is a virtualMachine which uses the OS's BPF VM for
|
||||
// processing BPF programs.
|
||||
type osVirtualMachine struct {
|
||||
l net.PacketConn
|
||||
s net.Conn
|
||||
}
|
||||
|
||||
// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting
|
||||
// packets into a UDP listener with a BPF program attached to it.
|
||||
func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
|
||||
l, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open OS VM UDP listener: %v", err)
|
||||
}
|
||||
|
||||
prog, err := bpf.Assemble(filter)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to compile BPF program: %v", err)
|
||||
}
|
||||
|
||||
p := ipv4.NewPacketConn(l)
|
||||
if err = p.SetBPF(prog); err != nil {
|
||||
t.Fatalf("failed to attach BPF program to listener: %v", err)
|
||||
}
|
||||
|
||||
s, err := net.Dial("udp4", l.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to dial connection to listener: %v", err)
|
||||
}
|
||||
|
||||
done := func() {
|
||||
_ = s.Close()
|
||||
_ = l.Close()
|
||||
}
|
||||
|
||||
return &osVirtualMachine{
|
||||
l: l,
|
||||
s: s,
|
||||
}, done
|
||||
}
|
||||
|
||||
// Run sends the input bytes into the OS's BPF VM and returns its verdict.
|
||||
func (vm *osVirtualMachine) Run(in []byte) (int, error) {
|
||||
go func() {
|
||||
_, _ = vm.s.Write(in)
|
||||
}()
|
||||
|
||||
vm.l.SetDeadline(time.Now().Add(50 * time.Millisecond))
|
||||
|
||||
var b [512]byte
|
||||
n, _, err := vm.l.ReadFrom(b[:])
|
||||
if err != nil {
|
||||
// A timeout indicates that BPF filtered out the packet, and thus,
|
||||
// no input should be returned.
|
||||
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
49
vendor/golang.org/x/net/bpf/vm_extension_test.go
generated
vendored
49
vendor/golang.org/x/net/bpf/vm_extension_test.go
generated
vendored
|
@ -1,49 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func TestVMLoadExtensionNotImplemented(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadExtension{
|
||||
Num: 100,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "extension 100 not implemented" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadExtensionExtLen(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadExtension{
|
||||
Num: bpf.ExtLen,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
380
vendor/golang.org/x/net/bpf/vm_jump_test.go
generated
vendored
380
vendor/golang.org/x/net/bpf/vm_jump_test.go
generated
vendored
|
@ -1,380 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func TestVMJumpOne(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.Jump{
|
||||
Skip: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpOutOfProgram(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.Jump{
|
||||
Skip: 1,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "cannot jump 1 instructions; jumping past program bounds" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfTrueOutOfProgram(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
SkipTrue: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfFalseOutOfProgram(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
SkipFalse: 3,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfEqual(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 1,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfNotEqual(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpNotEqual,
|
||||
Val: 1,
|
||||
SkipFalse: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfGreaterThan(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 4,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpGreaterThan,
|
||||
Val: 0x00010202,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 12,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfLessThan(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 4,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpLessThan,
|
||||
Val: 0xff010203,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 12,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfGreaterOrEqual(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 4,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpGreaterOrEqual,
|
||||
Val: 0x00010203,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 12,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfLessOrEqual(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 4,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpLessOrEqual,
|
||||
Val: 0xff010203,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 12,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 4, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfBitsSet(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpBitsSet,
|
||||
Val: 0x1122,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 10,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x01, 0x02,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMJumpIfBitsNotSet(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpBitsNotSet,
|
||||
Val: 0x1221,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
bpf.RetConstant{
|
||||
Val: 10,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x01, 0x02,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
246
vendor/golang.org/x/net/bpf/vm_load_test.go
generated
vendored
246
vendor/golang.org/x/net/bpf/vm_load_test.go
generated
vendored
|
@ -1,246 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 100,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Size: 5,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid load byte length 0" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadConstantOK(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadConstant{
|
||||
Dst: bpf.RegX,
|
||||
Val: 9,
|
||||
},
|
||||
bpf.TXA{},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadIndirectOutOfBounds(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadIndirect{
|
||||
Off: 100,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadMemShiftOutOfBounds(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadMemShift{
|
||||
Off: 100,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
dhcp4Port = 53
|
||||
)
|
||||
|
||||
func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) {
|
||||
vm, in, done := testDHCPv4(t)
|
||||
defer done()
|
||||
|
||||
// Append mostly empty UDP header with incorrect DHCPv4 port
|
||||
in = append(in, []byte{
|
||||
0, 0,
|
||||
0, dhcp4Port + 1,
|
||||
0, 0,
|
||||
0, 0,
|
||||
}...)
|
||||
|
||||
out, err := vm.Run(in)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 0, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) {
|
||||
vm, in, done := testDHCPv4(t)
|
||||
defer done()
|
||||
|
||||
// Append mostly empty UDP header with correct DHCPv4 port
|
||||
in = append(in, []byte{
|
||||
0, 0,
|
||||
0, dhcp4Port,
|
||||
0, 0,
|
||||
0, 0,
|
||||
}...)
|
||||
|
||||
out, err := vm.Run(in)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := len(in)-8, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) {
|
||||
// DHCPv4 test data courtesy of David Anderson:
|
||||
// https://github.com/google/netboot/blob/master/dhcp4/conn_linux.go#L59-L70
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
// Load IPv4 packet length
|
||||
bpf.LoadMemShift{Off: 8},
|
||||
// Get UDP dport
|
||||
bpf.LoadIndirect{Off: 8 + 2, Size: 2},
|
||||
// Correct dport?
|
||||
bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1},
|
||||
// Accept
|
||||
bpf.RetConstant{Val: 1500},
|
||||
// Ignore
|
||||
bpf.RetConstant{Val: 0},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
|
||||
// Minimal requirements to make a valid IPv4 header
|
||||
h := &ipv4.Header{
|
||||
Len: ipv4.HeaderLen,
|
||||
Src: net.IPv4(192, 168, 1, 1),
|
||||
Dst: net.IPv4(192, 168, 1, 2),
|
||||
}
|
||||
hb, err := h.Marshal()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal IPv4 header: %v", err)
|
||||
}
|
||||
|
||||
hb = append([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
}, hb...)
|
||||
|
||||
return vm, hb, done
|
||||
}
|
115
vendor/golang.org/x/net/bpf/vm_ret_test.go
generated
vendored
115
vendor/golang.org/x/net/bpf/vm_ret_test.go
generated
vendored
|
@ -1,115 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func TestVMRetA(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
9,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMRetALargerThanInput(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 2,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 255,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMRetConstant(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.RetConstant{
|
||||
Val: 9,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 1, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMRetConstantLargerThanInput(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.RetConstant{
|
||||
Val: 16,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0, 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
247
vendor/golang.org/x/net/bpf/vm_scratch_test.go
generated
vendored
247
vendor/golang.org/x/net/bpf/vm_scratch_test.go
generated
vendored
|
@ -1,247 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: -1,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: 16,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMStoreScratchUnknownSourceRegister(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.StoreScratch{
|
||||
Src: 100,
|
||||
N: 0,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid source register 100" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegX,
|
||||
N: -1,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegX,
|
||||
N: 16,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadScratch{
|
||||
Dst: 100,
|
||||
N: 0,
|
||||
},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if errStr(err) != "assembling instruction 1: invalid target register 100" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMStoreScratchLoadScratchOneValue(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
// Load byte 255
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
// Copy to X and store in scratch[0]
|
||||
bpf.TAX{},
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegX,
|
||||
N: 0,
|
||||
},
|
||||
// Load byte 1
|
||||
bpf.LoadAbsolute{
|
||||
Off: 9,
|
||||
Size: 1,
|
||||
},
|
||||
// Overwrite 1 with 255 from scratch[0]
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegA,
|
||||
N: 0,
|
||||
},
|
||||
// Return 255
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
255, 1, 2,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 3, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
// Load byte 10
|
||||
bpf.LoadAbsolute{
|
||||
Off: 8,
|
||||
Size: 1,
|
||||
},
|
||||
// Store in scratch[0]
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: 0,
|
||||
},
|
||||
// Load byte 20
|
||||
bpf.LoadAbsolute{
|
||||
Off: 9,
|
||||
Size: 1,
|
||||
},
|
||||
// Store in scratch[1]
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: 1,
|
||||
},
|
||||
// Load byte 30
|
||||
bpf.LoadAbsolute{
|
||||
Off: 10,
|
||||
Size: 1,
|
||||
},
|
||||
// Store in scratch[2]
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: 2,
|
||||
},
|
||||
// Load byte 1
|
||||
bpf.LoadAbsolute{
|
||||
Off: 11,
|
||||
Size: 1,
|
||||
},
|
||||
// Store in scratch[3]
|
||||
bpf.StoreScratch{
|
||||
Src: bpf.RegA,
|
||||
N: 3,
|
||||
},
|
||||
// Load in byte 10 to X
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegX,
|
||||
N: 0,
|
||||
},
|
||||
// Copy X -> A
|
||||
bpf.TXA{},
|
||||
// Verify value is 10
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 10,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
// Fail test if incorrect
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
// Load in byte 20 to A
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegA,
|
||||
N: 1,
|
||||
},
|
||||
// Verify value is 20
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 20,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
// Fail test if incorrect
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
// Load in byte 30 to A
|
||||
bpf.LoadScratch{
|
||||
Dst: bpf.RegA,
|
||||
N: 2,
|
||||
},
|
||||
// Verify value is 30
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: 30,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
// Fail test if incorrect
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
// Return first two bytes on success
|
||||
bpf.RetConstant{
|
||||
Val: 10,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load BPF program: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
out, err := vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
10, 20, 30, 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
if want, got := 2, out; want != got {
|
||||
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||
want, got)
|
||||
}
|
||||
}
|
144
vendor/golang.org/x/net/bpf/vm_test.go
generated
vendored
144
vendor/golang.org/x/net/bpf/vm_test.go
generated
vendored
|
@ -1,144 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bpf_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
var _ bpf.Instruction = unknown{}
|
||||
|
||||
type unknown struct{}
|
||||
|
||||
func (unknown) Assemble() (bpf.RawInstruction, error) {
|
||||
return bpf.RawInstruction{}, nil
|
||||
}
|
||||
|
||||
func TestVMUnknownInstruction(t *testing.T) {
|
||||
vm, done, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadConstant{
|
||||
Dst: bpf.RegA,
|
||||
Val: 100,
|
||||
},
|
||||
// Should terminate the program with an error immediately
|
||||
unknown{},
|
||||
bpf.RetA{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer done()
|
||||
|
||||
_, err = vm.Run([]byte{
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00,
|
||||
})
|
||||
if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" {
|
||||
t.Fatalf("unexpected error while running program: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMNoReturnInstruction(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{
|
||||
bpf.LoadConstant{
|
||||
Dst: bpf.RegA,
|
||||
Val: 1,
|
||||
},
|
||||
})
|
||||
if errStr(err) != "BPF program must end with RetA or RetConstant" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMNoInputInstructions(t *testing.T) {
|
||||
_, _, err := testVM(t, []bpf.Instruction{})
|
||||
if errStr(err) != "one or more Instructions must be specified" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ExampleNewVM demonstrates usage of a VM, using an Ethernet frame
|
||||
// as input and checking its EtherType to determine if it should be accepted.
|
||||
func ExampleNewVM() {
|
||||
// Offset | Length | Comment
|
||||
// -------------------------
|
||||
// 00 | 06 | Ethernet destination MAC address
|
||||
// 06 | 06 | Ethernet source MAC address
|
||||
// 12 | 02 | Ethernet EtherType
|
||||
const (
|
||||
etOff = 12
|
||||
etLen = 2
|
||||
|
||||
etARP = 0x0806
|
||||
)
|
||||
|
||||
// Set up a VM to filter traffic based on if its EtherType
|
||||
// matches the ARP EtherType.
|
||||
vm, err := bpf.NewVM([]bpf.Instruction{
|
||||
// Load EtherType value from Ethernet header
|
||||
bpf.LoadAbsolute{
|
||||
Off: etOff,
|
||||
Size: etLen,
|
||||
},
|
||||
// If EtherType is equal to the ARP EtherType, jump to allow
|
||||
// packet to be accepted
|
||||
bpf.JumpIf{
|
||||
Cond: bpf.JumpEqual,
|
||||
Val: etARP,
|
||||
SkipTrue: 1,
|
||||
},
|
||||
// EtherType does not match the ARP EtherType
|
||||
bpf.RetConstant{
|
||||
Val: 0,
|
||||
},
|
||||
// EtherType matches the ARP EtherType, accept up to 1500
|
||||
// bytes of packet
|
||||
bpf.RetConstant{
|
||||
Val: 1500,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to load BPF program: %v", err))
|
||||
}
|
||||
|
||||
// Create an Ethernet frame with the ARP EtherType for testing
|
||||
frame := []byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
|
||||
0x08, 0x06,
|
||||
// Payload omitted for brevity
|
||||
}
|
||||
|
||||
// Run our VM's BPF program using the Ethernet frame as input
|
||||
out, err := vm.Run(frame)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err))
|
||||
}
|
||||
|
||||
// BPF VM can return a byte count greater than the number of input
|
||||
// bytes, so trim the output to match the input byte length
|
||||
if out > len(frame) {
|
||||
out = len(frame)
|
||||
}
|
||||
|
||||
fmt.Printf("out: %d bytes", out)
|
||||
|
||||
// Output:
|
||||
// out: 14 bytes
|
||||
}
|
||||
|
||||
// errStr returns the string representation of an error, or
|
||||
// "<nil>" if it is nil.
|
||||
func errStr(err error) string {
|
||||
if err == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
return err.Error()
|
||||
}
|
1
vendor/golang.org/x/net/codereview.cfg
generated
vendored
1
vendor/golang.org/x/net/codereview.cfg
generated
vendored
|
@ -1 +0,0 @@
|
|||
issuerepo: golang/go
|
119
vendor/golang.org/x/net/http/httpguts/httplex_test.go
generated
vendored
119
vendor/golang.org/x/net/http/httpguts/httplex_test.go
generated
vendored
|
@ -1,119 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package httpguts
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func isChar(c rune) bool { return c <= 127 }
|
||||
|
||||
func isCtl(c rune) bool { return c <= 31 || c == 127 }
|
||||
|
||||
func isSeparator(c rune) bool {
|
||||
switch c {
|
||||
case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestIsToken(t *testing.T) {
|
||||
for i := 0; i <= 130; i++ {
|
||||
r := rune(i)
|
||||
expected := isChar(r) && !isCtl(r) && !isSeparator(r)
|
||||
if IsTokenRune(r) != expected {
|
||||
t.Errorf("isToken(0x%x) = %v", r, !expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderValuesContainsToken(t *testing.T) {
|
||||
tests := []struct {
|
||||
vals []string
|
||||
token string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
vals: []string{"foo"},
|
||||
token: "foo",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"bar", "foo"},
|
||||
token: "foo",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"foo"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"foo"},
|
||||
token: "bar",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
vals: []string{" foo "},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"foo,bar"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"bar,foo,bar"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"bar , foo"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"foo ,bar "},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"bar, foo ,bar"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
vals: []string{"bar , foo"},
|
||||
token: "FOO",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got := HeaderValuesContainsToken(tt.vals, tt.token)
|
||||
if got != tt.want {
|
||||
t.Errorf("headerValuesContainsToken(%q, %q) = %v; want %v", tt.vals, tt.token, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPunycodeHostPort(t *testing.T) {
|
||||
tests := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"www.google.com", "www.google.com"},
|
||||
{"гофер.рф", "xn--c1ae0ajs.xn--p1ai"},
|
||||
{"bücher.de", "xn--bcher-kva.de"},
|
||||
{"bücher.de:8080", "xn--bcher-kva.de:8080"},
|
||||
{"[1::6]:8080", "[1::6]:8080"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got, err := PunycodeHostPort(tt.in)
|
||||
if tt.want != got || err != nil {
|
||||
t.Errorf("PunycodeHostPort(%q) = %q, %v, want %q, nil", tt.in, got, err, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
309
vendor/golang.org/x/net/http2/ciphers_test.go
generated
vendored
309
vendor/golang.org/x/net/http2/ciphers_test.go
generated
vendored
|
@ -1,309 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsBadCipherBad(t *testing.T) {
|
||||
for _, c := range badCiphers {
|
||||
if !isBadCipher(c) {
|
||||
t.Errorf("Wrong result for isBadCipher(%d), want true", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// verify we don't give false positives on ciphers not on blacklist
|
||||
func TestIsBadCipherGood(t *testing.T) {
|
||||
goodCiphers := map[uint16]string{
|
||||
cipher_TLS_DHE_RSA_WITH_AES_256_CCM: "cipher_TLS_DHE_RSA_WITH_AES_256_CCM",
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM: "cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
|
||||
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: "cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||
}
|
||||
for c, name := range goodCiphers {
|
||||
if isBadCipher(c) {
|
||||
t.Errorf("Wrong result for isBadCipher(%d) %s, want false", c, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copied from https://http2.github.io/http2-spec/#BadCipherSuites,
|
||||
var badCiphers = []uint16{
|
||||
cipher_TLS_NULL_WITH_NULL_NULL,
|
||||
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||
cipher_TLS_PSK_WITH_AES_256_CCM_8,
|
||||
}
|
28
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
28
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
|
@ -52,9 +52,31 @@ const (
|
|||
noDialOnMiss = false
|
||||
)
|
||||
|
||||
// shouldTraceGetConn reports whether getClientConn should call any
|
||||
// ClientTrace.GetConn hook associated with the http.Request.
|
||||
//
|
||||
// This complexity is needed to avoid double calls of the GetConn hook
|
||||
// during the back-and-forth between net/http and x/net/http2 (when the
|
||||
// net/http.Transport is upgraded to also speak http2), as well as support
|
||||
// the case where x/net/http2 is being used directly.
|
||||
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
|
||||
// If our Transport wasn't made via ConfigureTransport, always
|
||||
// trace the GetConn hook if provided, because that means the
|
||||
// http2 package is being used directly and it's the one
|
||||
// dialing, as opposed to net/http.
|
||||
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
|
||||
return true
|
||||
}
|
||||
// Otherwise, only use the GetConn hook if this connection has
|
||||
// been used previously for other requests. For fresh
|
||||
// connections, the net/http package does the dialing.
|
||||
return !st.freshConn
|
||||
}
|
||||
|
||||
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
||||
if isConnectionCloseRequest(req) && dialOnMiss {
|
||||
// It gets its own connection.
|
||||
traceGetConn(req, addr)
|
||||
const singleUse = true
|
||||
cc, err := p.t.dialClientConn(addr, singleUse)
|
||||
if err != nil {
|
||||
|
@ -64,7 +86,10 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
|||
}
|
||||
p.mu.Lock()
|
||||
for _, cc := range p.conns[addr] {
|
||||
if cc.CanTakeNewRequest() {
|
||||
if st := cc.idleState(); st.canTakeNewRequest {
|
||||
if p.shouldTraceGetConn(st) {
|
||||
traceGetConn(req, addr)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
return cc, nil
|
||||
}
|
||||
|
@ -73,6 +98,7 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
|||
p.mu.Unlock()
|
||||
return nil, ErrNoCachedConn
|
||||
}
|
||||
traceGetConn(req, addr)
|
||||
call := p.getStartDialLocked(addr)
|
||||
p.mu.Unlock()
|
||||
<-call.done
|
||||
|
|
8
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
8
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
|
@ -57,7 +57,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
|
|||
|
||||
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
||||
// converting panics into errors.
|
||||
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
||||
func registerHTTPSProtocol(t *http.Transport, rt noDialH2RoundTripper) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("%v", e)
|
||||
|
@ -69,10 +69,12 @@ func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error)
|
|||
|
||||
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
|
||||
// if there's already has a cached connection to the host.
|
||||
type noDialH2RoundTripper struct{ t *Transport }
|
||||
// (The field is exported so it can be accessed via reflect from net/http; tested
|
||||
// by TestNoDialH2RoundTripperType)
|
||||
type noDialH2RoundTripper struct{ *Transport }
|
||||
|
||||
func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
res, err := rt.t.RoundTrip(req)
|
||||
res, err := rt.Transport.RoundTrip(req)
|
||||
if isNoCachedConnError(err) {
|
||||
return nil, http.ErrSkipAltProtocol
|
||||
}
|
||||
|
|
157
vendor/golang.org/x/net/http2/databuffer_test.go
generated
vendored
157
vendor/golang.org/x/net/http2/databuffer_test.go
generated
vendored
|
@ -1,157 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func fmtDataChunk(chunk []byte) string {
|
||||
out := ""
|
||||
var last byte
|
||||
var count int
|
||||
for _, c := range chunk {
|
||||
if c != last {
|
||||
if count > 0 {
|
||||
out += fmt.Sprintf(" x %d ", count)
|
||||
count = 0
|
||||
}
|
||||
out += string([]byte{c})
|
||||
last = c
|
||||
}
|
||||
count++
|
||||
}
|
||||
if count > 0 {
|
||||
out += fmt.Sprintf(" x %d", count)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func fmtDataChunks(chunks [][]byte) string {
|
||||
var out string
|
||||
for _, chunk := range chunks {
|
||||
out += fmt.Sprintf("{%q}", fmtDataChunk(chunk))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) {
|
||||
// Run setup, then read the remaining bytes from the dataBuffer and check
|
||||
// that they match wantBytes. We use different read sizes to check corner
|
||||
// cases in Read.
|
||||
for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} {
|
||||
t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) {
|
||||
b := setup(t)
|
||||
buf := make([]byte, readSize)
|
||||
var gotRead bytes.Buffer
|
||||
for {
|
||||
n, err := b.Read(buf)
|
||||
gotRead.Write(buf[:n])
|
||||
if err == errReadEmpty {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("error after %v bytes: %v", gotRead.Len(), err)
|
||||
}
|
||||
}
|
||||
if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) {
|
||||
t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDataBufferAllocation(t *testing.T) {
|
||||
writes := [][]byte{
|
||||
bytes.Repeat([]byte("a"), 1*1024-1),
|
||||
[]byte("a"),
|
||||
bytes.Repeat([]byte("b"), 4*1024-1),
|
||||
[]byte("b"),
|
||||
bytes.Repeat([]byte("c"), 8*1024-1),
|
||||
[]byte("c"),
|
||||
bytes.Repeat([]byte("d"), 16*1024-1),
|
||||
[]byte("d"),
|
||||
bytes.Repeat([]byte("e"), 32*1024),
|
||||
}
|
||||
var wantRead bytes.Buffer
|
||||
for _, p := range writes {
|
||||
wantRead.Write(p)
|
||||
}
|
||||
|
||||
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
|
||||
b := &dataBuffer{}
|
||||
for _, p := range writes {
|
||||
if n, err := b.Write(p); n != len(p) || err != nil {
|
||||
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
|
||||
}
|
||||
}
|
||||
want := [][]byte{
|
||||
bytes.Repeat([]byte("a"), 1*1024),
|
||||
bytes.Repeat([]byte("b"), 4*1024),
|
||||
bytes.Repeat([]byte("c"), 8*1024),
|
||||
bytes.Repeat([]byte("d"), 16*1024),
|
||||
bytes.Repeat([]byte("e"), 16*1024),
|
||||
bytes.Repeat([]byte("e"), 16*1024),
|
||||
}
|
||||
if !reflect.DeepEqual(b.chunks, want) {
|
||||
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
|
||||
}
|
||||
return b
|
||||
})
|
||||
}
|
||||
|
||||
func TestDataBufferAllocationWithExpected(t *testing.T) {
|
||||
writes := [][]byte{
|
||||
bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB
|
||||
bytes.Repeat([]byte("b"), 14*1024),
|
||||
bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more
|
||||
bytes.Repeat([]byte("d"), 2*1024),
|
||||
bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB
|
||||
}
|
||||
var wantRead bytes.Buffer
|
||||
for _, p := range writes {
|
||||
wantRead.Write(p)
|
||||
}
|
||||
|
||||
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
|
||||
b := &dataBuffer{expected: 32 * 1024}
|
||||
for _, p := range writes {
|
||||
if n, err := b.Write(p); n != len(p) || err != nil {
|
||||
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
|
||||
}
|
||||
}
|
||||
want := [][]byte{
|
||||
append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...),
|
||||
append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...),
|
||||
bytes.Repeat([]byte("e"), 1*1024),
|
||||
}
|
||||
if !reflect.DeepEqual(b.chunks, want) {
|
||||
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
|
||||
}
|
||||
return b
|
||||
})
|
||||
}
|
||||
|
||||
func TestDataBufferWriteAfterPartialRead(t *testing.T) {
|
||||
testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer {
|
||||
b := &dataBuffer{}
|
||||
if n, err := b.Write([]byte("abcd")); n != 4 || err != nil {
|
||||
t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err)
|
||||
}
|
||||
p := make([]byte, 2)
|
||||
if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) {
|
||||
t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err)
|
||||
}
|
||||
if n, err := b.Write([]byte("xyz")); n != 3 || err != nil {
|
||||
t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err)
|
||||
}
|
||||
return b
|
||||
})
|
||||
}
|
24
vendor/golang.org/x/net/http2/errors_test.go
generated
vendored
24
vendor/golang.org/x/net/http2/errors_test.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestErrCodeString(t *testing.T) {
|
||||
tests := []struct {
|
||||
err ErrCode
|
||||
want string
|
||||
}{
|
||||
{ErrCodeProtocol, "PROTOCOL_ERROR"},
|
||||
{0xd, "HTTP_1_1_REQUIRED"},
|
||||
{0xf, "unknown error code 0xf"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
got := tt.err.String()
|
||||
if got != tt.want {
|
||||
t.Errorf("%d. Error = %q; want %q", i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
87
vendor/golang.org/x/net/http2/flow_test.go
generated
vendored
87
vendor/golang.org/x/net/http2/flow_test.go
generated
vendored
|
@ -1,87 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFlow(t *testing.T) {
|
||||
var st flow
|
||||
var conn flow
|
||||
st.add(3)
|
||||
conn.add(2)
|
||||
|
||||
if got, want := st.available(), int32(3); got != want {
|
||||
t.Errorf("available = %d; want %d", got, want)
|
||||
}
|
||||
st.setConnFlow(&conn)
|
||||
if got, want := st.available(), int32(2); got != want {
|
||||
t.Errorf("after parent setup, available = %d; want %d", got, want)
|
||||
}
|
||||
|
||||
st.take(2)
|
||||
if got, want := conn.available(), int32(0); got != want {
|
||||
t.Errorf("after taking 2, conn = %d; want %d", got, want)
|
||||
}
|
||||
if got, want := st.available(), int32(0); got != want {
|
||||
t.Errorf("after taking 2, stream = %d; want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlowAdd(t *testing.T) {
|
||||
var f flow
|
||||
if !f.add(1) {
|
||||
t.Fatal("failed to add 1")
|
||||
}
|
||||
if !f.add(-1) {
|
||||
t.Fatal("failed to add -1")
|
||||
}
|
||||
if got, want := f.available(), int32(0); got != want {
|
||||
t.Fatalf("size = %d; want %d", got, want)
|
||||
}
|
||||
if !f.add(1<<31 - 1) {
|
||||
t.Fatal("failed to add 2^31-1")
|
||||
}
|
||||
if got, want := f.available(), int32(1<<31-1); got != want {
|
||||
t.Fatalf("size = %d; want %d", got, want)
|
||||
}
|
||||
if f.add(1) {
|
||||
t.Fatal("adding 1 to max shouldn't be allowed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlowAddOverflow(t *testing.T) {
|
||||
var f flow
|
||||
if !f.add(0) {
|
||||
t.Fatal("failed to add 0")
|
||||
}
|
||||
if !f.add(-1) {
|
||||
t.Fatal("failed to add -1")
|
||||
}
|
||||
if !f.add(0) {
|
||||
t.Fatal("failed to add 0")
|
||||
}
|
||||
if !f.add(1) {
|
||||
t.Fatal("failed to add 1")
|
||||
}
|
||||
if !f.add(1) {
|
||||
t.Fatal("failed to add 1")
|
||||
}
|
||||
if !f.add(0) {
|
||||
t.Fatal("failed to add 0")
|
||||
}
|
||||
if !f.add(-3) {
|
||||
t.Fatal("failed to add -3")
|
||||
}
|
||||
if got, want := f.available(), int32(-2); got != want {
|
||||
t.Fatalf("size = %d; want %d", got, want)
|
||||
}
|
||||
if !f.add(1<<31 - 1) {
|
||||
t.Fatal("failed to add 2^31-1")
|
||||
}
|
||||
if got, want := f.available(), int32(1+-3+(1<<31-1)); got != want {
|
||||
t.Fatalf("size = %d; want %d", got, want)
|
||||
}
|
||||
|
||||
}
|
63
vendor/golang.org/x/net/http2/frame.go
generated
vendored
63
vendor/golang.org/x/net/http2/frame.go
generated
vendored
|
@ -733,32 +733,67 @@ func (f *SettingsFrame) IsAck() bool {
|
|||
return f.FrameHeader.Flags.Has(FlagSettingsAck)
|
||||
}
|
||||
|
||||
func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
|
||||
func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
|
||||
f.checkValid()
|
||||
buf := f.p
|
||||
for len(buf) > 0 {
|
||||
settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
|
||||
if settingID == s {
|
||||
return binary.BigEndian.Uint32(buf[2:6]), true
|
||||
for i := 0; i < f.NumSettings(); i++ {
|
||||
if s := f.Setting(i); s.ID == id {
|
||||
return s.Val, true
|
||||
}
|
||||
buf = buf[6:]
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Setting returns the setting from the frame at the given 0-based index.
|
||||
// The index must be >= 0 and less than f.NumSettings().
|
||||
func (f *SettingsFrame) Setting(i int) Setting {
|
||||
buf := f.p
|
||||
return Setting{
|
||||
ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
|
||||
Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
|
||||
|
||||
// HasDuplicates reports whether f contains any duplicate setting IDs.
|
||||
func (f *SettingsFrame) HasDuplicates() bool {
|
||||
num := f.NumSettings()
|
||||
if num == 0 {
|
||||
return false
|
||||
}
|
||||
// If it's small enough (the common case), just do the n^2
|
||||
// thing and avoid a map allocation.
|
||||
if num < 10 {
|
||||
for i := 0; i < num; i++ {
|
||||
idi := f.Setting(i).ID
|
||||
for j := i + 1; j < num; j++ {
|
||||
idj := f.Setting(j).ID
|
||||
if idi == idj {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
seen := map[SettingID]bool{}
|
||||
for i := 0; i < num; i++ {
|
||||
id := f.Setting(i).ID
|
||||
if seen[id] {
|
||||
return true
|
||||
}
|
||||
seen[id] = true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ForeachSetting runs fn for each setting.
|
||||
// It stops and returns the first error.
|
||||
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
|
||||
f.checkValid()
|
||||
buf := f.p
|
||||
for len(buf) > 0 {
|
||||
if err := fn(Setting{
|
||||
SettingID(binary.BigEndian.Uint16(buf[:2])),
|
||||
binary.BigEndian.Uint32(buf[2:6]),
|
||||
}); err != nil {
|
||||
for i := 0; i < f.NumSettings(); i++ {
|
||||
if err := fn(f.Setting(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
buf = buf[6:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
1191
vendor/golang.org/x/net/http2/frame_test.go
generated
vendored
1191
vendor/golang.org/x/net/http2/frame_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
26
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.11
|
||||
|
||||
package http2
|
||||
|
||||
import "net/textproto"
|
||||
|
||||
func traceHasWroteHeaderField(trace *clientTrace) bool {
|
||||
return trace != nil && trace.WroteHeaderField != nil
|
||||
}
|
||||
|
||||
func traceWroteHeaderField(trace *clientTrace, k, v string) {
|
||||
if trace != nil && trace.WroteHeaderField != nil {
|
||||
trace.WroteHeaderField(k, []string{v})
|
||||
}
|
||||
}
|
||||
|
||||
func traceGot1xxResponseFunc(trace *clientTrace) func(int, textproto.MIMEHeader) error {
|
||||
if trace != nil {
|
||||
return trace.Got1xxResponse
|
||||
}
|
||||
return nil
|
||||
}
|
15
vendor/golang.org/x/net/http2/go17.go
generated
vendored
15
vendor/golang.org/x/net/http2/go17.go
generated
vendored
|
@ -18,6 +18,8 @@ type contextContext interface {
|
|||
context.Context
|
||||
}
|
||||
|
||||
var errCanceled = context.Canceled
|
||||
|
||||
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
|
||||
|
@ -48,6 +50,14 @@ func (t *Transport) idleConnTimeout() time.Duration {
|
|||
|
||||
func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
|
||||
|
||||
func traceGetConn(req *http.Request, hostPort string) {
|
||||
trace := httptrace.ContextClientTrace(req.Context())
|
||||
if trace == nil || trace.GetConn == nil {
|
||||
return
|
||||
}
|
||||
trace.GetConn(hostPort)
|
||||
}
|
||||
|
||||
func traceGotConn(req *http.Request, cc *ClientConn) {
|
||||
trace := httptrace.ContextClientTrace(req.Context())
|
||||
if trace == nil || trace.GotConn == nil {
|
||||
|
@ -104,3 +114,8 @@ func requestTrace(req *http.Request) *clientTrace {
|
|||
func (cc *ClientConn) Ping(ctx context.Context) error {
|
||||
return cc.ping(ctx)
|
||||
}
|
||||
|
||||
// Shutdown gracefully closes the client connection, waiting for running streams to complete.
|
||||
func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
||||
return cc.shutdown(ctx)
|
||||
}
|
||||
|
|
79
vendor/golang.org/x/net/http2/go18_test.go
generated
vendored
79
vendor/golang.org/x/net/http2/go18_test.go
generated
vendored
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Tests that http2.Server.IdleTimeout is initialized from
|
||||
// http.Server.{Idle,Read}Timeout. http.Server.IdleTimeout was
|
||||
// added in Go 1.8.
|
||||
func TestConfigureServerIdleTimeout_Go18(t *testing.T) {
|
||||
const timeout = 5 * time.Second
|
||||
const notThisOne = 1 * time.Second
|
||||
|
||||
// With a zero http2.Server, verify that it copies IdleTimeout:
|
||||
{
|
||||
s1 := &http.Server{
|
||||
IdleTimeout: timeout,
|
||||
ReadTimeout: notThisOne,
|
||||
}
|
||||
s2 := &Server{}
|
||||
if err := ConfigureServer(s1, s2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s2.IdleTimeout != timeout {
|
||||
t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
// And that it falls back to ReadTimeout:
|
||||
{
|
||||
s1 := &http.Server{
|
||||
ReadTimeout: timeout,
|
||||
}
|
||||
s2 := &Server{}
|
||||
if err := ConfigureServer(s1, s2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s2.IdleTimeout != timeout {
|
||||
t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that s1's IdleTimeout doesn't overwrite an existing setting:
|
||||
{
|
||||
s1 := &http.Server{
|
||||
IdleTimeout: notThisOne,
|
||||
}
|
||||
s2 := &Server{
|
||||
IdleTimeout: timeout,
|
||||
}
|
||||
if err := ConfigureServer(s1, s2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s2.IdleTimeout != timeout {
|
||||
t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertClone(t *testing.T) {
|
||||
c := &tls.Config{
|
||||
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
panic("shouldn't be called")
|
||||
},
|
||||
}
|
||||
c2 := cloneTLSConfig(c)
|
||||
if c2.GetClientCertificate == nil {
|
||||
t.Error("GetClientCertificate is nil")
|
||||
}
|
||||
}
|
59
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
59
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
|
@ -1,59 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServerGracefulShutdown(t *testing.T) {
|
||||
var st *serverTester
|
||||
handlerDone := make(chan struct{})
|
||||
st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(handlerDone)
|
||||
go st.ts.Config.Shutdown(context.Background())
|
||||
|
||||
ga := st.wantGoAway()
|
||||
if ga.ErrCode != ErrCodeNo {
|
||||
t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
|
||||
}
|
||||
if ga.LastStreamID != 1 {
|
||||
t.Errorf("GOAWAY LastStreamID = %v; want 1", ga.LastStreamID)
|
||||
}
|
||||
|
||||
w.Header().Set("x-foo", "bar")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
st.greet()
|
||||
st.bodylessReq1()
|
||||
|
||||
select {
|
||||
case <-handlerDone:
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("server did not shutdown?")
|
||||
}
|
||||
hf := st.wantHeaders()
|
||||
goth := st.decodeHeader(hf.HeaderBlockFragment())
|
||||
wanth := [][2]string{
|
||||
{":status", "200"},
|
||||
{"x-foo", "bar"},
|
||||
{"content-length", "0"},
|
||||
}
|
||||
if !reflect.DeepEqual(goth, wanth) {
|
||||
t.Errorf("Got headers %v; want %v", goth, wanth)
|
||||
}
|
||||
|
||||
n, err := st.cc.Read([]byte{0})
|
||||
if n != 0 || err == nil {
|
||||
t.Errorf("Read = %v, %v; want 0, non-nil", n, err)
|
||||
}
|
||||
}
|
33
vendor/golang.org/x/net/http2/gotrack_test.go
generated
vendored
33
vendor/golang.org/x/net/http2/gotrack_test.go
generated
vendored
|
@ -1,33 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGoroutineLock(t *testing.T) {
|
||||
oldDebug := DebugGoroutines
|
||||
DebugGoroutines = true
|
||||
defer func() { DebugGoroutines = oldDebug }()
|
||||
|
||||
g := newGoroutineLock()
|
||||
g.check()
|
||||
|
||||
sawPanic := make(chan interface{})
|
||||
go func() {
|
||||
defer func() { sawPanic <- recover() }()
|
||||
g.check() // should panic
|
||||
}()
|
||||
e := <-sawPanic
|
||||
if e == nil {
|
||||
t.Fatal("did not see panic from check in other goroutine")
|
||||
}
|
||||
if !strings.Contains(fmt.Sprint(e), "wrong goroutine") {
|
||||
t.Errorf("expected on see panic about running on the wrong goroutine; got %v", e)
|
||||
}
|
||||
}
|
386
vendor/golang.org/x/net/http2/hpack/encode_test.go
generated
vendored
386
vendor/golang.org/x/net/http2/hpack/encode_test.go
generated
vendored
|
@ -1,386 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEncoderTableSizeUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
size1, size2 uint32
|
||||
wantHex string
|
||||
}{
|
||||
// Should emit 2 table size updates (2048 and 4096)
|
||||
{2048, 4096, "3fe10f 3fe11f 82"},
|
||||
|
||||
// Should emit 1 table size update (2048)
|
||||
{16384, 2048, "3fe10f 82"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
var buf bytes.Buffer
|
||||
e := NewEncoder(&buf)
|
||||
e.SetMaxDynamicTableSize(tt.size1)
|
||||
e.SetMaxDynamicTableSize(tt.size2)
|
||||
if err := e.WriteField(pair(":method", "GET")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := removeSpace(tt.wantHex)
|
||||
if got := hex.EncodeToString(buf.Bytes()); got != want {
|
||||
t.Errorf("e.SetDynamicTableSize %v, %v = %q; want %q", tt.size1, tt.size2, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoderWriteField(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
e := NewEncoder(&buf)
|
||||
var got []HeaderField
|
||||
d := NewDecoder(4<<10, func(f HeaderField) {
|
||||
got = append(got, f)
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
hdrs []HeaderField
|
||||
}{
|
||||
{[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
}},
|
||||
{[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("cache-control", "no-cache"),
|
||||
}},
|
||||
{[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "https"),
|
||||
pair(":path", "/index.html"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("custom-key", "custom-value"),
|
||||
}},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
buf.Reset()
|
||||
got = got[:0]
|
||||
for _, hf := range tt.hdrs {
|
||||
if err := e.WriteField(hf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
_, err := d.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
t.Errorf("%d. Decoder Write = %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.hdrs) {
|
||||
t.Errorf("%d. Decoded %+v; want %+v", i, got, tt.hdrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoderSearchTable(t *testing.T) {
|
||||
e := NewEncoder(nil)
|
||||
|
||||
e.dynTab.add(pair("foo", "bar"))
|
||||
e.dynTab.add(pair("blake", "miz"))
|
||||
e.dynTab.add(pair(":method", "GET"))
|
||||
|
||||
tests := []struct {
|
||||
hf HeaderField
|
||||
wantI uint64
|
||||
wantMatch bool
|
||||
}{
|
||||
// Name and Value match
|
||||
{pair("foo", "bar"), uint64(staticTable.len()) + 3, true},
|
||||
{pair("blake", "miz"), uint64(staticTable.len()) + 2, true},
|
||||
{pair(":method", "GET"), 2, true},
|
||||
|
||||
// Only name match because Sensitive == true. This is allowed to match
|
||||
// any ":method" entry. The current implementation uses the last entry
|
||||
// added in newStaticTable.
|
||||
{HeaderField{":method", "GET", true}, 3, false},
|
||||
|
||||
// Only Name matches
|
||||
{pair("foo", "..."), uint64(staticTable.len()) + 3, false},
|
||||
{pair("blake", "..."), uint64(staticTable.len()) + 2, false},
|
||||
// As before, this is allowed to match any ":method" entry.
|
||||
{pair(":method", "..."), 3, false},
|
||||
|
||||
// None match
|
||||
{pair("foo-", "bar"), 0, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if gotI, gotMatch := e.searchTable(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
|
||||
t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendVarInt(t *testing.T) {
|
||||
tests := []struct {
|
||||
n byte
|
||||
i uint64
|
||||
want []byte
|
||||
}{
|
||||
// Fits in a byte:
|
||||
{1, 0, []byte{0}},
|
||||
{2, 2, []byte{2}},
|
||||
{3, 6, []byte{6}},
|
||||
{4, 14, []byte{14}},
|
||||
{5, 30, []byte{30}},
|
||||
{6, 62, []byte{62}},
|
||||
{7, 126, []byte{126}},
|
||||
{8, 254, []byte{254}},
|
||||
|
||||
// Multiple bytes:
|
||||
{5, 1337, []byte{31, 154, 10}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got := appendVarInt(nil, tt.n, tt.i)
|
||||
if !bytes.Equal(got, tt.want) {
|
||||
t.Errorf("appendVarInt(nil, %v, %v) = %v; want %v", tt.n, tt.i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendHpackString(t *testing.T) {
|
||||
tests := []struct {
|
||||
s, wantHex string
|
||||
}{
|
||||
// Huffman encoded
|
||||
{"www.example.com", "8c f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
|
||||
|
||||
// Not Huffman encoded
|
||||
{"a", "01 61"},
|
||||
|
||||
// zero length
|
||||
{"", "00"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
want := removeSpace(tt.wantHex)
|
||||
buf := appendHpackString(nil, tt.s)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("appendHpackString(nil, %q) = %q; want %q", tt.s, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendIndexed(t *testing.T) {
|
||||
tests := []struct {
|
||||
i uint64
|
||||
wantHex string
|
||||
}{
|
||||
// 1 byte
|
||||
{1, "81"},
|
||||
{126, "fe"},
|
||||
|
||||
// 2 bytes
|
||||
{127, "ff00"},
|
||||
{128, "ff01"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
want := removeSpace(tt.wantHex)
|
||||
buf := appendIndexed(nil, tt.i)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("appendIndex(nil, %v) = %q; want %q", tt.i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendNewName(t *testing.T) {
|
||||
tests := []struct {
|
||||
f HeaderField
|
||||
indexing bool
|
||||
wantHex string
|
||||
}{
|
||||
// Incremental indexing
|
||||
{HeaderField{"custom-key", "custom-value", false}, true, "40 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
|
||||
|
||||
// Without indexing
|
||||
{HeaderField{"custom-key", "custom-value", false}, false, "00 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
|
||||
|
||||
// Never indexed
|
||||
{HeaderField{"custom-key", "custom-value", true}, true, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
|
||||
{HeaderField{"custom-key", "custom-value", true}, false, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
want := removeSpace(tt.wantHex)
|
||||
buf := appendNewName(nil, tt.f, tt.indexing)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("appendNewName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendIndexedName(t *testing.T) {
|
||||
tests := []struct {
|
||||
f HeaderField
|
||||
i uint64
|
||||
indexing bool
|
||||
wantHex string
|
||||
}{
|
||||
// Incremental indexing
|
||||
{HeaderField{":status", "302", false}, 8, true, "48 82 6402"},
|
||||
|
||||
// Without indexing
|
||||
{HeaderField{":status", "302", false}, 8, false, "08 82 6402"},
|
||||
|
||||
// Never indexed
|
||||
{HeaderField{":status", "302", true}, 8, true, "18 82 6402"},
|
||||
{HeaderField{":status", "302", true}, 8, false, "18 82 6402"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
want := removeSpace(tt.wantHex)
|
||||
buf := appendIndexedName(nil, tt.f, tt.i, tt.indexing)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("appendIndexedName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTableSize(t *testing.T) {
|
||||
tests := []struct {
|
||||
i uint32
|
||||
wantHex string
|
||||
}{
|
||||
// Fits into 1 byte
|
||||
{30, "3e"},
|
||||
|
||||
// Extra byte
|
||||
{31, "3f00"},
|
||||
{32, "3f01"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
want := removeSpace(tt.wantHex)
|
||||
buf := appendTableSize(nil, tt.i)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("appendTableSize(nil, %v) = %q; want %q", tt.i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoderSetMaxDynamicTableSize(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
e := NewEncoder(&buf)
|
||||
tests := []struct {
|
||||
v uint32
|
||||
wantUpdate bool
|
||||
wantMinSize uint32
|
||||
wantMaxSize uint32
|
||||
}{
|
||||
// Set new table size to 2048
|
||||
{2048, true, 2048, 2048},
|
||||
|
||||
// Set new table size to 16384, but still limited to
|
||||
// 4096
|
||||
{16384, true, 2048, 4096},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
e.SetMaxDynamicTableSize(tt.v)
|
||||
if got := e.tableSizeUpdate; tt.wantUpdate != got {
|
||||
t.Errorf("e.tableSizeUpdate = %v; want %v", got, tt.wantUpdate)
|
||||
}
|
||||
if got := e.minSize; tt.wantMinSize != got {
|
||||
t.Errorf("e.minSize = %v; want %v", got, tt.wantMinSize)
|
||||
}
|
||||
if got := e.dynTab.maxSize; tt.wantMaxSize != got {
|
||||
t.Errorf("e.maxSize = %v; want %v", got, tt.wantMaxSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) {
|
||||
e := NewEncoder(nil)
|
||||
// 4095 < initialHeaderTableSize means maxSize is truncated to
|
||||
// 4095.
|
||||
e.SetMaxDynamicTableSizeLimit(4095)
|
||||
if got, want := e.dynTab.maxSize, uint32(4095); got != want {
|
||||
t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
|
||||
}
|
||||
if got, want := e.maxSizeLimit, uint32(4095); got != want {
|
||||
t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
|
||||
}
|
||||
if got, want := e.tableSizeUpdate, true; got != want {
|
||||
t.Errorf("e.tableSizeUpdate = %v; want %v", got, want)
|
||||
}
|
||||
// maxSize will be truncated to maxSizeLimit
|
||||
e.SetMaxDynamicTableSize(16384)
|
||||
if got, want := e.dynTab.maxSize, uint32(4095); got != want {
|
||||
t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
|
||||
}
|
||||
// 8192 > current maxSizeLimit, so maxSize does not change.
|
||||
e.SetMaxDynamicTableSizeLimit(8192)
|
||||
if got, want := e.dynTab.maxSize, uint32(4095); got != want {
|
||||
t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
|
||||
}
|
||||
if got, want := e.maxSizeLimit, uint32(8192); got != want {
|
||||
t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func removeSpace(s string) string {
|
||||
return strings.Replace(s, " ", "", -1)
|
||||
}
|
||||
|
||||
func BenchmarkEncoderSearchTable(b *testing.B) {
|
||||
e := NewEncoder(nil)
|
||||
|
||||
// A sample of possible header fields.
|
||||
// This is not based on any actual data from HTTP/2 traces.
|
||||
var possible []HeaderField
|
||||
for _, f := range staticTable.ents {
|
||||
if f.Value == "" {
|
||||
possible = append(possible, f)
|
||||
continue
|
||||
}
|
||||
// Generate 5 random values, except for cookie and set-cookie,
|
||||
// which we know can have many values in practice.
|
||||
num := 5
|
||||
if f.Name == "cookie" || f.Name == "set-cookie" {
|
||||
num = 25
|
||||
}
|
||||
for i := 0; i < num; i++ {
|
||||
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
|
||||
possible = append(possible, f)
|
||||
}
|
||||
}
|
||||
for k := 0; k < 10; k++ {
|
||||
f := HeaderField{
|
||||
Name: fmt.Sprintf("x-header-%d", k),
|
||||
Sensitive: rand.Int()%2 == 0,
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
|
||||
possible = append(possible, f)
|
||||
}
|
||||
}
|
||||
|
||||
// Add a random sample to the dynamic table. This very loosely simulates
|
||||
// a history of 100 requests with 20 header fields per request.
|
||||
for r := 0; r < 100*20; r++ {
|
||||
f := possible[rand.Int31n(int32(len(possible)))]
|
||||
// Skip if this is in the staticTable verbatim.
|
||||
if _, has := staticTable.search(f); !has {
|
||||
e.dynTab.add(f)
|
||||
}
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
for _, f := range possible {
|
||||
e.searchTable(f)
|
||||
}
|
||||
}
|
||||
}
|
741
vendor/golang.org/x/net/http2/hpack/hpack_test.go
generated
vendored
741
vendor/golang.org/x/net/http2/hpack/hpack_test.go
generated
vendored
|
@ -1,741 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (d *Decoder) mustAt(idx int) HeaderField {
|
||||
if hf, ok := d.at(uint64(idx)); !ok {
|
||||
panic(fmt.Sprintf("bogus index %d", idx))
|
||||
} else {
|
||||
return hf
|
||||
}
|
||||
}
|
||||
|
||||
func TestDynamicTableAt(t *testing.T) {
|
||||
d := NewDecoder(4096, nil)
|
||||
at := d.mustAt
|
||||
if got, want := at(2), (pair(":method", "GET")); got != want {
|
||||
t.Errorf("at(2) = %v; want %v", got, want)
|
||||
}
|
||||
d.dynTab.add(pair("foo", "bar"))
|
||||
d.dynTab.add(pair("blake", "miz"))
|
||||
if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
|
||||
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
||||
}
|
||||
if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
|
||||
t.Errorf("at(dyn 2) = %v; want %v", got, want)
|
||||
}
|
||||
if got, want := at(3), (pair(":method", "POST")); got != want {
|
||||
t.Errorf("at(3) = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDynamicTableSizeEvict(t *testing.T) {
|
||||
d := NewDecoder(4096, nil)
|
||||
if want := uint32(0); d.dynTab.size != want {
|
||||
t.Fatalf("size = %d; want %d", d.dynTab.size, want)
|
||||
}
|
||||
add := d.dynTab.add
|
||||
add(pair("blake", "eats pizza"))
|
||||
if want := uint32(15 + 32); d.dynTab.size != want {
|
||||
t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want)
|
||||
}
|
||||
add(pair("foo", "bar"))
|
||||
if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want {
|
||||
t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want)
|
||||
}
|
||||
d.dynTab.setMaxSize(15 + 32 + 1 /* slop */)
|
||||
if want := uint32(6 + 32); d.dynTab.size != want {
|
||||
t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
|
||||
}
|
||||
if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
|
||||
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
||||
}
|
||||
add(pair("long", strings.Repeat("x", 500)))
|
||||
if want := uint32(0); d.dynTab.size != want {
|
||||
t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoderDecode(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in []byte
|
||||
want []HeaderField
|
||||
wantDynTab []HeaderField // newest entry first
|
||||
}{
|
||||
// C.2.1 Literal Header Field with Indexing
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.1
|
||||
{"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"),
|
||||
[]HeaderField{pair("custom-key", "custom-header")},
|
||||
[]HeaderField{pair("custom-key", "custom-header")},
|
||||
},
|
||||
|
||||
// C.2.2 Literal Header Field without Indexing
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.2
|
||||
{"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"),
|
||||
[]HeaderField{pair(":path", "/sample/path")},
|
||||
[]HeaderField{}},
|
||||
|
||||
// C.2.3 Literal Header Field never Indexed
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.3
|
||||
{"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"),
|
||||
[]HeaderField{{"password", "secret", true}},
|
||||
[]HeaderField{}},
|
||||
|
||||
// C.2.4 Indexed Header Field
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.4
|
||||
{"C.2.4", []byte("\x82"),
|
||||
[]HeaderField{pair(":method", "GET")},
|
||||
[]HeaderField{}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
d := NewDecoder(4096, nil)
|
||||
hf, err := d.DecodeFull(tt.in)
|
||||
if err != nil {
|
||||
t.Errorf("%s: %v", tt.name, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(hf, tt.want) {
|
||||
t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want)
|
||||
}
|
||||
gotDynTab := d.dynTab.reverseCopy()
|
||||
if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) {
|
||||
t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
|
||||
hf = make([]HeaderField, len(dt.table.ents))
|
||||
for i := range hf {
|
||||
hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type encAndWant struct {
|
||||
enc []byte
|
||||
want []HeaderField
|
||||
wantDynTab []HeaderField
|
||||
wantDynSize uint32
|
||||
}
|
||||
|
||||
// C.3 Request Examples without Huffman Coding
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.3
|
||||
func TestDecodeC3_NoHuffman(t *testing.T) {
|
||||
testDecodeSeries(t, 4096, []encAndWant{
|
||||
{dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
57,
|
||||
},
|
||||
{dehex("8286 84be 5808 6e6f 2d63 6163 6865"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("cache-control", "no-cache"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("cache-control", "no-cache"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
110,
|
||||
},
|
||||
{dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "https"),
|
||||
pair(":path", "/index.html"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("custom-key", "custom-value"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("custom-key", "custom-value"),
|
||||
pair("cache-control", "no-cache"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
164,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// C.4 Request Examples with Huffman Coding
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.4
|
||||
func TestDecodeC4_Huffman(t *testing.T) {
|
||||
testDecodeSeries(t, 4096, []encAndWant{
|
||||
{dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
57,
|
||||
},
|
||||
{dehex("8286 84be 5886 a8eb 1064 9cbf"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "http"),
|
||||
pair(":path", "/"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("cache-control", "no-cache"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("cache-control", "no-cache"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
110,
|
||||
},
|
||||
{dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"),
|
||||
[]HeaderField{
|
||||
pair(":method", "GET"),
|
||||
pair(":scheme", "https"),
|
||||
pair(":path", "/index.html"),
|
||||
pair(":authority", "www.example.com"),
|
||||
pair("custom-key", "custom-value"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("custom-key", "custom-value"),
|
||||
pair("cache-control", "no-cache"),
|
||||
pair(":authority", "www.example.com"),
|
||||
},
|
||||
164,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.5
|
||||
// "This section shows several consecutive header lists, corresponding
|
||||
// to HTTP responses, on the same connection. The HTTP/2 setting
|
||||
// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
|
||||
// octets, causing some evictions to occur."
|
||||
func TestDecodeC5_ResponsesNoHuff(t *testing.T) {
|
||||
testDecodeSeries(t, 256, []encAndWant{
|
||||
{dehex(`
|
||||
4803 3330 3258 0770 7269 7661 7465 611d
|
||||
4d6f 6e2c 2032 3120 4f63 7420 3230 3133
|
||||
2032 303a 3133 3a32 3120 474d 546e 1768
|
||||
7474 7073 3a2f 2f77 7777 2e65 7861 6d70
|
||||
6c65 2e63 6f6d
|
||||
`),
|
||||
[]HeaderField{
|
||||
pair(":status", "302"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("cache-control", "private"),
|
||||
pair(":status", "302"),
|
||||
},
|
||||
222,
|
||||
},
|
||||
{dehex("4803 3330 37c1 c0bf"),
|
||||
[]HeaderField{
|
||||
pair(":status", "307"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair(":status", "307"),
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("cache-control", "private"),
|
||||
},
|
||||
222,
|
||||
},
|
||||
{dehex(`
|
||||
88c1 611d 4d6f 6e2c 2032 3120 4f63 7420
|
||||
3230 3133 2032 303a 3133 3a32 3220 474d
|
||||
54c0 5a04 677a 6970 7738 666f 6f3d 4153
|
||||
444a 4b48 514b 425a 584f 5157 454f 5049
|
||||
5541 5851 5745 4f49 553b 206d 6178 2d61
|
||||
6765 3d33 3630 303b 2076 6572 7369 6f6e
|
||||
3d31
|
||||
`),
|
||||
[]HeaderField{
|
||||
pair(":status", "200"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("content-encoding", "gzip"),
|
||||
pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
|
||||
pair("content-encoding", "gzip"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
|
||||
},
|
||||
215,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.C.6
|
||||
// "This section shows the same examples as the previous section, but
|
||||
// using Huffman encoding for the literal values. The HTTP/2 setting
|
||||
// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
|
||||
// octets, causing some evictions to occur. The eviction mechanism
|
||||
// uses the length of the decoded literal values, so the same
|
||||
// evictions occurs as in the previous section."
|
||||
func TestDecodeC6_ResponsesHuffman(t *testing.T) {
|
||||
testDecodeSeries(t, 256, []encAndWant{
|
||||
{dehex(`
|
||||
4882 6402 5885 aec3 771a 4b61 96d0 7abe
|
||||
9410 54d4 44a8 2005 9504 0b81 66e0 82a6
|
||||
2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8
|
||||
e9ae 82ae 43d3
|
||||
`),
|
||||
[]HeaderField{
|
||||
pair(":status", "302"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("cache-control", "private"),
|
||||
pair(":status", "302"),
|
||||
},
|
||||
222,
|
||||
},
|
||||
{dehex("4883 640e ffc1 c0bf"),
|
||||
[]HeaderField{
|
||||
pair(":status", "307"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair(":status", "307"),
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
|
||||
pair("cache-control", "private"),
|
||||
},
|
||||
222,
|
||||
},
|
||||
{dehex(`
|
||||
88c1 6196 d07a be94 1054 d444 a820 0595
|
||||
040b 8166 e084 a62d 1bff c05a 839b d9ab
|
||||
77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b
|
||||
3960 d5af 2708 7f36 72c1 ab27 0fb5 291f
|
||||
9587 3160 65c0 03ed 4ee5 b106 3d50 07
|
||||
`),
|
||||
[]HeaderField{
|
||||
pair(":status", "200"),
|
||||
pair("cache-control", "private"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
|
||||
pair("location", "https://www.example.com"),
|
||||
pair("content-encoding", "gzip"),
|
||||
pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
|
||||
},
|
||||
[]HeaderField{
|
||||
pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
|
||||
pair("content-encoding", "gzip"),
|
||||
pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
|
||||
},
|
||||
215,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) {
|
||||
d := NewDecoder(size, nil)
|
||||
for i, step := range steps {
|
||||
hf, err := d.DecodeFull(step.enc)
|
||||
if err != nil {
|
||||
t.Fatalf("Error at step index %d: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(hf, step.want) {
|
||||
t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want)
|
||||
}
|
||||
gotDynTab := d.dynTab.reverseCopy()
|
||||
if !reflect.DeepEqual(gotDynTab, step.wantDynTab) {
|
||||
t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab)
|
||||
}
|
||||
if d.dynTab.size != step.wantDynSize {
|
||||
t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanDecodeExcessPadding(t *testing.T) {
|
||||
tests := [][]byte{
|
||||
{0xff}, // Padding Exceeds 7 bits
|
||||
{0x1f, 0xff}, // {"a", 1 byte excess padding}
|
||||
{0x1f, 0xff, 0xff}, // {"a", 2 byte excess padding}
|
||||
{0x1f, 0xff, 0xff, 0xff}, // {"a", 3 byte excess padding}
|
||||
{0xff, 0x9f, 0xff, 0xff, 0xff}, // {"a", 29 bit excess padding}
|
||||
{'R', 0xbc, '0', 0xff, 0xff, 0xff, 0xff}, // Padding ends on partial symbol.
|
||||
}
|
||||
for i, in := range tests {
|
||||
var buf bytes.Buffer
|
||||
if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
|
||||
t.Errorf("test-%d: decode(%q) = %v; want ErrInvalidHuffman", i, in, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanDecodeEOS(t *testing.T) {
|
||||
in := []byte{0xff, 0xff, 0xff, 0xff, 0xfc} // {EOS, "?"}
|
||||
var buf bytes.Buffer
|
||||
if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
|
||||
t.Errorf("error = %v; want ErrInvalidHuffman", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanDecodeMaxLengthOnTrailingByte(t *testing.T) {
|
||||
in := []byte{0x00, 0x01} // {"0", "0", "0"}
|
||||
var buf bytes.Buffer
|
||||
if err := huffmanDecode(&buf, 2, in); err != ErrStringLength {
|
||||
t.Errorf("error = %v; want ErrStringLength", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanDecodeCorruptPadding(t *testing.T) {
|
||||
in := []byte{0x00}
|
||||
var buf bytes.Buffer
|
||||
if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
|
||||
t.Errorf("error = %v; want ErrInvalidHuffman", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanDecode(t *testing.T) {
|
||||
tests := []struct {
|
||||
inHex, want string
|
||||
}{
|
||||
{"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"},
|
||||
{"a8eb 1064 9cbf", "no-cache"},
|
||||
{"25a8 49e9 5ba9 7d7f", "custom-key"},
|
||||
{"25a8 49e9 5bb8 e8b4 bf", "custom-value"},
|
||||
{"6402", "302"},
|
||||
{"aec3 771a 4b", "private"},
|
||||
{"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"},
|
||||
{"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"},
|
||||
{"9bd9 ab", "gzip"},
|
||||
{"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
|
||||
"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
var buf bytes.Buffer
|
||||
in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1))
|
||||
if err != nil {
|
||||
t.Errorf("%d. hex input error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if _, err := HuffmanDecode(&buf, in); err != nil {
|
||||
t.Errorf("%d. decode error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if got := buf.String(); tt.want != got {
|
||||
t.Errorf("%d. decode = %q; want %q", i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendHuffmanString(t *testing.T) {
|
||||
tests := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
|
||||
{"no-cache", "a8eb 1064 9cbf"},
|
||||
{"custom-key", "25a8 49e9 5ba9 7d7f"},
|
||||
{"custom-value", "25a8 49e9 5bb8 e8b4 bf"},
|
||||
{"302", "6402"},
|
||||
{"private", "aec3 771a 4b"},
|
||||
{"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"},
|
||||
{"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"},
|
||||
{"gzip", "9bd9 ab"},
|
||||
{"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
|
||||
"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
buf := []byte{}
|
||||
want := strings.Replace(tt.want, " ", "", -1)
|
||||
buf = AppendHuffmanString(buf, tt.in)
|
||||
if got := hex.EncodeToString(buf); want != got {
|
||||
t.Errorf("%d. encode = %q; want %q", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanMaxStrLen(t *testing.T) {
|
||||
const msg = "Some string"
|
||||
huff := AppendHuffmanString(nil, msg)
|
||||
|
||||
testGood := func(max int) {
|
||||
var out bytes.Buffer
|
||||
if err := huffmanDecode(&out, max, huff); err != nil {
|
||||
t.Errorf("For maxLen=%d, unexpected error: %v", max, err)
|
||||
}
|
||||
if out.String() != msg {
|
||||
t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg)
|
||||
}
|
||||
}
|
||||
testGood(0)
|
||||
testGood(len(msg))
|
||||
testGood(len(msg) + 1)
|
||||
|
||||
var out bytes.Buffer
|
||||
if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength {
|
||||
t.Errorf("err = %v; want ErrStringLength", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHuffmanRoundtripStress(t *testing.T) {
|
||||
const Len = 50 // of uncompressed string
|
||||
input := make([]byte, Len)
|
||||
var output bytes.Buffer
|
||||
var huff []byte
|
||||
|
||||
n := 5000
|
||||
if testing.Short() {
|
||||
n = 100
|
||||
}
|
||||
seed := time.Now().UnixNano()
|
||||
t.Logf("Seed = %v", seed)
|
||||
src := rand.New(rand.NewSource(seed))
|
||||
var encSize int64
|
||||
for i := 0; i < n; i++ {
|
||||
for l := range input {
|
||||
input[l] = byte(src.Intn(256))
|
||||
}
|
||||
huff = AppendHuffmanString(huff[:0], string(input))
|
||||
encSize += int64(len(huff))
|
||||
output.Reset()
|
||||
if err := huffmanDecode(&output, 0, huff); err != nil {
|
||||
t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(output.Bytes(), input) {
|
||||
t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes())
|
||||
}
|
||||
}
|
||||
t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize)
|
||||
}
|
||||
|
||||
func TestHuffmanDecodeFuzz(t *testing.T) {
|
||||
const Len = 50 // of compressed
|
||||
var buf, zbuf bytes.Buffer
|
||||
|
||||
n := 5000
|
||||
if testing.Short() {
|
||||
n = 100
|
||||
}
|
||||
seed := time.Now().UnixNano()
|
||||
t.Logf("Seed = %v", seed)
|
||||
src := rand.New(rand.NewSource(seed))
|
||||
numFail := 0
|
||||
for i := 0; i < n; i++ {
|
||||
zbuf.Reset()
|
||||
if i == 0 {
|
||||
// Start with at least one invalid one.
|
||||
zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8")
|
||||
} else {
|
||||
for l := 0; l < Len; l++ {
|
||||
zbuf.WriteByte(byte(src.Intn(256)))
|
||||
}
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil {
|
||||
if err == ErrInvalidHuffman {
|
||||
numFail++
|
||||
continue
|
||||
}
|
||||
t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n)
|
||||
if numFail < 1 {
|
||||
t.Error("expected at least one invalid huffman encoding (test starts with one)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadVarInt(t *testing.T) {
|
||||
type res struct {
|
||||
i uint64
|
||||
consumed int
|
||||
err error
|
||||
}
|
||||
tests := []struct {
|
||||
n byte
|
||||
p []byte
|
||||
want res
|
||||
}{
|
||||
// Fits in a byte:
|
||||
{1, []byte{0}, res{0, 1, nil}},
|
||||
{2, []byte{2}, res{2, 1, nil}},
|
||||
{3, []byte{6}, res{6, 1, nil}},
|
||||
{4, []byte{14}, res{14, 1, nil}},
|
||||
{5, []byte{30}, res{30, 1, nil}},
|
||||
{6, []byte{62}, res{62, 1, nil}},
|
||||
{7, []byte{126}, res{126, 1, nil}},
|
||||
{8, []byte{254}, res{254, 1, nil}},
|
||||
|
||||
// Doesn't fit in a byte:
|
||||
{1, []byte{1}, res{0, 0, errNeedMore}},
|
||||
{2, []byte{3}, res{0, 0, errNeedMore}},
|
||||
{3, []byte{7}, res{0, 0, errNeedMore}},
|
||||
{4, []byte{15}, res{0, 0, errNeedMore}},
|
||||
{5, []byte{31}, res{0, 0, errNeedMore}},
|
||||
{6, []byte{63}, res{0, 0, errNeedMore}},
|
||||
{7, []byte{127}, res{0, 0, errNeedMore}},
|
||||
{8, []byte{255}, res{0, 0, errNeedMore}},
|
||||
|
||||
// Ignoring top bits:
|
||||
{5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111
|
||||
{5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100
|
||||
{5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101
|
||||
|
||||
// Extra byte:
|
||||
{5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte
|
||||
|
||||
// Short a byte:
|
||||
{5, []byte{191, 154}, res{0, 0, errNeedMore}},
|
||||
|
||||
// integer overflow:
|
||||
{1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
i, remain, err := readVarInt(tt.n, tt.p)
|
||||
consumed := len(tt.p) - len(remain)
|
||||
got := res{i, consumed, err}
|
||||
if got != tt.want {
|
||||
t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56
|
||||
func TestHuffmanFuzzCrash(t *testing.T) {
|
||||
got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8"))
|
||||
if got != "" {
|
||||
t.Errorf("Got %q; want empty string", got)
|
||||
}
|
||||
if err != ErrInvalidHuffman {
|
||||
t.Errorf("Err = %v; want ErrInvalidHuffman", err)
|
||||
}
|
||||
}
|
||||
|
||||
func pair(name, value string) HeaderField {
|
||||
return HeaderField{Name: name, Value: value}
|
||||
}
|
||||
|
||||
func dehex(s string) []byte {
|
||||
s = strings.Replace(s, " ", "", -1)
|
||||
s = strings.Replace(s, "\n", "", -1)
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestEmitEnabled(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
|
||||
enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
|
||||
|
||||
numCallback := 0
|
||||
var dec *Decoder
|
||||
dec = NewDecoder(8<<20, func(HeaderField) {
|
||||
numCallback++
|
||||
dec.SetEmitEnabled(false)
|
||||
})
|
||||
if !dec.EmitEnabled() {
|
||||
t.Errorf("initial emit enabled = false; want true")
|
||||
}
|
||||
if _, err := dec.Write(buf.Bytes()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if numCallback != 1 {
|
||||
t.Errorf("num callbacks = %d; want 1", numCallback)
|
||||
}
|
||||
if dec.EmitEnabled() {
|
||||
t.Errorf("emit enabled = true; want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveBufLimit(t *testing.T) {
|
||||
const maxStr = 1 << 10
|
||||
var got []HeaderField
|
||||
dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) {
|
||||
got = append(got, hf)
|
||||
})
|
||||
dec.SetMaxStringLength(maxStr)
|
||||
var frag []byte
|
||||
frag = append(frag[:0], encodeTypeByte(false, false))
|
||||
frag = appendVarInt(frag, 7, 3)
|
||||
frag = append(frag, "foo"...)
|
||||
frag = appendVarInt(frag, 7, 3)
|
||||
frag = append(frag, "bar"...)
|
||||
|
||||
if _, err := dec.Write(frag); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := []HeaderField{{Name: "foo", Value: "bar"}}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("After small writes, got %v; want %v", got, want)
|
||||
}
|
||||
|
||||
frag = append(frag[:0], encodeTypeByte(false, false))
|
||||
frag = appendVarInt(frag, 7, maxStr*3)
|
||||
frag = append(frag, make([]byte, maxStr*3)...)
|
||||
|
||||
_, err := dec.Write(frag)
|
||||
if err != ErrStringLength {
|
||||
t.Fatalf("Write error = %v; want ErrStringLength", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDynamicSizeUpdate(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
enc.SetMaxDynamicTableSize(255)
|
||||
enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
|
||||
|
||||
d := NewDecoder(4096, nil)
|
||||
_, err := d.DecodeFull(buf.Bytes())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: got = %v", err)
|
||||
}
|
||||
|
||||
// must fail since the dynamic table update must be at the beginning
|
||||
_, err = d.DecodeFull(buf.Bytes())
|
||||
if err == nil {
|
||||
t.Fatalf("dynamic table size update not at the beginning of a header block")
|
||||
}
|
||||
}
|
20
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
20
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
|
@ -47,6 +47,7 @@ var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
|
|||
// If maxLen is greater than 0, attempts to write more to buf than
|
||||
// maxLen bytes will return ErrStringLength.
|
||||
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
||||
rootHuffmanNode := getRootHuffmanNode()
|
||||
n := rootHuffmanNode
|
||||
// cur is the bit buffer that has not been fed into n.
|
||||
// cbits is the number of low order bits in cur that are valid.
|
||||
|
@ -106,7 +107,7 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
|||
|
||||
type node struct {
|
||||
// children is non-nil for internal nodes
|
||||
children []*node
|
||||
children *[256]*node
|
||||
|
||||
// The following are only valid if children is nil:
|
||||
codeLen uint8 // number of bits that led to the output of sym
|
||||
|
@ -114,22 +115,31 @@ type node struct {
|
|||
}
|
||||
|
||||
func newInternalNode() *node {
|
||||
return &node{children: make([]*node, 256)}
|
||||
return &node{children: new([256]*node)}
|
||||
}
|
||||
|
||||
var rootHuffmanNode = newInternalNode()
|
||||
var (
|
||||
buildRootOnce sync.Once
|
||||
lazyRootHuffmanNode *node
|
||||
)
|
||||
|
||||
func init() {
|
||||
func getRootHuffmanNode() *node {
|
||||
buildRootOnce.Do(buildRootHuffmanNode)
|
||||
return lazyRootHuffmanNode
|
||||
}
|
||||
|
||||
func buildRootHuffmanNode() {
|
||||
if len(huffmanCodes) != 256 {
|
||||
panic("unexpected size")
|
||||
}
|
||||
lazyRootHuffmanNode = newInternalNode()
|
||||
for i, code := range huffmanCodes {
|
||||
addDecoderNode(byte(i), code, huffmanCodeLen[i])
|
||||
}
|
||||
}
|
||||
|
||||
func addDecoderNode(sym byte, code uint32, codeLen uint8) {
|
||||
cur := rootHuffmanNode
|
||||
cur := lazyRootHuffmanNode
|
||||
for codeLen > 8 {
|
||||
codeLen -= 8
|
||||
i := uint8(code >> codeLen)
|
||||
|
|
214
vendor/golang.org/x/net/http2/hpack/tables_test.go
generated
vendored
214
vendor/golang.org/x/net/http2/hpack/tables_test.go
generated
vendored
|
@ -1,214 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hpack
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHeaderFieldTable(t *testing.T) {
|
||||
table := &headerFieldTable{}
|
||||
table.init()
|
||||
table.addEntry(pair("key1", "value1-1"))
|
||||
table.addEntry(pair("key2", "value2-1"))
|
||||
table.addEntry(pair("key1", "value1-2"))
|
||||
table.addEntry(pair("key3", "value3-1"))
|
||||
table.addEntry(pair("key4", "value4-1"))
|
||||
table.addEntry(pair("key2", "value2-2"))
|
||||
|
||||
// Tests will be run twice: once before evicting anything, and
|
||||
// again after evicting the three oldest entries.
|
||||
tests := []struct {
|
||||
f HeaderField
|
||||
beforeWantStaticI uint64
|
||||
beforeWantMatch bool
|
||||
afterWantStaticI uint64
|
||||
afterWantMatch bool
|
||||
}{
|
||||
{HeaderField{"key1", "value1-1", false}, 1, true, 0, false},
|
||||
{HeaderField{"key1", "value1-2", false}, 3, true, 0, false},
|
||||
{HeaderField{"key1", "value1-3", false}, 3, false, 0, false},
|
||||
{HeaderField{"key2", "value2-1", false}, 2, true, 3, false},
|
||||
{HeaderField{"key2", "value2-2", false}, 6, true, 3, true},
|
||||
{HeaderField{"key2", "value2-3", false}, 6, false, 3, false},
|
||||
{HeaderField{"key4", "value4-1", false}, 5, true, 2, true},
|
||||
// Name match only, because sensitive.
|
||||
{HeaderField{"key4", "value4-1", true}, 5, false, 2, false},
|
||||
// Key not found.
|
||||
{HeaderField{"key5", "value5-x", false}, 0, false, 0, false},
|
||||
}
|
||||
|
||||
staticToDynamic := func(i uint64) uint64 {
|
||||
if i == 0 {
|
||||
return 0
|
||||
}
|
||||
return uint64(table.len()) - i + 1 // dynamic is the reversed table
|
||||
}
|
||||
|
||||
searchStatic := func(f HeaderField) (uint64, bool) {
|
||||
old := staticTable
|
||||
staticTable = table
|
||||
defer func() { staticTable = old }()
|
||||
return staticTable.search(f)
|
||||
}
|
||||
|
||||
searchDynamic := func(f HeaderField) (uint64, bool) {
|
||||
return table.search(f)
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
gotI, gotMatch := searchStatic(test.f)
|
||||
if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||
t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||
}
|
||||
gotI, gotMatch = searchDynamic(test.f)
|
||||
wantDynamicI := staticToDynamic(test.beforeWantStaticI)
|
||||
if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||
t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||
}
|
||||
}
|
||||
|
||||
table.evictOldest(3)
|
||||
|
||||
for _, test := range tests {
|
||||
gotI, gotMatch := searchStatic(test.f)
|
||||
if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||
t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||
}
|
||||
gotI, gotMatch = searchDynamic(test.f)
|
||||
wantDynamicI := staticToDynamic(test.afterWantStaticI)
|
||||
if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||
t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderFieldTable_LookupMapEviction(t *testing.T) {
|
||||
table := &headerFieldTable{}
|
||||
table.init()
|
||||
table.addEntry(pair("key1", "value1-1"))
|
||||
table.addEntry(pair("key2", "value2-1"))
|
||||
table.addEntry(pair("key1", "value1-2"))
|
||||
table.addEntry(pair("key3", "value3-1"))
|
||||
table.addEntry(pair("key4", "value4-1"))
|
||||
table.addEntry(pair("key2", "value2-2"))
|
||||
|
||||
// evict all pairs
|
||||
table.evictOldest(table.len())
|
||||
|
||||
if l := table.len(); l > 0 {
|
||||
t.Errorf("table.len() = %d, want 0", l)
|
||||
}
|
||||
|
||||
if l := len(table.byName); l > 0 {
|
||||
t.Errorf("len(table.byName) = %d, want 0", l)
|
||||
}
|
||||
|
||||
if l := len(table.byNameValue); l > 0 {
|
||||
t.Errorf("len(table.byNameValue) = %d, want 0", l)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticTable(t *testing.T) {
|
||||
fromSpec := `
|
||||
+-------+-----------------------------+---------------+
|
||||
| 1 | :authority | |
|
||||
| 2 | :method | GET |
|
||||
| 3 | :method | POST |
|
||||
| 4 | :path | / |
|
||||
| 5 | :path | /index.html |
|
||||
| 6 | :scheme | http |
|
||||
| 7 | :scheme | https |
|
||||
| 8 | :status | 200 |
|
||||
| 9 | :status | 204 |
|
||||
| 10 | :status | 206 |
|
||||
| 11 | :status | 304 |
|
||||
| 12 | :status | 400 |
|
||||
| 13 | :status | 404 |
|
||||
| 14 | :status | 500 |
|
||||
| 15 | accept-charset | |
|
||||
| 16 | accept-encoding | gzip, deflate |
|
||||
| 17 | accept-language | |
|
||||
| 18 | accept-ranges | |
|
||||
| 19 | accept | |
|
||||
| 20 | access-control-allow-origin | |
|
||||
| 21 | age | |
|
||||
| 22 | allow | |
|
||||
| 23 | authorization | |
|
||||
| 24 | cache-control | |
|
||||
| 25 | content-disposition | |
|
||||
| 26 | content-encoding | |
|
||||
| 27 | content-language | |
|
||||
| 28 | content-length | |
|
||||
| 29 | content-location | |
|
||||
| 30 | content-range | |
|
||||
| 31 | content-type | |
|
||||
| 32 | cookie | |
|
||||
| 33 | date | |
|
||||
| 34 | etag | |
|
||||
| 35 | expect | |
|
||||
| 36 | expires | |
|
||||
| 37 | from | |
|
||||
| 38 | host | |
|
||||
| 39 | if-match | |
|
||||
| 40 | if-modified-since | |
|
||||
| 41 | if-none-match | |
|
||||
| 42 | if-range | |
|
||||
| 43 | if-unmodified-since | |
|
||||
| 44 | last-modified | |
|
||||
| 45 | link | |
|
||||
| 46 | location | |
|
||||
| 47 | max-forwards | |
|
||||
| 48 | proxy-authenticate | |
|
||||
| 49 | proxy-authorization | |
|
||||
| 50 | range | |
|
||||
| 51 | referer | |
|
||||
| 52 | refresh | |
|
||||
| 53 | retry-after | |
|
||||
| 54 | server | |
|
||||
| 55 | set-cookie | |
|
||||
| 56 | strict-transport-security | |
|
||||
| 57 | transfer-encoding | |
|
||||
| 58 | user-agent | |
|
||||
| 59 | vary | |
|
||||
| 60 | via | |
|
||||
| 61 | www-authenticate | |
|
||||
+-------+-----------------------------+---------------+
|
||||
`
|
||||
bs := bufio.NewScanner(strings.NewReader(fromSpec))
|
||||
re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
|
||||
for bs.Scan() {
|
||||
l := bs.Text()
|
||||
if !strings.Contains(l, "|") {
|
||||
continue
|
||||
}
|
||||
m := re.FindStringSubmatch(l)
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
i, err := strconv.Atoi(m[1])
|
||||
if err != nil {
|
||||
t.Errorf("Bogus integer on line %q", l)
|
||||
continue
|
||||
}
|
||||
if i < 1 || i > staticTable.len() {
|
||||
t.Errorf("Bogus index %d on line %q", i, l)
|
||||
continue
|
||||
}
|
||||
if got, want := staticTable.ents[i-1].Name, m[2]; got != want {
|
||||
t.Errorf("header index %d name = %q; want %q", i, got, want)
|
||||
}
|
||||
if got, want := staticTable.ents[i-1].Value, m[3]; got != want {
|
||||
t.Errorf("header index %d value = %q; want %q", i, got, want)
|
||||
}
|
||||
}
|
||||
if err := bs.Err(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
227
vendor/golang.org/x/net/http2/http2_test.go
generated
vendored
227
vendor/golang.org/x/net/http2/http2_test.go
generated
vendored
|
@ -1,227 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
var knownFailing = flag.Bool("known_failing", false, "Run known-failing tests.")
|
||||
|
||||
func condSkipFailingTest(t *testing.T) {
|
||||
if !*knownFailing {
|
||||
t.Skip("Skipping known-failing test without --known_failing")
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inTests = true
|
||||
DebugGoroutines = true
|
||||
flag.BoolVar(&VerboseLogs, "verboseh2", VerboseLogs, "Verbose HTTP/2 debug logging")
|
||||
}
|
||||
|
||||
func TestSettingString(t *testing.T) {
|
||||
tests := []struct {
|
||||
s Setting
|
||||
want string
|
||||
}{
|
||||
{Setting{SettingMaxFrameSize, 123}, "[MAX_FRAME_SIZE = 123]"},
|
||||
{Setting{1<<16 - 1, 123}, "[UNKNOWN_SETTING_65535 = 123]"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
got := fmt.Sprint(tt.s)
|
||||
if got != tt.want {
|
||||
t.Errorf("%d. for %#v, string = %q; want %q", i, tt.s, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type twriter struct {
|
||||
t testing.TB
|
||||
st *serverTester // optional
|
||||
}
|
||||
|
||||
func (w twriter) Write(p []byte) (n int, err error) {
|
||||
if w.st != nil {
|
||||
ps := string(p)
|
||||
for _, phrase := range w.st.logFilter {
|
||||
if strings.Contains(ps, phrase) {
|
||||
return len(p), nil // no logging
|
||||
}
|
||||
}
|
||||
}
|
||||
w.t.Logf("%s", p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// like encodeHeader, but don't add implicit pseudo headers.
|
||||
func encodeHeaderNoImplicit(t *testing.T, headers ...string) []byte {
|
||||
var buf bytes.Buffer
|
||||
enc := hpack.NewEncoder(&buf)
|
||||
for len(headers) > 0 {
|
||||
k, v := headers[0], headers[1]
|
||||
headers = headers[2:]
|
||||
if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil {
|
||||
t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// Verify that curl has http2.
|
||||
func requireCurl(t *testing.T) {
|
||||
out, err := dockerLogs(curl(t, "--version"))
|
||||
if err != nil {
|
||||
t.Skipf("failed to determine curl features; skipping test")
|
||||
}
|
||||
if !strings.Contains(string(out), "HTTP2") {
|
||||
t.Skip("curl doesn't support HTTP2; skipping test")
|
||||
}
|
||||
}
|
||||
|
||||
func curl(t *testing.T, args ...string) (container string) {
|
||||
out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).Output()
|
||||
if err != nil {
|
||||
t.Skipf("Failed to run curl in docker: %v, %s", err, out)
|
||||
}
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
// Verify that h2load exists.
|
||||
func requireH2load(t *testing.T) {
|
||||
out, err := dockerLogs(h2load(t, "--version"))
|
||||
if err != nil {
|
||||
t.Skipf("failed to probe h2load; skipping test: %s", out)
|
||||
}
|
||||
if !strings.Contains(string(out), "h2load nghttp2/") {
|
||||
t.Skipf("h2load not present; skipping test. (Output=%q)", out)
|
||||
}
|
||||
}
|
||||
|
||||
func h2load(t *testing.T, args ...string) (container string) {
|
||||
out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl"}, args...)...).Output()
|
||||
if err != nil {
|
||||
t.Skipf("Failed to run h2load in docker: %v, %s", err, out)
|
||||
}
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
type puppetCommand struct {
|
||||
fn func(w http.ResponseWriter, r *http.Request)
|
||||
done chan<- bool
|
||||
}
|
||||
|
||||
type handlerPuppet struct {
|
||||
ch chan puppetCommand
|
||||
}
|
||||
|
||||
func newHandlerPuppet() *handlerPuppet {
|
||||
return &handlerPuppet{
|
||||
ch: make(chan puppetCommand),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *handlerPuppet) act(w http.ResponseWriter, r *http.Request) {
|
||||
for cmd := range p.ch {
|
||||
cmd.fn(w, r)
|
||||
cmd.done <- true
|
||||
}
|
||||
}
|
||||
|
||||
func (p *handlerPuppet) done() { close(p.ch) }
|
||||
func (p *handlerPuppet) do(fn func(http.ResponseWriter, *http.Request)) {
|
||||
done := make(chan bool)
|
||||
p.ch <- puppetCommand{fn, done}
|
||||
<-done
|
||||
}
|
||||
func dockerLogs(container string) ([]byte, error) {
|
||||
out, err := exec.Command("docker", "wait", container).CombinedOutput()
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
|
||||
if err != nil {
|
||||
return out, errors.New("unexpected exit status from docker wait")
|
||||
}
|
||||
out, err = exec.Command("docker", "logs", container).CombinedOutput()
|
||||
exec.Command("docker", "rm", container).Run()
|
||||
if err == nil && exitStatus != 0 {
|
||||
err = fmt.Errorf("exit status %d: %s", exitStatus, out)
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
func kill(container string) {
|
||||
exec.Command("docker", "kill", container).Run()
|
||||
exec.Command("docker", "rm", container).Run()
|
||||
}
|
||||
|
||||
func cleanDate(res *http.Response) {
|
||||
if d := res.Header["Date"]; len(d) == 1 {
|
||||
d[0] = "XXX"
|
||||
}
|
||||
}
|
||||
|
||||
func TestSorterPoolAllocs(t *testing.T) {
|
||||
ss := []string{"a", "b", "c"}
|
||||
h := http.Header{
|
||||
"a": nil,
|
||||
"b": nil,
|
||||
"c": nil,
|
||||
}
|
||||
sorter := new(sorter)
|
||||
|
||||
if allocs := testing.AllocsPerRun(100, func() {
|
||||
sorter.SortStrings(ss)
|
||||
}); allocs >= 1 {
|
||||
t.Logf("SortStrings allocs = %v; want <1", allocs)
|
||||
}
|
||||
|
||||
if allocs := testing.AllocsPerRun(5, func() {
|
||||
if len(sorter.Keys(h)) != 3 {
|
||||
t.Fatal("wrong result")
|
||||
}
|
||||
}); allocs > 0 {
|
||||
t.Logf("Keys allocs = %v; want <1", allocs)
|
||||
}
|
||||
}
|
||||
|
||||
// waitCondition reports whether fn eventually returned true,
|
||||
// checking immediately and then every checkEvery amount,
|
||||
// until waitFor has elapsed, at which point it returns false.
|
||||
func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool {
|
||||
deadline := time.Now().Add(waitFor)
|
||||
for time.Now().Before(deadline) {
|
||||
if fn() {
|
||||
return true
|
||||
}
|
||||
time.Sleep(checkEvery)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// waitErrCondition is like waitCondition but with errors instead of bools.
|
||||
func waitErrCondition(waitFor, checkEvery time.Duration, fn func() error) error {
|
||||
deadline := time.Now().Add(waitFor)
|
||||
var err error
|
||||
for time.Now().Before(deadline) {
|
||||
if err = fn(); err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(checkEvery)
|
||||
}
|
||||
return err
|
||||
}
|
17
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.11
|
||||
|
||||
package http2
|
||||
|
||||
import "net/textproto"
|
||||
|
||||
func traceHasWroteHeaderField(trace *clientTrace) bool { return false }
|
||||
|
||||
func traceWroteHeaderField(trace *clientTrace, k, v string) {}
|
||||
|
||||
func traceGot1xxResponseFunc(trace *clientTrace) func(int, textproto.MIMEHeader) error {
|
||||
return nil
|
||||
}
|
8
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
8
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
|
@ -8,6 +8,7 @@ package http2
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
@ -18,6 +19,8 @@ type contextContext interface {
|
|||
Err() error
|
||||
}
|
||||
|
||||
var errCanceled = errors.New("canceled")
|
||||
|
||||
type fakeContext struct{}
|
||||
|
||||
func (fakeContext) Done() <-chan struct{} { return nil }
|
||||
|
@ -34,6 +37,7 @@ func setResponseUncompressed(res *http.Response) {
|
|||
type clientTrace struct{}
|
||||
|
||||
func requestTrace(*http.Request) *clientTrace { return nil }
|
||||
func traceGetConn(*http.Request, string) {}
|
||||
func traceGotConn(*http.Request, *ClientConn) {}
|
||||
func traceFirstResponseByte(*clientTrace) {}
|
||||
func traceWroteHeaders(*clientTrace) {}
|
||||
|
@ -84,4 +88,8 @@ func (cc *ClientConn) Ping(ctx contextContext) error {
|
|||
return cc.ping(ctx)
|
||||
}
|
||||
|
||||
func (cc *ClientConn) Shutdown(ctx contextContext) error {
|
||||
return cc.shutdown(ctx)
|
||||
}
|
||||
|
||||
func (t *Transport) idleConnTimeout() time.Duration { return 0 }
|
||||
|
|
130
vendor/golang.org/x/net/http2/pipe_test.go
generated
vendored
130
vendor/golang.org/x/net/http2/pipe_test.go
generated
vendored
|
@ -1,130 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPipeClose(t *testing.T) {
|
||||
var p pipe
|
||||
p.b = new(bytes.Buffer)
|
||||
a := errors.New("a")
|
||||
b := errors.New("b")
|
||||
p.CloseWithError(a)
|
||||
p.CloseWithError(b)
|
||||
_, err := p.Read(make([]byte, 1))
|
||||
if err != a {
|
||||
t.Errorf("err = %v want %v", err, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeDoneChan(t *testing.T) {
|
||||
var p pipe
|
||||
done := p.Done()
|
||||
select {
|
||||
case <-done:
|
||||
t.Fatal("done too soon")
|
||||
default:
|
||||
}
|
||||
p.CloseWithError(io.EOF)
|
||||
select {
|
||||
case <-done:
|
||||
default:
|
||||
t.Fatal("should be done")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeDoneChan_ErrFirst(t *testing.T) {
|
||||
var p pipe
|
||||
p.CloseWithError(io.EOF)
|
||||
done := p.Done()
|
||||
select {
|
||||
case <-done:
|
||||
default:
|
||||
t.Fatal("should be done")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeDoneChan_Break(t *testing.T) {
|
||||
var p pipe
|
||||
done := p.Done()
|
||||
select {
|
||||
case <-done:
|
||||
t.Fatal("done too soon")
|
||||
default:
|
||||
}
|
||||
p.BreakWithError(io.EOF)
|
||||
select {
|
||||
case <-done:
|
||||
default:
|
||||
t.Fatal("should be done")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeDoneChan_Break_ErrFirst(t *testing.T) {
|
||||
var p pipe
|
||||
p.BreakWithError(io.EOF)
|
||||
done := p.Done()
|
||||
select {
|
||||
case <-done:
|
||||
default:
|
||||
t.Fatal("should be done")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeCloseWithError(t *testing.T) {
|
||||
p := &pipe{b: new(bytes.Buffer)}
|
||||
const body = "foo"
|
||||
io.WriteString(p, body)
|
||||
a := errors.New("test error")
|
||||
p.CloseWithError(a)
|
||||
all, err := ioutil.ReadAll(p)
|
||||
if string(all) != body {
|
||||
t.Errorf("read bytes = %q; want %q", all, body)
|
||||
}
|
||||
if err != a {
|
||||
t.Logf("read error = %v, %v", err, a)
|
||||
}
|
||||
// Read and Write should fail.
|
||||
if n, err := p.Write([]byte("abc")); err != errClosedPipeWrite || n != 0 {
|
||||
t.Errorf("Write(abc) after close\ngot %v, %v\nwant 0, %v", n, err, errClosedPipeWrite)
|
||||
}
|
||||
if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
|
||||
t.Errorf("Read() after close\ngot %v, nil\nwant 0, %v", n, errClosedPipeWrite)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeBreakWithError(t *testing.T) {
|
||||
p := &pipe{b: new(bytes.Buffer)}
|
||||
io.WriteString(p, "foo")
|
||||
a := errors.New("test err")
|
||||
p.BreakWithError(a)
|
||||
all, err := ioutil.ReadAll(p)
|
||||
if string(all) != "" {
|
||||
t.Errorf("read bytes = %q; want empty string", all)
|
||||
}
|
||||
if err != a {
|
||||
t.Logf("read error = %v, %v", err, a)
|
||||
}
|
||||
if p.b != nil {
|
||||
t.Errorf("buffer should be nil after BreakWithError")
|
||||
}
|
||||
// Write should succeed silently.
|
||||
if n, err := p.Write([]byte("abc")); err != nil || n != 3 {
|
||||
t.Errorf("Write(abc) after break\ngot %v, %v\nwant 0, nil", n, err)
|
||||
}
|
||||
if p.b != nil {
|
||||
t.Errorf("buffer should be nil after Write")
|
||||
}
|
||||
// Read should fail.
|
||||
if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
|
||||
t.Errorf("Read() after close\ngot %v, nil\nwant 0, not nil", n)
|
||||
}
|
||||
}
|
29
vendor/golang.org/x/net/http2/server.go
generated
vendored
29
vendor/golang.org/x/net/http2/server.go
generated
vendored
|
@ -1487,6 +1487,12 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
if f.NumSettings() > 100 || f.HasDuplicates() {
|
||||
// This isn't actually in the spec, but hang up on
|
||||
// suspiciously large settings frames or those with
|
||||
// duplicate entries.
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1575,6 +1581,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
// type PROTOCOL_ERROR."
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
// RFC 7540, sec 6.1: If a DATA frame is received whose stream is not in
|
||||
// "open" or "half-closed (local)" state, the recipient MUST respond with a
|
||||
// stream error (Section 5.4.2) of type STREAM_CLOSED.
|
||||
if state == stateClosed {
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
}
|
||||
if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {
|
||||
// This includes sending a RST_STREAM if the stream is
|
||||
// in stateHalfClosedLocal (which currently means that
|
||||
|
@ -1721,6 +1733,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
// processing this frame.
|
||||
return nil
|
||||
}
|
||||
// RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
|
||||
// WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
|
||||
// this state, it MUST respond with a stream error (Section 5.4.2) of
|
||||
// type STREAM_CLOSED.
|
||||
if st.state == stateHalfClosedRemote {
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
}
|
||||
return st.processTrailerHeaders(f)
|
||||
}
|
||||
|
||||
|
@ -2327,15 +2346,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||
}
|
||||
_, hasContentType := rws.snapHeader["Content-Type"]
|
||||
if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||
if cto := rws.snapHeader.Get("X-Content-Type-Options"); strings.EqualFold("nosniff", cto) {
|
||||
// nosniff is an explicit directive not to guess a content-type.
|
||||
// Content-sniffing is no less susceptible to polyglot attacks via
|
||||
// hosted content when done on the server.
|
||||
ctype = "application/octet-stream"
|
||||
rws.conn.logf("http2: WriteHeader called with X-Content-Type-Options:nosniff but no Content-Type")
|
||||
} else {
|
||||
ctype = http.DetectContentType(p)
|
||||
}
|
||||
ctype = http.DetectContentType(p)
|
||||
}
|
||||
var date string
|
||||
if _, ok := rws.snapHeader["Date"]; !ok {
|
||||
|
|
521
vendor/golang.org/x/net/http2/server_push_test.go
generated
vendored
521
vendor/golang.org/x/net/http2/server_push_test.go
generated
vendored
|
@ -1,521 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServer_Push_Success(t *testing.T) {
|
||||
const (
|
||||
mainBody = "<html>index page</html>"
|
||||
pushedBody = "<html>pushed page</html>"
|
||||
userAgent = "testagent"
|
||||
cookie = "testcookie"
|
||||
)
|
||||
|
||||
var stURL string
|
||||
checkPromisedReq := func(r *http.Request, wantMethod string, wantH http.Header) error {
|
||||
if got, want := r.Method, wantMethod; got != want {
|
||||
return fmt.Errorf("promised Req.Method=%q, want %q", got, want)
|
||||
}
|
||||
if got, want := r.Header, wantH; !reflect.DeepEqual(got, want) {
|
||||
return fmt.Errorf("promised Req.Header=%q, want %q", got, want)
|
||||
}
|
||||
if got, want := "https://"+r.Host, stURL; got != want {
|
||||
return fmt.Errorf("promised Req.Host=%q, want %q", got, want)
|
||||
}
|
||||
if r.Body == nil {
|
||||
return fmt.Errorf("nil Body")
|
||||
}
|
||||
if buf, err := ioutil.ReadAll(r.Body); err != nil || len(buf) != 0 {
|
||||
return fmt.Errorf("ReadAll(Body)=%q,%v, want '',nil", buf, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
errc := make(chan error, 3)
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.RequestURI() {
|
||||
case "/":
|
||||
// Push "/pushed?get" as a GET request, using an absolute URL.
|
||||
opt := &http.PushOptions{
|
||||
Header: http.Header{
|
||||
"User-Agent": {userAgent},
|
||||
},
|
||||
}
|
||||
if err := w.(http.Pusher).Push(stURL+"/pushed?get", opt); err != nil {
|
||||
errc <- fmt.Errorf("error pushing /pushed?get: %v", err)
|
||||
return
|
||||
}
|
||||
// Push "/pushed?head" as a HEAD request, using a path.
|
||||
opt = &http.PushOptions{
|
||||
Method: "HEAD",
|
||||
Header: http.Header{
|
||||
"User-Agent": {userAgent},
|
||||
"Cookie": {cookie},
|
||||
},
|
||||
}
|
||||
if err := w.(http.Pusher).Push("/pushed?head", opt); err != nil {
|
||||
errc <- fmt.Errorf("error pushing /pushed?head: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(mainBody)))
|
||||
w.WriteHeader(200)
|
||||
io.WriteString(w, mainBody)
|
||||
errc <- nil
|
||||
|
||||
case "/pushed?get":
|
||||
wantH := http.Header{}
|
||||
wantH.Set("User-Agent", userAgent)
|
||||
if err := checkPromisedReq(r, "GET", wantH); err != nil {
|
||||
errc <- fmt.Errorf("/pushed?get: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(pushedBody)))
|
||||
w.WriteHeader(200)
|
||||
io.WriteString(w, pushedBody)
|
||||
errc <- nil
|
||||
|
||||
case "/pushed?head":
|
||||
wantH := http.Header{}
|
||||
wantH.Set("User-Agent", userAgent)
|
||||
wantH.Set("Cookie", cookie)
|
||||
if err := checkPromisedReq(r, "HEAD", wantH); err != nil {
|
||||
errc <- fmt.Errorf("/pushed?head: %v", err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
errc <- nil
|
||||
|
||||
default:
|
||||
errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI())
|
||||
}
|
||||
})
|
||||
stURL = st.ts.URL
|
||||
|
||||
// Send one request, which should push two responses.
|
||||
st.greet()
|
||||
getSlash(st)
|
||||
for k := 0; k < 3; k++ {
|
||||
select {
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Errorf("timeout waiting for handler %d to finish", k)
|
||||
case err := <-errc:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkPushPromise := func(f Frame, promiseID uint32, wantH [][2]string) error {
|
||||
pp, ok := f.(*PushPromiseFrame)
|
||||
if !ok {
|
||||
return fmt.Errorf("got a %T; want *PushPromiseFrame", f)
|
||||
}
|
||||
if !pp.HeadersEnded() {
|
||||
return fmt.Errorf("want END_HEADERS flag in PushPromiseFrame")
|
||||
}
|
||||
if got, want := pp.PromiseID, promiseID; got != want {
|
||||
return fmt.Errorf("got PromiseID %v; want %v", got, want)
|
||||
}
|
||||
gotH := st.decodeHeader(pp.HeaderBlockFragment())
|
||||
if !reflect.DeepEqual(gotH, wantH) {
|
||||
return fmt.Errorf("got promised headers %v; want %v", gotH, wantH)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
checkHeaders := func(f Frame, wantH [][2]string) error {
|
||||
hf, ok := f.(*HeadersFrame)
|
||||
if !ok {
|
||||
return fmt.Errorf("got a %T; want *HeadersFrame", f)
|
||||
}
|
||||
gotH := st.decodeHeader(hf.HeaderBlockFragment())
|
||||
if !reflect.DeepEqual(gotH, wantH) {
|
||||
return fmt.Errorf("got response headers %v; want %v", gotH, wantH)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
checkData := func(f Frame, wantData string) error {
|
||||
df, ok := f.(*DataFrame)
|
||||
if !ok {
|
||||
return fmt.Errorf("got a %T; want *DataFrame", f)
|
||||
}
|
||||
if gotData := string(df.Data()); gotData != wantData {
|
||||
return fmt.Errorf("got response data %q; want %q", gotData, wantData)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stream 1 has 2 PUSH_PROMISE + HEADERS + DATA
|
||||
// Stream 2 has HEADERS + DATA
|
||||
// Stream 4 has HEADERS
|
||||
expected := map[uint32][]func(Frame) error{
|
||||
1: {
|
||||
func(f Frame) error {
|
||||
return checkPushPromise(f, 2, [][2]string{
|
||||
{":method", "GET"},
|
||||
{":scheme", "https"},
|
||||
{":authority", st.ts.Listener.Addr().String()},
|
||||
{":path", "/pushed?get"},
|
||||
{"user-agent", userAgent},
|
||||
})
|
||||
},
|
||||
func(f Frame) error {
|
||||
return checkPushPromise(f, 4, [][2]string{
|
||||
{":method", "HEAD"},
|
||||
{":scheme", "https"},
|
||||
{":authority", st.ts.Listener.Addr().String()},
|
||||
{":path", "/pushed?head"},
|
||||
{"cookie", cookie},
|
||||
{"user-agent", userAgent},
|
||||
})
|
||||
},
|
||||
func(f Frame) error {
|
||||
return checkHeaders(f, [][2]string{
|
||||
{":status", "200"},
|
||||
{"content-type", "text/html"},
|
||||
{"content-length", strconv.Itoa(len(mainBody))},
|
||||
})
|
||||
},
|
||||
func(f Frame) error {
|
||||
return checkData(f, mainBody)
|
||||
},
|
||||
},
|
||||
2: {
|
||||
func(f Frame) error {
|
||||
return checkHeaders(f, [][2]string{
|
||||
{":status", "200"},
|
||||
{"content-type", "text/html"},
|
||||
{"content-length", strconv.Itoa(len(pushedBody))},
|
||||
})
|
||||
},
|
||||
func(f Frame) error {
|
||||
return checkData(f, pushedBody)
|
||||
},
|
||||
},
|
||||
4: {
|
||||
func(f Frame) error {
|
||||
return checkHeaders(f, [][2]string{
|
||||
{":status", "204"},
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
consumed := map[uint32]int{}
|
||||
for k := 0; len(expected) > 0; k++ {
|
||||
f, err := st.readFrame()
|
||||
if err != nil {
|
||||
for id, left := range expected {
|
||||
t.Errorf("stream %d: missing %d frames", id, len(left))
|
||||
}
|
||||
t.Fatalf("readFrame %d: %v", k, err)
|
||||
}
|
||||
id := f.Header().StreamID
|
||||
label := fmt.Sprintf("stream %d, frame %d", id, consumed[id])
|
||||
if len(expected[id]) == 0 {
|
||||
t.Fatalf("%s: unexpected frame %#+v", label, f)
|
||||
}
|
||||
check := expected[id][0]
|
||||
expected[id] = expected[id][1:]
|
||||
if len(expected[id]) == 0 {
|
||||
delete(expected, id)
|
||||
}
|
||||
if err := check(f); err != nil {
|
||||
t.Fatalf("%s: %v", label, err)
|
||||
}
|
||||
consumed[id]++
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_Push_SuccessNoRace(t *testing.T) {
|
||||
// Regression test for issue #18326. Ensure the request handler can mutate
|
||||
// pushed request headers without racing with the PUSH_PROMISE write.
|
||||
errc := make(chan error, 2)
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.RequestURI() {
|
||||
case "/":
|
||||
opt := &http.PushOptions{
|
||||
Header: http.Header{"User-Agent": {"testagent"}},
|
||||
}
|
||||
if err := w.(http.Pusher).Push("/pushed", opt); err != nil {
|
||||
errc <- fmt.Errorf("error pushing: %v", err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
errc <- nil
|
||||
|
||||
case "/pushed":
|
||||
// Update request header, ensure there is no race.
|
||||
r.Header.Set("User-Agent", "newagent")
|
||||
r.Header.Set("Cookie", "cookie")
|
||||
w.WriteHeader(200)
|
||||
errc <- nil
|
||||
|
||||
default:
|
||||
errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI())
|
||||
}
|
||||
})
|
||||
|
||||
// Send one request, which should push one response.
|
||||
st.greet()
|
||||
getSlash(st)
|
||||
for k := 0; k < 2; k++ {
|
||||
select {
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Errorf("timeout waiting for handler %d to finish", k)
|
||||
case err := <-errc:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectRecursivePush(t *testing.T) {
|
||||
// Expect two requests, but might get three if there's a bug and the second push succeeds.
|
||||
errc := make(chan error, 3)
|
||||
handler := func(w http.ResponseWriter, r *http.Request) error {
|
||||
baseURL := "https://" + r.Host
|
||||
switch r.URL.Path {
|
||||
case "/":
|
||||
if err := w.(http.Pusher).Push(baseURL+"/push1", nil); err != nil {
|
||||
return fmt.Errorf("first Push()=%v, want nil", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
case "/push1":
|
||||
if got, want := w.(http.Pusher).Push(baseURL+"/push2", nil), ErrRecursivePush; got != want {
|
||||
return fmt.Errorf("Push()=%v, want %v", got, want)
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected path: %q", r.URL.Path)
|
||||
}
|
||||
}
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
errc <- handler(w, r)
|
||||
})
|
||||
defer st.Close()
|
||||
st.greet()
|
||||
getSlash(st)
|
||||
if err := <-errc; err != nil {
|
||||
t.Errorf("First request failed: %v", err)
|
||||
}
|
||||
if err := <-errc; err != nil {
|
||||
t.Errorf("Second request failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func testServer_Push_RejectSingleRequest(t *testing.T, doPush func(http.Pusher, *http.Request) error, settings ...Setting) {
|
||||
// Expect one request, but might get two if there's a bug and the push succeeds.
|
||||
errc := make(chan error, 2)
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
errc <- doPush(w.(http.Pusher), r)
|
||||
})
|
||||
defer st.Close()
|
||||
st.greet()
|
||||
if err := st.fr.WriteSettings(settings...); err != nil {
|
||||
st.t.Fatalf("WriteSettings: %v", err)
|
||||
}
|
||||
st.wantSettingsAck()
|
||||
getSlash(st)
|
||||
if err := <-errc; err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// Should not get a PUSH_PROMISE frame.
|
||||
hf := st.wantHeaders()
|
||||
if !hf.StreamEnded() {
|
||||
t.Error("stream should end after headers")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectIfDisabled(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if got, want := p.Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want {
|
||||
return fmt.Errorf("Push()=%v, want %v", got, want)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Setting{SettingEnablePush, 0})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectWhenNoConcurrentStreams(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if got, want := p.Push("https://"+r.Host+"/pushed", nil), ErrPushLimitReached; got != want {
|
||||
return fmt.Errorf("Push()=%v, want %v", got, want)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Setting{SettingMaxConcurrentStreams, 0})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectWrongScheme(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if err := p.Push("http://"+r.Host+"/pushed", nil); err == nil {
|
||||
return errors.New("Push() should have failed (push target URL is http)")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectMissingHost(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if err := p.Push("https:pushed", nil); err == nil {
|
||||
return errors.New("Push() should have failed (push target URL missing host)")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectRelativePath(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if err := p.Push("../test", nil); err == nil {
|
||||
return errors.New("Push() should have failed (push target is a relative path)")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectForbiddenMethod(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Method: "POST"}); err == nil {
|
||||
return errors.New("Push() should have failed (cannot promise a POST)")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectForbiddenHeader(t *testing.T) {
|
||||
testServer_Push_RejectSingleRequest(t,
|
||||
func(p http.Pusher, r *http.Request) error {
|
||||
header := http.Header{
|
||||
"Content-Length": {"10"},
|
||||
"Content-Encoding": {"gzip"},
|
||||
"Trailer": {"Foo"},
|
||||
"Te": {"trailers"},
|
||||
"Host": {"test.com"},
|
||||
":authority": {"test.com"},
|
||||
}
|
||||
if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Header: header}); err == nil {
|
||||
return errors.New("Push() should have failed (forbidden headers)")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_Push_StateTransitions(t *testing.T) {
|
||||
const body = "foo"
|
||||
|
||||
gotPromise := make(chan bool)
|
||||
finishedPush := make(chan bool)
|
||||
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.RequestURI() {
|
||||
case "/":
|
||||
if err := w.(http.Pusher).Push("/pushed", nil); err != nil {
|
||||
t.Errorf("Push error: %v", err)
|
||||
}
|
||||
// Don't finish this request until the push finishes so we don't
|
||||
// nondeterministically interleave output frames with the push.
|
||||
<-finishedPush
|
||||
case "/pushed":
|
||||
<-gotPromise
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(body)))
|
||||
w.WriteHeader(200)
|
||||
io.WriteString(w, body)
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
st.greet()
|
||||
if st.stream(2) != nil {
|
||||
t.Fatal("stream 2 should be empty")
|
||||
}
|
||||
if got, want := st.streamState(2), stateIdle; got != want {
|
||||
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
||||
}
|
||||
getSlash(st)
|
||||
// After the PUSH_PROMISE is sent, the stream should be stateHalfClosedRemote.
|
||||
st.wantPushPromise()
|
||||
if got, want := st.streamState(2), stateHalfClosedRemote; got != want {
|
||||
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
||||
}
|
||||
// We stall the HTTP handler for "/pushed" until the above check. If we don't
|
||||
// stall the handler, then the handler might write HEADERS and DATA and finish
|
||||
// the stream before we check st.streamState(2) -- should that happen, we'll
|
||||
// see stateClosed and fail the above check.
|
||||
close(gotPromise)
|
||||
st.wantHeaders()
|
||||
if df := st.wantData(); !df.StreamEnded() {
|
||||
t.Fatal("expected END_STREAM flag on DATA")
|
||||
}
|
||||
if got, want := st.streamState(2), stateClosed; got != want {
|
||||
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
||||
}
|
||||
close(finishedPush)
|
||||
}
|
||||
|
||||
func TestServer_Push_RejectAfterGoAway(t *testing.T) {
|
||||
var readyOnce sync.Once
|
||||
ready := make(chan struct{})
|
||||
errc := make(chan error, 2)
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case <-ready:
|
||||
case <-time.After(5 * time.Second):
|
||||
errc <- fmt.Errorf("timeout waiting for GOAWAY to be processed")
|
||||
}
|
||||
if got, want := w.(http.Pusher).Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want {
|
||||
errc <- fmt.Errorf("Push()=%v, want %v", got, want)
|
||||
}
|
||||
errc <- nil
|
||||
})
|
||||
defer st.Close()
|
||||
st.greet()
|
||||
getSlash(st)
|
||||
|
||||
// Send GOAWAY and wait for it to be processed.
|
||||
st.fr.WriteGoAway(1, ErrCodeNo, nil)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ready:
|
||||
return
|
||||
default:
|
||||
}
|
||||
st.sc.serveMsgCh <- func(loopNum int) {
|
||||
if !st.sc.pushEnabled {
|
||||
readyOnce.Do(func() { close(ready) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err := <-errc; err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
3843
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
3843
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
207
vendor/golang.org/x/net/http2/transport.go
generated
vendored
207
vendor/golang.org/x/net/http2/transport.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
|||
mathrand "math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -159,6 +160,7 @@ type ClientConn struct {
|
|||
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
||||
flow flow // our conn-level flow control quota (cs.flow is per stream)
|
||||
inflow flow // peer's conn-level flow control
|
||||
closing bool
|
||||
closed bool
|
||||
wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
|
||||
goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
|
||||
|
@ -211,9 +213,10 @@ type clientStream struct {
|
|||
done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
|
||||
|
||||
// owned by clientConnReadLoop:
|
||||
firstByte bool // got the first response byte
|
||||
pastHeaders bool // got first MetaHeadersFrame (actual headers)
|
||||
pastTrailers bool // got optional second MetaHeadersFrame (trailers)
|
||||
firstByte bool // got the first response byte
|
||||
pastHeaders bool // got first MetaHeadersFrame (actual headers)
|
||||
pastTrailers bool // got optional second MetaHeadersFrame (trailers)
|
||||
num1xx uint8 // number of 1xx responses seen
|
||||
|
||||
trailer http.Header // accumulated trailers
|
||||
resTrailer *http.Header // client's Response.Trailer
|
||||
|
@ -237,6 +240,17 @@ func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
var got1xxFuncForTests func(int, textproto.MIMEHeader) error
|
||||
|
||||
// get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
|
||||
// if any. It returns nil if not set or if the Go version is too old.
|
||||
func (cs *clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) error {
|
||||
if fn := got1xxFuncForTests; fn != nil {
|
||||
return fn
|
||||
}
|
||||
return traceGot1xxResponseFunc(cs.trace)
|
||||
}
|
||||
|
||||
// awaitRequestCancel waits for the user to cancel a request, its context to
|
||||
// expire, or for the request to be done (any way it might be removed from the
|
||||
// cc.streams map: peer reset, successful completion, TCP connection breakage,
|
||||
|
@ -423,27 +437,36 @@ func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*htt
|
|||
if !canRetryError(err) {
|
||||
return nil, err
|
||||
}
|
||||
if !afterBodyWrite {
|
||||
return req, nil
|
||||
}
|
||||
// If the Body is nil (or http.NoBody), it's safe to reuse
|
||||
// this request and its Body.
|
||||
if req.Body == nil || reqBodyIsNoBody(req.Body) {
|
||||
return req, nil
|
||||
}
|
||||
// Otherwise we depend on the Request having its GetBody
|
||||
// func defined.
|
||||
|
||||
// If the request body can be reset back to its original
|
||||
// state via the optional req.GetBody, do that.
|
||||
getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
|
||||
if getBody == nil {
|
||||
return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
|
||||
if getBody != nil {
|
||||
// TODO: consider a req.Body.Close here? or audit that all caller paths do?
|
||||
body, err := getBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newReq := *req
|
||||
newReq.Body = body
|
||||
return &newReq, nil
|
||||
}
|
||||
body, err := getBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
// The Request.Body can't reset back to the beginning, but we
|
||||
// don't seem to have started to read from it yet, so reuse
|
||||
// the request directly. The "afterBodyWrite" means the
|
||||
// bodyWrite process has started, which becomes true before
|
||||
// the first Read.
|
||||
if !afterBodyWrite {
|
||||
return req, nil
|
||||
}
|
||||
newReq := *req
|
||||
newReq.Body = body
|
||||
return &newReq, nil
|
||||
|
||||
return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
|
||||
}
|
||||
|
||||
func canRetryError(err error) bool {
|
||||
|
@ -630,12 +653,32 @@ func (cc *ClientConn) CanTakeNewRequest() bool {
|
|||
return cc.canTakeNewRequestLocked()
|
||||
}
|
||||
|
||||
func (cc *ClientConn) canTakeNewRequestLocked() bool {
|
||||
// clientConnIdleState describes the suitability of a client
|
||||
// connection to initiate a new RoundTrip request.
|
||||
type clientConnIdleState struct {
|
||||
canTakeNewRequest bool
|
||||
freshConn bool // whether it's unused by any previous request
|
||||
}
|
||||
|
||||
func (cc *ClientConn) idleState() clientConnIdleState {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
return cc.idleStateLocked()
|
||||
}
|
||||
|
||||
func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
|
||||
if cc.singleUse && cc.nextStreamID > 1 {
|
||||
return false
|
||||
return
|
||||
}
|
||||
return cc.goAway == nil && !cc.closed &&
|
||||
st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing &&
|
||||
int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32
|
||||
st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest
|
||||
return
|
||||
}
|
||||
|
||||
func (cc *ClientConn) canTakeNewRequestLocked() bool {
|
||||
st := cc.idleStateLocked()
|
||||
return st.canTakeNewRequest
|
||||
}
|
||||
|
||||
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
|
||||
|
@ -665,6 +708,88 @@ func (cc *ClientConn) closeIfIdle() {
|
|||
cc.tconn.Close()
|
||||
}
|
||||
|
||||
var shutdownEnterWaitStateHook = func() {}
|
||||
|
||||
// Shutdown gracefully close the client connection, waiting for running streams to complete.
|
||||
// Public implementation is in go17.go and not_go17.go
|
||||
func (cc *ClientConn) shutdown(ctx contextContext) error {
|
||||
if err := cc.sendGoAway(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Wait for all in-flight streams to complete or connection to close
|
||||
done := make(chan error, 1)
|
||||
cancelled := false // guarded by cc.mu
|
||||
go func() {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
for {
|
||||
if len(cc.streams) == 0 || cc.closed {
|
||||
cc.closed = true
|
||||
done <- cc.tconn.Close()
|
||||
break
|
||||
}
|
||||
if cancelled {
|
||||
break
|
||||
}
|
||||
cc.cond.Wait()
|
||||
}
|
||||
}()
|
||||
shutdownEnterWaitStateHook()
|
||||
select {
|
||||
case err := <-done:
|
||||
return err
|
||||
case <-ctx.Done():
|
||||
cc.mu.Lock()
|
||||
// Free the goroutine above
|
||||
cancelled = true
|
||||
cc.cond.Broadcast()
|
||||
cc.mu.Unlock()
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *ClientConn) sendGoAway() error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
if cc.closing {
|
||||
// GOAWAY sent already
|
||||
return nil
|
||||
}
|
||||
// Send a graceful shutdown frame to server
|
||||
maxStreamID := cc.nextStreamID
|
||||
if err := cc.fr.WriteGoAway(maxStreamID, ErrCodeNo, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cc.bw.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Prevent new requests
|
||||
cc.closing = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the client connection immediately.
|
||||
//
|
||||
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
|
||||
func (cc *ClientConn) Close() error {
|
||||
cc.mu.Lock()
|
||||
defer cc.cond.Broadcast()
|
||||
defer cc.mu.Unlock()
|
||||
err := errors.New("http2: client connection force closed via ClientConn.Close")
|
||||
for id, cs := range cc.streams {
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
default:
|
||||
}
|
||||
cs.bufPipe.CloseWithError(err)
|
||||
delete(cc.streams, id)
|
||||
}
|
||||
cc.closed = true
|
||||
return cc.tconn.Close()
|
||||
}
|
||||
|
||||
const maxAllocFrameSize = 512 << 10
|
||||
|
||||
// frameBuffer returns a scratch buffer suitable for writing DATA frames.
|
||||
|
@ -747,7 +872,7 @@ func checkConnHeaders(req *http.Request) error {
|
|||
if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
|
||||
return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
|
||||
}
|
||||
if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "close" && vv[0] != "keep-alive") {
|
||||
if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !strings.EqualFold(vv[0], "close") && !strings.EqualFold(vv[0], "keep-alive")) {
|
||||
return fmt.Errorf("http2: invalid Connection request header: %q", vv)
|
||||
}
|
||||
return nil
|
||||
|
@ -1291,9 +1416,16 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
|||
return nil, errRequestHeaderListSize
|
||||
}
|
||||
|
||||
trace := requestTrace(req)
|
||||
traceHeaders := traceHasWroteHeaderField(trace)
|
||||
|
||||
// Header list size is ok. Write the headers.
|
||||
enumerateHeaders(func(name, value string) {
|
||||
cc.writeHeader(strings.ToLower(name), value)
|
||||
name = strings.ToLower(name)
|
||||
cc.writeHeader(name, value)
|
||||
if traceHeaders {
|
||||
traceWroteHeaderField(trace, name, value)
|
||||
}
|
||||
})
|
||||
|
||||
return cc.hbuf.Bytes(), nil
|
||||
|
@ -1615,8 +1747,7 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
|||
// is the detail.
|
||||
//
|
||||
// As a special case, handleResponse may return (nil, nil) to skip the
|
||||
// frame (currently only used for 100 expect continue). This special
|
||||
// case is going away after Issue 13851 is fixed.
|
||||
// frame (currently only used for 1xx responses).
|
||||
func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) {
|
||||
if f.Truncated {
|
||||
return nil, errResponseHeaderListSize
|
||||
|
@ -1631,15 +1762,6 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
|||
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
|
||||
}
|
||||
|
||||
if statusCode == 100 {
|
||||
traceGot100Continue(cs.trace)
|
||||
if cs.on100 != nil {
|
||||
cs.on100() // forces any write delay timer to fire
|
||||
}
|
||||
cs.pastHeaders = false // do it all again
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
header := make(http.Header)
|
||||
res := &http.Response{
|
||||
Proto: "HTTP/2.0",
|
||||
|
@ -1664,6 +1786,27 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
|||
}
|
||||
}
|
||||
|
||||
if statusCode >= 100 && statusCode <= 199 {
|
||||
cs.num1xx++
|
||||
const max1xxResponses = 5 // arbitrary bound on number of informational responses, same as net/http
|
||||
if cs.num1xx > max1xxResponses {
|
||||
return nil, errors.New("http2: too many 1xx informational responses")
|
||||
}
|
||||
if fn := cs.get1xxTraceFunc(); fn != nil {
|
||||
if err := fn(statusCode, textproto.MIMEHeader(header)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if statusCode == 100 {
|
||||
traceGot100Continue(cs.trace)
|
||||
if cs.on100 != nil {
|
||||
cs.on100() // forces any write delay timer to fire
|
||||
}
|
||||
}
|
||||
cs.pastHeaders = false // do it all again
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
streamEnded := f.StreamEnded()
|
||||
isHead := cs.req.Method == "HEAD"
|
||||
if !streamEnded || isHead {
|
||||
|
|
3848
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
3848
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
541
vendor/golang.org/x/net/http2/writesched_priority_test.go
generated
vendored
541
vendor/golang.org/x/net/http2/writesched_priority_test.go
generated
vendored
|
@ -1,541 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func defaultPriorityWriteScheduler() *priorityWriteScheduler {
|
||||
return NewPriorityWriteScheduler(nil).(*priorityWriteScheduler)
|
||||
}
|
||||
|
||||
func checkPriorityWellFormed(ws *priorityWriteScheduler) error {
|
||||
for id, n := range ws.nodes {
|
||||
if id != n.id {
|
||||
return fmt.Errorf("bad ws.nodes: ws.nodes[%d] = %d", id, n.id)
|
||||
}
|
||||
if n.parent == nil {
|
||||
if n.next != nil || n.prev != nil {
|
||||
return fmt.Errorf("bad node %d: nil parent but prev/next not nil", id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
found := false
|
||||
for k := n.parent.kids; k != nil; k = k.next {
|
||||
if k.id == id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("bad node %d: not found in parent %d kids list", id, n.parent.id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fmtTree(ws *priorityWriteScheduler, fmtNode func(*priorityNode) string) string {
|
||||
var ids []int
|
||||
for _, n := range ws.nodes {
|
||||
ids = append(ids, int(n.id))
|
||||
}
|
||||
sort.Ints(ids)
|
||||
|
||||
var buf bytes.Buffer
|
||||
for _, id := range ids {
|
||||
if buf.Len() != 0 {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
if id == 0 {
|
||||
buf.WriteString(fmtNode(&ws.root))
|
||||
} else {
|
||||
buf.WriteString(fmtNode(ws.nodes[uint32(id)]))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func fmtNodeParentSkipRoot(n *priorityNode) string {
|
||||
switch {
|
||||
case n.id == 0:
|
||||
return ""
|
||||
case n.parent == nil:
|
||||
return fmt.Sprintf("%d{parent:nil}", n.id)
|
||||
default:
|
||||
return fmt.Sprintf("%d{parent:%d}", n.id, n.parent.id)
|
||||
}
|
||||
}
|
||||
|
||||
func fmtNodeWeightParentSkipRoot(n *priorityNode) string {
|
||||
switch {
|
||||
case n.id == 0:
|
||||
return ""
|
||||
case n.parent == nil:
|
||||
return fmt.Sprintf("%d{weight:%d,parent:nil}", n.id, n.weight)
|
||||
default:
|
||||
return fmt.Sprintf("%d{weight:%d,parent:%d}", n.id, n.weight, n.parent.id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityTwoStreams(t *testing.T) {
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{})
|
||||
|
||||
want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After open\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
|
||||
// Move 1's parent to 2.
|
||||
ws.AdjustStream(1, PriorityParam{
|
||||
StreamDep: 2,
|
||||
Weight: 32,
|
||||
Exclusive: false,
|
||||
})
|
||||
want = "1{weight:32,parent:2} 2{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityAdjustExclusiveZero(t *testing.T) {
|
||||
// 1, 2, and 3 are all children of the 0 stream.
|
||||
// Exclusive reprioritization to any of the streams should bring
|
||||
// the rest of the streams under the reprioritized stream.
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{})
|
||||
ws.OpenStream(3, OpenStreamOptions{})
|
||||
|
||||
want := "1{weight:15,parent:0} 2{weight:15,parent:0} 3{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After open\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
|
||||
ws.AdjustStream(2, PriorityParam{
|
||||
StreamDep: 0,
|
||||
Weight: 20,
|
||||
Exclusive: true,
|
||||
})
|
||||
want = "1{weight:15,parent:2} 2{weight:20,parent:0} 3{weight:15,parent:2}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityAdjustOwnParent(t *testing.T) {
|
||||
// Assigning a node as its own parent should have no effect.
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{})
|
||||
ws.AdjustStream(2, PriorityParam{
|
||||
StreamDep: 2,
|
||||
Weight: 20,
|
||||
Exclusive: true,
|
||||
})
|
||||
want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityClosedStreams(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxClosedNodesInTree: 2}).(*priorityWriteScheduler)
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
|
||||
ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
|
||||
|
||||
// Close the first three streams. We lose 1, but keep 2 and 3.
|
||||
ws.CloseStream(1)
|
||||
ws.CloseStream(2)
|
||||
ws.CloseStream(3)
|
||||
|
||||
want := "2{weight:15,parent:0} 3{weight:15,parent:2} 4{weight:15,parent:3}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After close\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Adding a stream as an exclusive child of 1 gives it default
|
||||
// priorities, since 1 is gone.
|
||||
ws.OpenStream(5, OpenStreamOptions{})
|
||||
ws.AdjustStream(5, PriorityParam{StreamDep: 1, Weight: 15, Exclusive: true})
|
||||
|
||||
// Adding a stream as an exclusive child of 2 should work, since 2 is not gone.
|
||||
ws.OpenStream(6, OpenStreamOptions{})
|
||||
ws.AdjustStream(6, PriorityParam{StreamDep: 2, Weight: 15, Exclusive: true})
|
||||
|
||||
want = "2{weight:15,parent:0} 3{weight:15,parent:6} 4{weight:15,parent:3} 5{weight:15,parent:0} 6{weight:15,parent:2}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After add streams\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityClosedStreamsDisabled(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
|
||||
|
||||
// Close the first two streams. We keep only 3.
|
||||
ws.CloseStream(1)
|
||||
ws.CloseStream(2)
|
||||
|
||||
want := "3{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After close\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityIdleStreams(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxIdleNodesInTree: 2}).(*priorityWriteScheduler)
|
||||
ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
|
||||
ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
|
||||
ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
|
||||
ws.OpenStream(4, OpenStreamOptions{})
|
||||
ws.OpenStream(5, OpenStreamOptions{})
|
||||
ws.OpenStream(6, OpenStreamOptions{})
|
||||
ws.AdjustStream(4, PriorityParam{StreamDep: 1, Weight: 15})
|
||||
ws.AdjustStream(5, PriorityParam{StreamDep: 2, Weight: 15})
|
||||
ws.AdjustStream(6, PriorityParam{StreamDep: 3, Weight: 15})
|
||||
|
||||
want := "2{weight:15,parent:0} 3{weight:20,parent:2} 4{weight:15,parent:0} 5{weight:15,parent:2} 6{weight:15,parent:3}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After open\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityIdleStreamsDisabled(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
|
||||
ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
|
||||
ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
|
||||
ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
|
||||
ws.OpenStream(4, OpenStreamOptions{})
|
||||
|
||||
want := "4{weight:15,parent:0}"
|
||||
if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
|
||||
t.Errorf("After open\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrioritySection531NonExclusive(t *testing.T) {
|
||||
// Example from RFC 7540 Section 5.3.1.
|
||||
// A,B,C,D = 1,2,3,4
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(4, OpenStreamOptions{})
|
||||
ws.AdjustStream(4, PriorityParam{
|
||||
StreamDep: 1,
|
||||
Weight: 15,
|
||||
Exclusive: false,
|
||||
})
|
||||
want := "1{parent:0} 2{parent:1} 3{parent:1} 4{parent:1}"
|
||||
if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrioritySection531Exclusive(t *testing.T) {
|
||||
// Example from RFC 7540 Section 5.3.1.
|
||||
// A,B,C,D = 1,2,3,4
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(4, OpenStreamOptions{})
|
||||
ws.AdjustStream(4, PriorityParam{
|
||||
StreamDep: 1,
|
||||
Weight: 15,
|
||||
Exclusive: true,
|
||||
})
|
||||
want := "1{parent:0} 2{parent:4} 3{parent:4} 4{parent:1}"
|
||||
if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func makeSection533Tree() *priorityWriteScheduler {
|
||||
// Initial tree from RFC 7540 Section 5.3.3.
|
||||
// A,B,C,D,E,F = 1,2,3,4,5,6
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
|
||||
return ws
|
||||
}
|
||||
|
||||
func TestPrioritySection533NonExclusive(t *testing.T) {
|
||||
// Example from RFC 7540 Section 5.3.3.
|
||||
// A,B,C,D,E,F = 1,2,3,4,5,6
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
|
||||
ws.AdjustStream(1, PriorityParam{
|
||||
StreamDep: 4,
|
||||
Weight: 15,
|
||||
Exclusive: false,
|
||||
})
|
||||
want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:4}"
|
||||
if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrioritySection533Exclusive(t *testing.T) {
|
||||
// Example from RFC 7540 Section 5.3.3.
|
||||
// A,B,C,D,E,F = 1,2,3,4,5,6
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
|
||||
ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
|
||||
ws.AdjustStream(1, PriorityParam{
|
||||
StreamDep: 4,
|
||||
Weight: 15,
|
||||
Exclusive: true,
|
||||
})
|
||||
want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:1}"
|
||||
if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
|
||||
t.Errorf("After adjust\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
if err := checkPriorityWellFormed(ws); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkPopAll(ws WriteScheduler, order []uint32) error {
|
||||
for k, id := range order {
|
||||
wr, ok := ws.Pop()
|
||||
if !ok {
|
||||
return fmt.Errorf("Pop[%d]: got ok=false, want %d (order=%v)", k, id, order)
|
||||
}
|
||||
if got := wr.StreamID(); got != id {
|
||||
return fmt.Errorf("Pop[%d]: got %v, want %d (order=%v)", k, got, id, order)
|
||||
}
|
||||
}
|
||||
wr, ok := ws.Pop()
|
||||
if ok {
|
||||
return fmt.Errorf("Pop[%d]: got %v, want ok=false (order=%v)", len(order), wr.StreamID(), order)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPriorityPopFrom533Tree(t *testing.T) {
|
||||
ws := makeSection533Tree()
|
||||
|
||||
ws.Push(makeWriteHeadersRequest(3 /*C*/))
|
||||
ws.Push(makeWriteNonStreamRequest())
|
||||
ws.Push(makeWriteHeadersRequest(5 /*E*/))
|
||||
ws.Push(makeWriteHeadersRequest(1 /*A*/))
|
||||
t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
|
||||
|
||||
if err := checkPopAll(ws, []uint32{0 /*NonStream*/, 1, 3, 5}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityPopFromLinearTree(t *testing.T) {
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
|
||||
ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
|
||||
|
||||
ws.Push(makeWriteHeadersRequest(3))
|
||||
ws.Push(makeWriteHeadersRequest(4))
|
||||
ws.Push(makeWriteHeadersRequest(1))
|
||||
ws.Push(makeWriteHeadersRequest(2))
|
||||
ws.Push(makeWriteNonStreamRequest())
|
||||
ws.Push(makeWriteNonStreamRequest())
|
||||
t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
|
||||
|
||||
if err := checkPopAll(ws, []uint32{0, 0 /*NonStreams*/, 1, 2, 3, 4}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityFlowControl(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: false})
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
|
||||
sc := &serverConn{maxFrameSize: 16}
|
||||
st1 := &stream{id: 1, sc: sc}
|
||||
st2 := &stream{id: 2, sc: sc}
|
||||
|
||||
ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 16), false}, st1, nil})
|
||||
ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 16), false}, st2, nil})
|
||||
ws.AdjustStream(2, PriorityParam{StreamDep: 1})
|
||||
|
||||
// No flow-control bytes available.
|
||||
if wr, ok := ws.Pop(); ok {
|
||||
t.Fatalf("Pop(limited by flow control)=%v,true, want false", wr)
|
||||
}
|
||||
|
||||
// Add enough flow-control bytes to write st2 in two Pop calls.
|
||||
// Should write data from st2 even though it's lower priority than st1.
|
||||
for i := 1; i <= 2; i++ {
|
||||
st2.flow.add(8)
|
||||
wr, ok := ws.Pop()
|
||||
if !ok {
|
||||
t.Fatalf("Pop(%d)=false, want true", i)
|
||||
}
|
||||
if got, want := wr.DataSize(), 8; got != want {
|
||||
t.Fatalf("Pop(%d)=%d bytes, want %d bytes", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityThrottleOutOfOrderWrites(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: true})
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
|
||||
|
||||
sc := &serverConn{maxFrameSize: 4096}
|
||||
st1 := &stream{id: 1, sc: sc}
|
||||
st2 := &stream{id: 2, sc: sc}
|
||||
st1.flow.add(4096)
|
||||
st2.flow.add(4096)
|
||||
ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 4096), false}, st2, nil})
|
||||
ws.AdjustStream(2, PriorityParam{StreamDep: 1})
|
||||
|
||||
// We have enough flow-control bytes to write st2 in a single Pop call.
|
||||
// However, due to out-of-order write throttling, the first call should
|
||||
// only write 1KB.
|
||||
wr, ok := ws.Pop()
|
||||
if !ok {
|
||||
t.Fatalf("Pop(st2.first)=false, want true")
|
||||
}
|
||||
if got, want := wr.StreamID(), uint32(2); got != want {
|
||||
t.Fatalf("Pop(st2.first)=stream %d, want stream %d", got, want)
|
||||
}
|
||||
if got, want := wr.DataSize(), 1024; got != want {
|
||||
t.Fatalf("Pop(st2.first)=%d bytes, want %d bytes", got, want)
|
||||
}
|
||||
|
||||
// Now add data on st1. This should take precedence.
|
||||
ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 4096), false}, st1, nil})
|
||||
wr, ok = ws.Pop()
|
||||
if !ok {
|
||||
t.Fatalf("Pop(st1)=false, want true")
|
||||
}
|
||||
if got, want := wr.StreamID(), uint32(1); got != want {
|
||||
t.Fatalf("Pop(st1)=stream %d, want stream %d", got, want)
|
||||
}
|
||||
if got, want := wr.DataSize(), 4096; got != want {
|
||||
t.Fatalf("Pop(st1)=%d bytes, want %d bytes", got, want)
|
||||
}
|
||||
|
||||
// Should go back to writing 1KB from st2.
|
||||
wr, ok = ws.Pop()
|
||||
if !ok {
|
||||
t.Fatalf("Pop(st2.last)=false, want true")
|
||||
}
|
||||
if got, want := wr.StreamID(), uint32(2); got != want {
|
||||
t.Fatalf("Pop(st2.last)=stream %d, want stream %d", got, want)
|
||||
}
|
||||
if got, want := wr.DataSize(), 1024; got != want {
|
||||
t.Fatalf("Pop(st2.last)=%d bytes, want %d bytes", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityWeights(t *testing.T) {
|
||||
ws := defaultPriorityWriteScheduler()
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.OpenStream(2, OpenStreamOptions{})
|
||||
|
||||
sc := &serverConn{maxFrameSize: 8}
|
||||
st1 := &stream{id: 1, sc: sc}
|
||||
st2 := &stream{id: 2, sc: sc}
|
||||
st1.flow.add(40)
|
||||
st2.flow.add(40)
|
||||
|
||||
ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 40), false}, st1, nil})
|
||||
ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 40), false}, st2, nil})
|
||||
ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 34})
|
||||
ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 9})
|
||||
|
||||
// st1 gets 3.5x the bandwidth of st2 (3.5 = (34+1)/(9+1)).
|
||||
// The maximum frame size is 8 bytes. The write sequence should be:
|
||||
// st1, total bytes so far is (st1=8, st=0)
|
||||
// st2, total bytes so far is (st1=8, st=8)
|
||||
// st1, total bytes so far is (st1=16, st=8)
|
||||
// st1, total bytes so far is (st1=24, st=8) // 3x bandwidth
|
||||
// st1, total bytes so far is (st1=32, st=8) // 4x bandwidth
|
||||
// st2, total bytes so far is (st1=32, st=16) // 2x bandwidth
|
||||
// st1, total bytes so far is (st1=40, st=16)
|
||||
// st2, total bytes so far is (st1=40, st=24)
|
||||
// st2, total bytes so far is (st1=40, st=32)
|
||||
// st2, total bytes so far is (st1=40, st=40)
|
||||
if err := checkPopAll(ws, []uint32{1, 2, 1, 1, 1, 2, 1, 2, 2, 2}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityRstStreamOnNonOpenStreams(t *testing.T) {
|
||||
ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{
|
||||
MaxClosedNodesInTree: 0,
|
||||
MaxIdleNodesInTree: 0,
|
||||
})
|
||||
ws.OpenStream(1, OpenStreamOptions{})
|
||||
ws.CloseStream(1)
|
||||
ws.Push(FrameWriteRequest{write: streamError(1, ErrCodeProtocol)})
|
||||
ws.Push(FrameWriteRequest{write: streamError(2, ErrCodeProtocol)})
|
||||
|
||||
if err := checkPopAll(ws, []uint32{1, 2}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
44
vendor/golang.org/x/net/http2/writesched_random_test.go
generated
vendored
44
vendor/golang.org/x/net/http2/writesched_random_test.go
generated
vendored
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRandomScheduler(t *testing.T) {
|
||||
ws := NewRandomWriteScheduler()
|
||||
ws.Push(makeWriteHeadersRequest(3))
|
||||
ws.Push(makeWriteHeadersRequest(4))
|
||||
ws.Push(makeWriteHeadersRequest(1))
|
||||
ws.Push(makeWriteHeadersRequest(2))
|
||||
ws.Push(makeWriteNonStreamRequest())
|
||||
ws.Push(makeWriteNonStreamRequest())
|
||||
|
||||
// Pop all frames. Should get the non-stream requests first,
|
||||
// followed by the stream requests in any order.
|
||||
var order []FrameWriteRequest
|
||||
for {
|
||||
wr, ok := ws.Pop()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
order = append(order, wr)
|
||||
}
|
||||
t.Logf("got frames: %v", order)
|
||||
if len(order) != 6 {
|
||||
t.Fatalf("got %d frames, expected 6", len(order))
|
||||
}
|
||||
if order[0].StreamID() != 0 || order[1].StreamID() != 0 {
|
||||
t.Fatal("expected non-stream frames first", order[0], order[1])
|
||||
}
|
||||
got := make(map[uint32]bool)
|
||||
for _, wr := range order[2:] {
|
||||
got[wr.StreamID()] = true
|
||||
}
|
||||
for id := uint32(1); id <= 4; id++ {
|
||||
if !got[id] {
|
||||
t.Errorf("frame not found for stream %d", id)
|
||||
}
|
||||
}
|
||||
}
|
125
vendor/golang.org/x/net/http2/writesched_test.go
generated
vendored
125
vendor/golang.org/x/net/http2/writesched_test.go
generated
vendored
|
@ -1,125 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func makeWriteNonStreamRequest() FrameWriteRequest {
|
||||
return FrameWriteRequest{writeSettingsAck{}, nil, nil}
|
||||
}
|
||||
|
||||
func makeWriteHeadersRequest(streamID uint32) FrameWriteRequest {
|
||||
st := &stream{id: streamID}
|
||||
return FrameWriteRequest{&writeResHeaders{streamID: streamID, httpResCode: 200}, st, nil}
|
||||
}
|
||||
|
||||
func checkConsume(wr FrameWriteRequest, nbytes int32, want []FrameWriteRequest) error {
|
||||
consumed, rest, n := wr.Consume(nbytes)
|
||||
var wantConsumed, wantRest FrameWriteRequest
|
||||
switch len(want) {
|
||||
case 0:
|
||||
case 1:
|
||||
wantConsumed = want[0]
|
||||
case 2:
|
||||
wantConsumed = want[0]
|
||||
wantRest = want[1]
|
||||
}
|
||||
if !reflect.DeepEqual(consumed, wantConsumed) || !reflect.DeepEqual(rest, wantRest) || n != len(want) {
|
||||
return fmt.Errorf("got %v, %v, %v\nwant %v, %v, %v", consumed, rest, n, wantConsumed, wantRest, len(want))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestFrameWriteRequestNonData(t *testing.T) {
|
||||
wr := makeWriteNonStreamRequest()
|
||||
if got, want := wr.DataSize(), 0; got != want {
|
||||
t.Errorf("DataSize: got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
// Non-DATA frames are always consumed whole.
|
||||
if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
|
||||
t.Errorf("Consume:\n%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrameWriteRequestData(t *testing.T) {
|
||||
st := &stream{
|
||||
id: 1,
|
||||
sc: &serverConn{maxFrameSize: 16},
|
||||
}
|
||||
const size = 32
|
||||
wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)}
|
||||
if got, want := wr.DataSize(), size; got != want {
|
||||
t.Errorf("DataSize: got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
// No flow-control bytes available: cannot consume anything.
|
||||
if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil {
|
||||
t.Errorf("Consume(limited by flow control):\n%v", err)
|
||||
}
|
||||
|
||||
// Add enough flow-control bytes to consume the entire frame,
|
||||
// but we're now restricted by st.sc.maxFrameSize.
|
||||
st.flow.add(size)
|
||||
want := []FrameWriteRequest{
|
||||
{
|
||||
write: &writeData{st.id, make([]byte, st.sc.maxFrameSize), false},
|
||||
stream: st,
|
||||
done: nil,
|
||||
},
|
||||
{
|
||||
write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true},
|
||||
stream: st,
|
||||
done: wr.done,
|
||||
},
|
||||
}
|
||||
if err := checkConsume(wr, math.MaxInt32, want); err != nil {
|
||||
t.Errorf("Consume(limited by maxFrameSize):\n%v", err)
|
||||
}
|
||||
rest := want[1]
|
||||
|
||||
// Consume 8 bytes from the remaining frame.
|
||||
want = []FrameWriteRequest{
|
||||
{
|
||||
write: &writeData{st.id, make([]byte, 8), false},
|
||||
stream: st,
|
||||
done: nil,
|
||||
},
|
||||
{
|
||||
write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
|
||||
stream: st,
|
||||
done: wr.done,
|
||||
},
|
||||
}
|
||||
if err := checkConsume(rest, 8, want); err != nil {
|
||||
t.Errorf("Consume(8):\n%v", err)
|
||||
}
|
||||
rest = want[1]
|
||||
|
||||
// Consume all remaining bytes.
|
||||
want = []FrameWriteRequest{
|
||||
{
|
||||
write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
|
||||
stream: st,
|
||||
done: wr.done,
|
||||
},
|
||||
}
|
||||
if err := checkConsume(rest, math.MaxInt32, want); err != nil {
|
||||
t.Errorf("Consume(remainder):\n%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrameWriteRequest_StreamID(t *testing.T) {
|
||||
const streamID = 123
|
||||
wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)}
|
||||
if got := wr.StreamID(); got != streamID {
|
||||
t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID)
|
||||
}
|
||||
}
|
356
vendor/golang.org/x/net/http2/z_spec_test.go
generated
vendored
356
vendor/golang.org/x/net/http2/z_spec_test.go
generated
vendored
|
@ -1,356 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var coverSpec = flag.Bool("coverspec", false, "Run spec coverage tests")
|
||||
|
||||
// The global map of sentence coverage for the http2 spec.
|
||||
var defaultSpecCoverage specCoverage
|
||||
|
||||
var loadSpecOnce sync.Once
|
||||
|
||||
func loadSpec() {
|
||||
if f, err := os.Open("testdata/draft-ietf-httpbis-http2.xml"); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
defaultSpecCoverage = readSpecCov(f)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// covers marks all sentences for section sec in defaultSpecCoverage. Sentences not
|
||||
// "covered" will be included in report outputted by TestSpecCoverage.
|
||||
func covers(sec, sentences string) {
|
||||
loadSpecOnce.Do(loadSpec)
|
||||
defaultSpecCoverage.cover(sec, sentences)
|
||||
}
|
||||
|
||||
type specPart struct {
|
||||
section string
|
||||
sentence string
|
||||
}
|
||||
|
||||
func (ss specPart) Less(oo specPart) bool {
|
||||
atoi := func(s string) int {
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
a := strings.Split(ss.section, ".")
|
||||
b := strings.Split(oo.section, ".")
|
||||
for len(a) > 0 {
|
||||
if len(b) == 0 {
|
||||
return false
|
||||
}
|
||||
x, y := atoi(a[0]), atoi(b[0])
|
||||
if x == y {
|
||||
a, b = a[1:], b[1:]
|
||||
continue
|
||||
}
|
||||
return x < y
|
||||
}
|
||||
if len(b) > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type bySpecSection []specPart
|
||||
|
||||
func (a bySpecSection) Len() int { return len(a) }
|
||||
func (a bySpecSection) Less(i, j int) bool { return a[i].Less(a[j]) }
|
||||
func (a bySpecSection) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type specCoverage struct {
|
||||
coverage map[specPart]bool
|
||||
d *xml.Decoder
|
||||
}
|
||||
|
||||
func joinSection(sec []int) string {
|
||||
s := fmt.Sprintf("%d", sec[0])
|
||||
for _, n := range sec[1:] {
|
||||
s = fmt.Sprintf("%s.%d", s, n)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (sc specCoverage) readSection(sec []int) {
|
||||
var (
|
||||
buf = new(bytes.Buffer)
|
||||
sub = 0
|
||||
)
|
||||
for {
|
||||
tk, err := sc.d.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
switch v := tk.(type) {
|
||||
case xml.StartElement:
|
||||
if skipElement(v) {
|
||||
if err := sc.d.Skip(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if v.Name.Local == "section" {
|
||||
sub++
|
||||
}
|
||||
break
|
||||
}
|
||||
switch v.Name.Local {
|
||||
case "section":
|
||||
sub++
|
||||
sc.readSection(append(sec, sub))
|
||||
case "xref":
|
||||
buf.Write(sc.readXRef(v))
|
||||
}
|
||||
case xml.CharData:
|
||||
if len(sec) == 0 {
|
||||
break
|
||||
}
|
||||
buf.Write(v)
|
||||
case xml.EndElement:
|
||||
if v.Name.Local == "section" {
|
||||
sc.addSentences(joinSection(sec), buf.String())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sc specCoverage) readXRef(se xml.StartElement) []byte {
|
||||
var b []byte
|
||||
for {
|
||||
tk, err := sc.d.Token()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch v := tk.(type) {
|
||||
case xml.CharData:
|
||||
if b != nil {
|
||||
panic("unexpected CharData")
|
||||
}
|
||||
b = []byte(string(v))
|
||||
case xml.EndElement:
|
||||
if v.Name.Local != "xref" {
|
||||
panic("expected </xref>")
|
||||
}
|
||||
if b != nil {
|
||||
return b
|
||||
}
|
||||
sig := attrSig(se)
|
||||
switch sig {
|
||||
case "target":
|
||||
return []byte(fmt.Sprintf("[%s]", attrValue(se, "target")))
|
||||
case "fmt-of,rel,target", "fmt-,,rel,target":
|
||||
return []byte(fmt.Sprintf("[%s, %s]", attrValue(se, "target"), attrValue(se, "rel")))
|
||||
case "fmt-of,sec,target", "fmt-,,sec,target":
|
||||
return []byte(fmt.Sprintf("[section %s of %s]", attrValue(se, "sec"), attrValue(se, "target")))
|
||||
case "fmt-of,rel,sec,target":
|
||||
return []byte(fmt.Sprintf("[section %s of %s, %s]", attrValue(se, "sec"), attrValue(se, "target"), attrValue(se, "rel")))
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown attribute signature %q in %#v", sig, fmt.Sprintf("%#v", se)))
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected tag %q", v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var skipAnchor = map[string]bool{
|
||||
"intro": true,
|
||||
"Overview": true,
|
||||
}
|
||||
|
||||
var skipTitle = map[string]bool{
|
||||
"Acknowledgements": true,
|
||||
"Change Log": true,
|
||||
"Document Organization": true,
|
||||
"Conventions and Terminology": true,
|
||||
}
|
||||
|
||||
func skipElement(s xml.StartElement) bool {
|
||||
switch s.Name.Local {
|
||||
case "artwork":
|
||||
return true
|
||||
case "section":
|
||||
for _, attr := range s.Attr {
|
||||
switch attr.Name.Local {
|
||||
case "anchor":
|
||||
if skipAnchor[attr.Value] || strings.HasPrefix(attr.Value, "changes.since.") {
|
||||
return true
|
||||
}
|
||||
case "title":
|
||||
if skipTitle[attr.Value] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func readSpecCov(r io.Reader) specCoverage {
|
||||
sc := specCoverage{
|
||||
coverage: map[specPart]bool{},
|
||||
d: xml.NewDecoder(r)}
|
||||
sc.readSection(nil)
|
||||
return sc
|
||||
}
|
||||
|
||||
func (sc specCoverage) addSentences(sec string, sentence string) {
|
||||
for _, s := range parseSentences(sentence) {
|
||||
sc.coverage[specPart{sec, s}] = false
|
||||
}
|
||||
}
|
||||
|
||||
func (sc specCoverage) cover(sec string, sentence string) {
|
||||
for _, s := range parseSentences(sentence) {
|
||||
p := specPart{sec, s}
|
||||
if _, ok := sc.coverage[p]; !ok {
|
||||
panic(fmt.Sprintf("Not found in spec: %q, %q", sec, s))
|
||||
}
|
||||
sc.coverage[specPart{sec, s}] = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var whitespaceRx = regexp.MustCompile(`\s+`)
|
||||
|
||||
func parseSentences(sens string) []string {
|
||||
sens = strings.TrimSpace(sens)
|
||||
if sens == "" {
|
||||
return nil
|
||||
}
|
||||
ss := strings.Split(whitespaceRx.ReplaceAllString(sens, " "), ". ")
|
||||
for i, s := range ss {
|
||||
s = strings.TrimSpace(s)
|
||||
if !strings.HasSuffix(s, ".") {
|
||||
s += "."
|
||||
}
|
||||
ss[i] = s
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
func TestSpecParseSentences(t *testing.T) {
|
||||
tests := []struct {
|
||||
ss string
|
||||
want []string
|
||||
}{
|
||||
{"Sentence 1. Sentence 2.",
|
||||
[]string{
|
||||
"Sentence 1.",
|
||||
"Sentence 2.",
|
||||
}},
|
||||
{"Sentence 1. \nSentence 2.\tSentence 3.",
|
||||
[]string{
|
||||
"Sentence 1.",
|
||||
"Sentence 2.",
|
||||
"Sentence 3.",
|
||||
}},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := parseSentences(tt.ss)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("%d: got = %q, want %q", i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpecCoverage(t *testing.T) {
|
||||
if !*coverSpec {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
loadSpecOnce.Do(loadSpec)
|
||||
|
||||
var (
|
||||
list []specPart
|
||||
cv = defaultSpecCoverage.coverage
|
||||
total = len(cv)
|
||||
complete = 0
|
||||
)
|
||||
|
||||
for sp, touched := range defaultSpecCoverage.coverage {
|
||||
if touched {
|
||||
complete++
|
||||
} else {
|
||||
list = append(list, sp)
|
||||
}
|
||||
}
|
||||
sort.Stable(bySpecSection(list))
|
||||
|
||||
if testing.Short() && len(list) > 5 {
|
||||
list = list[:5]
|
||||
}
|
||||
|
||||
for _, p := range list {
|
||||
t.Errorf("\tSECTION %s: %s", p.section, p.sentence)
|
||||
}
|
||||
|
||||
t.Logf("%d/%d (%d%%) sentences covered", complete, total, (complete/total)*100)
|
||||
}
|
||||
|
||||
func attrSig(se xml.StartElement) string {
|
||||
var names []string
|
||||
for _, attr := range se.Attr {
|
||||
if attr.Name.Local == "fmt" {
|
||||
names = append(names, "fmt-"+attr.Value)
|
||||
} else {
|
||||
names = append(names, attr.Name.Local)
|
||||
}
|
||||
}
|
||||
sort.Strings(names)
|
||||
return strings.Join(names, ",")
|
||||
}
|
||||
|
||||
func attrValue(se xml.StartElement, attr string) string {
|
||||
for _, a := range se.Attr {
|
||||
if a.Name.Local == attr {
|
||||
return a.Value
|
||||
}
|
||||
}
|
||||
panic("unknown attribute " + attr)
|
||||
}
|
||||
|
||||
func TestSpecPartLess(t *testing.T) {
|
||||
tests := []struct {
|
||||
sec1, sec2 string
|
||||
want bool
|
||||
}{
|
||||
{"6.2.1", "6.2", false},
|
||||
{"6.2", "6.2.1", true},
|
||||
{"6.10", "6.10.1", true},
|
||||
{"6.10", "6.1.1", false}, // 10, not 1
|
||||
{"6.1", "6.1", false}, // equal, so not less
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got := (specPart{tt.sec1, "foo"}).Less(specPart{tt.sec2, "foo"})
|
||||
if got != tt.want {
|
||||
t.Errorf("Less(%q, %q) = %v; want %v", tt.sec1, tt.sec2, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
70
vendor/golang.org/x/net/idna/example_test.go
generated
vendored
70
vendor/golang.org/x/net/idna/example_test.go
generated
vendored
|
@ -1,70 +0,0 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
func ExampleProfile() {
|
||||
// Raw Punycode has no restrictions and does no mappings.
|
||||
fmt.Println(idna.ToASCII(""))
|
||||
fmt.Println(idna.ToASCII("*.faß.com"))
|
||||
fmt.Println(idna.Punycode.ToASCII("*.faß.com"))
|
||||
|
||||
// Rewrite IDN for lookup. This (currently) uses transitional mappings to
|
||||
// find a balance between IDNA2003 and IDNA2008 compatibility.
|
||||
fmt.Println(idna.Lookup.ToASCII(""))
|
||||
fmt.Println(idna.Lookup.ToASCII("www.faß.com"))
|
||||
|
||||
// Convert an IDN to ASCII for registration purposes. This changes the
|
||||
// encoding, but reports an error if the input was illformed.
|
||||
fmt.Println(idna.Registration.ToASCII(""))
|
||||
fmt.Println(idna.Registration.ToASCII("www.faß.com"))
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// <nil>
|
||||
// www.fass.com <nil>
|
||||
// idna: invalid label ""
|
||||
// www.xn--fa-hia.com <nil>
|
||||
}
|
||||
|
||||
func ExampleNew() {
|
||||
var p *idna.Profile
|
||||
|
||||
// Raw Punycode has no restrictions and does no mappings.
|
||||
p = idna.New()
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Do mappings. Note that star is not allowed in a DNS lookup.
|
||||
p = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true)) // Map ß -> ss
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Lookup for registration. Also does not allow '*'.
|
||||
p = idna.New(idna.ValidateForRegistration())
|
||||
fmt.Println(p.ToUnicode("*.faß.com"))
|
||||
|
||||
// Set up a profile maps for lookup, but allows wild cards.
|
||||
p = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true), // Map ß -> ss
|
||||
idna.StrictDomainName(false)) // Set more permissive ASCII rules.
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Output:
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// *.fass.com idna: disallowed rune U+002A
|
||||
// *.faß.com idna: disallowed rune U+002A
|
||||
// *.fass.com <nil>
|
||||
}
|
108
vendor/golang.org/x/net/idna/idna_test.go
generated
vendored
108
vendor/golang.org/x/net/idna/idna_test.go
generated
vendored
|
@ -1,108 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var idnaTestCases = [...]struct {
|
||||
ascii, unicode string
|
||||
}{
|
||||
// Labels.
|
||||
{"books", "books"},
|
||||
{"xn--bcher-kva", "bücher"},
|
||||
|
||||
// Domains.
|
||||
{"foo--xn--bar.org", "foo--xn--bar.org"},
|
||||
{"golang.org", "golang.org"},
|
||||
{"example.xn--p1ai", "example.рф"},
|
||||
{"xn--czrw28b.tw", "商業.tw"},
|
||||
{"www.xn--mller-kva.de", "www.müller.de"},
|
||||
}
|
||||
|
||||
func TestIDNA(t *testing.T) {
|
||||
for _, tc := range idnaTestCases {
|
||||
if a, err := ToASCII(tc.unicode); err != nil {
|
||||
t.Errorf("ToASCII(%q): %v", tc.unicode, err)
|
||||
} else if a != tc.ascii {
|
||||
t.Errorf("ToASCII(%q): got %q, want %q", tc.unicode, a, tc.ascii)
|
||||
}
|
||||
|
||||
if u, err := ToUnicode(tc.ascii); err != nil {
|
||||
t.Errorf("ToUnicode(%q): %v", tc.ascii, err)
|
||||
} else if u != tc.unicode {
|
||||
t.Errorf("ToUnicode(%q): got %q, want %q", tc.ascii, u, tc.unicode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDNASeparators(t *testing.T) {
|
||||
type subCase struct {
|
||||
unicode string
|
||||
wantASCII string
|
||||
wantErr bool
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
profile *Profile
|
||||
subCases []subCase
|
||||
}{
|
||||
{
|
||||
name: "Punycode", profile: Punycode,
|
||||
subCases: []subCase{
|
||||
{"example\u3002jp", "xn--examplejp-ck3h", false},
|
||||
{"東京\uFF0Ejp", "xn--jp-l92cn98g071o", false},
|
||||
{"大阪\uFF61jp", "xn--jp-ku9cz72u463f", false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Lookup", profile: Lookup,
|
||||
subCases: []subCase{
|
||||
{"example\u3002jp", "example.jp", false},
|
||||
{"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
|
||||
{"大阪\uFF61jp", "xn--pssu33l.jp", false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Display", profile: Display,
|
||||
subCases: []subCase{
|
||||
{"example\u3002jp", "example.jp", false},
|
||||
{"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
|
||||
{"大阪\uFF61jp", "xn--pssu33l.jp", false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Registration", profile: Registration,
|
||||
subCases: []subCase{
|
||||
{"example\u3002jp", "", true},
|
||||
{"東京\uFF0Ejp", "", true},
|
||||
{"大阪\uFF61jp", "", true},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
for _, c := range tc.subCases {
|
||||
gotA, err := tc.profile.ToASCII(c.unicode)
|
||||
if c.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("ToASCII(%q): got no error, but an error expected", c.unicode)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("ToASCII(%q): got err=%v, but no error expected", c.unicode, err)
|
||||
} else if gotA != c.wantASCII {
|
||||
t.Errorf("ToASCII(%q): got %q, want %q", c.unicode, gotA, c.wantASCII)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode
|
||||
// return errors.
|
198
vendor/golang.org/x/net/idna/punycode_test.go
generated
vendored
198
vendor/golang.org/x/net/idna/punycode_test.go
generated
vendored
|
@ -1,198 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var punycodeTestCases = [...]struct {
|
||||
s, encoded string
|
||||
}{
|
||||
{"", ""},
|
||||
{"-", "--"},
|
||||
{"-a", "-a-"},
|
||||
{"-a-", "-a--"},
|
||||
{"a", "a-"},
|
||||
{"a-", "a--"},
|
||||
{"a-b", "a-b-"},
|
||||
{"books", "books-"},
|
||||
{"bücher", "bcher-kva"},
|
||||
{"Hello世界", "Hello-ck1hg65u"},
|
||||
{"ü", "tda"},
|
||||
{"üý", "tdac"},
|
||||
|
||||
// The test cases below come from RFC 3492 section 7.1 with Errata 3026.
|
||||
{
|
||||
// (A) Arabic (Egyptian).
|
||||
"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
|
||||
"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
|
||||
"egbpdaj6bu4bxfgehfvwxn",
|
||||
},
|
||||
{
|
||||
// (B) Chinese (simplified).
|
||||
"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
|
||||
"ihqwcrb4cv8a8dqg056pqjye",
|
||||
},
|
||||
{
|
||||
// (C) Chinese (traditional).
|
||||
"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
|
||||
"ihqwctvzc91f659drss3x8bo0yb",
|
||||
},
|
||||
{
|
||||
// (D) Czech.
|
||||
"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
|
||||
"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
|
||||
"\u0065\u0073\u006B\u0079",
|
||||
"Proprostnemluvesky-uyb24dma41a",
|
||||
},
|
||||
{
|
||||
// (E) Hebrew.
|
||||
"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
|
||||
"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
|
||||
"\u05D1\u05E8\u05D9\u05EA",
|
||||
"4dbcagdahymbxekheh6e0a7fei0b",
|
||||
},
|
||||
{
|
||||
// (F) Hindi (Devanagari).
|
||||
"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
|
||||
"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
|
||||
"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
|
||||
"\u0939\u0948\u0902",
|
||||
"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
|
||||
},
|
||||
{
|
||||
// (G) Japanese (kanji and hiragana).
|
||||
"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
|
||||
"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
|
||||
"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
|
||||
},
|
||||
{
|
||||
// (H) Korean (Hangul syllables).
|
||||
"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
|
||||
"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
|
||||
"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
|
||||
"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
|
||||
"psd879ccm6fea98c",
|
||||
},
|
||||
{
|
||||
// (I) Russian (Cyrillic).
|
||||
"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
|
||||
"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
|
||||
"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
|
||||
"\u0438",
|
||||
"b1abfaaepdrnnbgefbadotcwatmq2g4l",
|
||||
},
|
||||
{
|
||||
// (J) Spanish.
|
||||
"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
|
||||
"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
|
||||
"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
|
||||
"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
|
||||
"\u0061\u00F1\u006F\u006C",
|
||||
"PorqunopuedensimplementehablarenEspaol-fmd56a",
|
||||
},
|
||||
{
|
||||
// (K) Vietnamese.
|
||||
"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
|
||||
"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
|
||||
"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
|
||||
"\u0056\u0069\u1EC7\u0074",
|
||||
"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
|
||||
},
|
||||
{
|
||||
// (L) 3<nen>B<gumi><kinpachi><sensei>.
|
||||
"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
|
||||
"3B-ww4c5e180e575a65lsy2b",
|
||||
},
|
||||
{
|
||||
// (M) <amuro><namie>-with-SUPER-MONKEYS.
|
||||
"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
|
||||
"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
|
||||
"\u004F\u004E\u004B\u0045\u0059\u0053",
|
||||
"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
|
||||
},
|
||||
{
|
||||
// (N) Hello-Another-Way-<sorezore><no><basho>.
|
||||
"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
|
||||
"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
|
||||
"\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
|
||||
"Hello-Another-Way--fc4qua05auwb3674vfr0b",
|
||||
},
|
||||
{
|
||||
// (O) <hitotsu><yane><no><shita>2.
|
||||
"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
|
||||
"2-u9tlzr9756bt3uc0v",
|
||||
},
|
||||
{
|
||||
// (P) Maji<de>Koi<suru>5<byou><mae>
|
||||
"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
|
||||
"\u308B\u0035\u79D2\u524D",
|
||||
"MajiKoi5-783gue6qz075azm5e",
|
||||
},
|
||||
{
|
||||
// (Q) <pafii>de<runba>
|
||||
"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
|
||||
"de-jg4avhby1noc0d",
|
||||
},
|
||||
{
|
||||
// (R) <sono><supiido><de>
|
||||
"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
|
||||
"d9juau41awczczp",
|
||||
},
|
||||
{
|
||||
// (S) -> $1.00 <-
|
||||
"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
|
||||
"\u003C\u002D",
|
||||
"-> $1.00 <--",
|
||||
},
|
||||
}
|
||||
|
||||
func TestPunycode(t *testing.T) {
|
||||
for _, tc := range punycodeTestCases {
|
||||
if got, err := decode(tc.encoded); err != nil {
|
||||
t.Errorf("decode(%q): %v", tc.encoded, err)
|
||||
} else if got != tc.s {
|
||||
t.Errorf("decode(%q): got %q, want %q", tc.encoded, got, tc.s)
|
||||
}
|
||||
|
||||
if got, err := encode("", tc.s); err != nil {
|
||||
t.Errorf(`encode("", %q): %v`, tc.s, err)
|
||||
} else if got != tc.encoded {
|
||||
t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var punycodeErrorTestCases = [...]string{
|
||||
"decode -", // A sole '-' is invalid.
|
||||
"decode foo\x00bar", // '\x00' is not in [0-9A-Za-z].
|
||||
"decode foo#bar", // '#' is not in [0-9A-Za-z].
|
||||
"decode foo\u00A3bar", // '\u00A3' is not in [0-9A-Za-z].
|
||||
"decode 9", // "9a" decodes to codepoint \u00A3; "9" is truncated.
|
||||
"decode 99999a", // "99999a" decodes to codepoint \U0048A3C1, which is > \U0010FFFF.
|
||||
"decode 9999999999a", // "9999999999a" overflows the int32 calculation.
|
||||
|
||||
"encode " + strings.Repeat("x", 65536) + "\uff00", // int32 overflow.
|
||||
}
|
||||
|
||||
func TestPunycodeErrors(t *testing.T) {
|
||||
for _, tc := range punycodeErrorTestCases {
|
||||
var err error
|
||||
switch {
|
||||
case strings.HasPrefix(tc, "decode "):
|
||||
_, err = decode(tc[7:])
|
||||
case strings.HasPrefix(tc, "encode "):
|
||||
_, err = encode("", tc[7:])
|
||||
}
|
||||
if err == nil {
|
||||
if len(tc) > 256 {
|
||||
tc = tc[:100] + "..." + tc[len(tc)-100:]
|
||||
}
|
||||
t.Errorf("no error for %s", tc)
|
||||
}
|
||||
}
|
||||
}
|
259
vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
generated
vendored
259
vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
generated
vendored
|
@ -1,259 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package socket_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/internal/socket"
|
||||
)
|
||||
|
||||
type mockControl struct {
|
||||
Level int
|
||||
Type int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func TestControlMessage(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
cs []mockControl
|
||||
}{
|
||||
{
|
||||
[]mockControl{
|
||||
{Level: 1, Type: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]mockControl{
|
||||
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]mockControl{
|
||||
{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]mockControl{
|
||||
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]mockControl{
|
||||
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||
},
|
||||
},
|
||||
} {
|
||||
var w []byte
|
||||
var tailPadLen int
|
||||
mm := socket.NewControlMessage([]int{0})
|
||||
for i, c := range tt.cs {
|
||||
m := socket.NewControlMessage([]int{len(c.Data)})
|
||||
l := len(m) - len(mm)
|
||||
if i == len(tt.cs)-1 && l > len(c.Data) {
|
||||
tailPadLen = l - len(c.Data)
|
||||
}
|
||||
w = append(w, m...)
|
||||
}
|
||||
|
||||
var err error
|
||||
ww := make([]byte, len(w))
|
||||
copy(ww, w)
|
||||
m := socket.ControlMessage(ww)
|
||||
for _, c := range tt.cs {
|
||||
if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
|
||||
t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
|
||||
}
|
||||
copy(m.Data(len(c.Data)), c.Data)
|
||||
m = m.Next(len(c.Data))
|
||||
}
|
||||
m = socket.ControlMessage(w)
|
||||
for _, c := range tt.cs {
|
||||
m, err = m.Marshal(c.Level, c.Type, c.Data)
|
||||
if err != nil {
|
||||
t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(ww, w) {
|
||||
t.Fatalf("got %#v; want %#v", ww, w)
|
||||
}
|
||||
|
||||
ws := [][]byte{w}
|
||||
if tailPadLen > 0 {
|
||||
// Test a message with no tail padding.
|
||||
nopad := w[:len(w)-tailPadLen]
|
||||
ws = append(ws, [][]byte{nopad}...)
|
||||
}
|
||||
for _, w := range ws {
|
||||
ms, err := socket.ControlMessage(w).Parse()
|
||||
if err != nil {
|
||||
t.Fatalf("(%v).Parse() = %v", tt.cs, err)
|
||||
}
|
||||
for i, m := range ms {
|
||||
lvl, typ, dataLen, err := m.ParseHeader()
|
||||
if err != nil {
|
||||
t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
|
||||
}
|
||||
if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
|
||||
t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDP(t *testing.T) {
|
||||
c, err := nettest.NewLocalPacketListener("udp")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
cc, err := socket.NewConn(c.(net.Conn))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Run("Message", func(t *testing.T) {
|
||||
data := []byte("HELLO-R-U-THERE")
|
||||
wm := socket.Message{
|
||||
Buffers: bytes.SplitAfter(data, []byte("-")),
|
||||
Addr: c.LocalAddr(),
|
||||
}
|
||||
if err := cc.SendMsg(&wm, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := make([]byte, 32)
|
||||
rm := socket.Message{
|
||||
Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
|
||||
}
|
||||
if err := cc.RecvMsg(&rm, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(b[:rm.N], data) {
|
||||
t.Fatalf("got %#v; want %#v", b[:rm.N], data)
|
||||
}
|
||||
})
|
||||
switch runtime.GOOS {
|
||||
case "android", "linux":
|
||||
t.Run("Messages", func(t *testing.T) {
|
||||
data := []byte("HELLO-R-U-THERE")
|
||||
wmbs := bytes.SplitAfter(data, []byte("-"))
|
||||
wms := []socket.Message{
|
||||
{Buffers: wmbs[:1], Addr: c.LocalAddr()},
|
||||
{Buffers: wmbs[1:], Addr: c.LocalAddr()},
|
||||
}
|
||||
n, err := cc.SendMsgs(wms, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != len(wms) {
|
||||
t.Fatalf("got %d; want %d", n, len(wms))
|
||||
}
|
||||
b := make([]byte, 32)
|
||||
rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
|
||||
rms := []socket.Message{
|
||||
{Buffers: rmbs[0]},
|
||||
{Buffers: rmbs[1]},
|
||||
}
|
||||
n, err = cc.RecvMsgs(rms, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != len(rms) {
|
||||
t.Fatalf("got %d; want %d", n, len(rms))
|
||||
}
|
||||
nn := 0
|
||||
for i := 0; i < n; i++ {
|
||||
nn += rms[i].N
|
||||
}
|
||||
if !bytes.Equal(b[:nn], data) {
|
||||
t.Fatalf("got %#v; want %#v", b[:nn], data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// The behavior of transmission for zero byte paylaod depends
|
||||
// on each platform implementation. Some may transmit only
|
||||
// protocol header and options, other may transmit nothing.
|
||||
// We test only that SendMsg and SendMsgs will not crash with
|
||||
// empty buffers.
|
||||
wm := socket.Message{
|
||||
Buffers: [][]byte{{}},
|
||||
Addr: c.LocalAddr(),
|
||||
}
|
||||
cc.SendMsg(&wm, 0)
|
||||
wms := []socket.Message{
|
||||
{Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
|
||||
}
|
||||
cc.SendMsgs(wms, 0)
|
||||
}
|
||||
|
||||
func BenchmarkUDP(b *testing.B) {
|
||||
c, err := nettest.NewLocalPacketListener("udp")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
cc, err := socket.NewConn(c.(net.Conn))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
data := []byte("HELLO-R-U-THERE")
|
||||
wm := socket.Message{
|
||||
Buffers: [][]byte{data},
|
||||
Addr: c.LocalAddr(),
|
||||
}
|
||||
rm := socket.Message{
|
||||
Buffers: [][]byte{make([]byte, 128)},
|
||||
OOB: make([]byte, 128),
|
||||
}
|
||||
|
||||
for M := 1; M <= 1<<9; M = M << 1 {
|
||||
b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j := 0; j < M; j++ {
|
||||
if err := cc.SendMsg(&wm, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if err := cc.RecvMsg(&rm, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
switch runtime.GOOS {
|
||||
case "android", "linux":
|
||||
wms := make([]socket.Message, M)
|
||||
for i := range wms {
|
||||
wms[i].Buffers = [][]byte{data}
|
||||
wms[i].Addr = c.LocalAddr()
|
||||
}
|
||||
rms := make([]socket.Message, M)
|
||||
for i := range rms {
|
||||
rms[i].Buffers = [][]byte{make([]byte, 128)}
|
||||
rms[i].OOB = make([]byte, 128)
|
||||
}
|
||||
b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := cc.SendMsgs(wms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, err := cc.RecvMsgs(rms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
46
vendor/golang.org/x/net/internal/socket/socket_test.go
generated
vendored
46
vendor/golang.org/x/net/internal/socket/socket_test.go
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package socket_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/internal/socket"
|
||||
)
|
||||
|
||||
func TestSocket(t *testing.T) {
|
||||
t.Run("Option", func(t *testing.T) {
|
||||
testSocketOption(t, &socket.Option{Level: syscall.SOL_SOCKET, Name: syscall.SO_RCVBUF, Len: 4})
|
||||
})
|
||||
}
|
||||
|
||||
func testSocketOption(t *testing.T, so *socket.Option) {
|
||||
c, err := nettest.NewLocalPacketListener("udp")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
cc, err := socket.NewConn(c.(net.Conn))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
const N = 2048
|
||||
if err := so.SetInt(cc, N); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, err := so.GetInt(cc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n < N {
|
||||
t.Fatalf("got %d; want greater than or equal to %d", n, N)
|
||||
}
|
||||
}
|
170
vendor/golang.org/x/net/internal/socks/dial_test.go
generated
vendored
170
vendor/golang.org/x/net/internal/socks/dial_test.go
generated
vendored
|
@ -1,170 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package socks_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/internal/socks"
|
||||
"golang.org/x/net/internal/sockstest"
|
||||
)
|
||||
|
||||
func TestDial(t *testing.T) {
|
||||
t.Run("Connect", func(t *testing.T) {
|
||||
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close()
|
||||
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||
d.AuthMethods = []socks.AuthMethod{
|
||||
socks.AuthMethodNotRequired,
|
||||
socks.AuthMethodUsernamePassword,
|
||||
}
|
||||
d.Authenticate = (&socks.UsernamePassword{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
}).Authenticate
|
||||
c, err := d.DialContext(context.Background(), ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.(*socks.Conn).BoundAddr()
|
||||
c.Close()
|
||||
})
|
||||
t.Run("ConnectWithConn", func(t *testing.T) {
|
||||
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close()
|
||||
c, err := net.Dial(ss.Addr().Network(), ss.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||
d.AuthMethods = []socks.AuthMethod{
|
||||
socks.AuthMethodNotRequired,
|
||||
socks.AuthMethodUsernamePassword,
|
||||
}
|
||||
d.Authenticate = (&socks.UsernamePassword{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
}).Authenticate
|
||||
a, err := d.DialWithConn(context.Background(), c, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := a.(*socks.Addr); !ok {
|
||||
t.Fatalf("got %+v; want socks.Addr", a)
|
||||
}
|
||||
})
|
||||
t.Run("Cancel", func(t *testing.T) {
|
||||
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close()
|
||||
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
dialErr := make(chan error)
|
||||
go func() {
|
||||
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||
if err == nil {
|
||||
c.Close()
|
||||
}
|
||||
dialErr <- err
|
||||
}()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
cancel()
|
||||
err = <-dialErr
|
||||
if perr, nerr := parseDialError(err); perr != context.Canceled && nerr == nil {
|
||||
t.Fatalf("got %v; want context.Canceled or equivalent", err)
|
||||
}
|
||||
})
|
||||
t.Run("Deadline", func(t *testing.T) {
|
||||
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close()
|
||||
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
|
||||
defer cancel()
|
||||
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||
if err == nil {
|
||||
c.Close()
|
||||
}
|
||||
if perr, nerr := parseDialError(err); perr != context.DeadlineExceeded && nerr == nil {
|
||||
t.Fatalf("got %v; want context.DeadlineExceeded or equivalent", err)
|
||||
}
|
||||
})
|
||||
t.Run("WithRogueServer", func(t *testing.T) {
|
||||
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, rogueCmdFunc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close()
|
||||
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||
for i := 0; i < 2*len(rogueCmdList); i++ {
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
|
||||
defer cancel()
|
||||
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||
if err == nil {
|
||||
t.Log(c.(*socks.Conn).BoundAddr())
|
||||
c.Close()
|
||||
t.Error("should fail")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func blackholeCmdFunc(rw io.ReadWriter, b []byte) error {
|
||||
if _, err := sockstest.ParseCmdRequest(b); err != nil {
|
||||
return err
|
||||
}
|
||||
var bb [1]byte
|
||||
for {
|
||||
if _, err := rw.Read(bb[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rogueCmdFunc(rw io.ReadWriter, b []byte) error {
|
||||
if _, err := sockstest.ParseCmdRequest(b); err != nil {
|
||||
return err
|
||||
}
|
||||
rw.Write(rogueCmdList[rand.Intn(len(rogueCmdList))])
|
||||
return nil
|
||||
}
|
||||
|
||||
var rogueCmdList = [][]byte{
|
||||
{0x05},
|
||||
{0x06, 0x00, 0x00, 0x01, 192, 0, 2, 1, 0x17, 0x4b},
|
||||
{0x05, 0x00, 0xff, 0x01, 192, 0, 2, 2, 0x17, 0x4b},
|
||||
{0x05, 0x00, 0x00, 0x01, 192, 0, 2, 3},
|
||||
{0x05, 0x00, 0x00, 0x03, 0x04, 'F', 'Q', 'D', 'N'},
|
||||
}
|
||||
|
||||
func parseDialError(err error) (perr, nerr error) {
|
||||
if e, ok := err.(*net.OpError); ok {
|
||||
err = e.Err
|
||||
nerr = e
|
||||
}
|
||||
if e, ok := err.(*os.SyscallError); ok {
|
||||
err = e.Err
|
||||
}
|
||||
perr = err
|
||||
return
|
||||
}
|
93
vendor/golang.org/x/net/ipv4/bpf_test.go
generated
vendored
93
vendor/golang.org/x/net/ipv4/bpf_test.go
generated
vendored
|
@ -1,93 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestBPF(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
l, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
p := ipv4.NewPacketConn(l)
|
||||
|
||||
// This filter accepts UDP packets whose first payload byte is
|
||||
// even.
|
||||
prog, err := bpf.Assemble([]bpf.Instruction{
|
||||
// Load the first byte of the payload (skipping UDP header).
|
||||
bpf.LoadAbsolute{Off: 8, Size: 1},
|
||||
// Select LSB of the byte.
|
||||
bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
|
||||
// Byte is even?
|
||||
bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
|
||||
// Accept.
|
||||
bpf.RetConstant{Val: 4096},
|
||||
// Ignore.
|
||||
bpf.RetConstant{Val: 0},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("compiling BPF: %s", err)
|
||||
}
|
||||
|
||||
if err = p.SetBPF(prog); err != nil {
|
||||
t.Fatalf("attaching filter to Conn: %s", err)
|
||||
}
|
||||
|
||||
s, err := net.Dial("udp4", l.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
go func() {
|
||||
for i := byte(0); i < 10; i++ {
|
||||
s.Write([]byte{i})
|
||||
}
|
||||
}()
|
||||
|
||||
l.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
seen := make([]bool, 5)
|
||||
for {
|
||||
var b [512]byte
|
||||
n, _, err := l.ReadFrom(b[:])
|
||||
if err != nil {
|
||||
t.Fatalf("reading from listener: %s", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Fatalf("unexpected packet length, want 1, got %d", n)
|
||||
}
|
||||
if b[0] >= 10 {
|
||||
t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
|
||||
}
|
||||
if b[0]%2 != 0 {
|
||||
t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
|
||||
}
|
||||
seen[b[0]/2] = true
|
||||
|
||||
seenAll := true
|
||||
for _, v := range seen {
|
||||
if !v {
|
||||
seenAll = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if seenAll {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
21
vendor/golang.org/x/net/ipv4/control_test.go
generated
vendored
21
vendor/golang.org/x/net/ipv4/control_test.go
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestControlMessageParseWithFuzz(t *testing.T) {
|
||||
var cm ipv4.ControlMessage
|
||||
for _, fuzz := range []string{
|
||||
"\f\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00",
|
||||
"\f\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00",
|
||||
} {
|
||||
cm.Parse([]byte(fuzz))
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/net/ipv4/doc.go
generated
vendored
2
vendor/golang.org/x/net/ipv4/doc.go
generated
vendored
|
@ -55,7 +55,7 @@
|
|||
// Multicasting
|
||||
//
|
||||
// The options for multicasting are available for net.UDPConn and
|
||||
// net.IPconn which are created as network connections that use the
|
||||
// net.IPConn which are created as network connections that use the
|
||||
// IPv4 transport. A few network facilities must be prepared before
|
||||
// you begin multicasting, at a minimum joining network interfaces and
|
||||
// multicast groups.
|
||||
|
|
224
vendor/golang.org/x/net/ipv4/example_test.go
generated
vendored
224
vendor/golang.org/x/net/ipv4/example_test.go
generated
vendored
|
@ -1,224 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func ExampleConn_markingTCP() {
|
||||
ln, err := net.Listen("tcp", "0.0.0.0:1024")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
for {
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
defer c.Close()
|
||||
if c.RemoteAddr().(*net.TCPAddr).IP.To4() != nil {
|
||||
p := ipv4.NewConn(c)
|
||||
if err := p.SetTOS(0x28); err != nil { // DSCP AF11
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := p.SetTTL(128); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(c)
|
||||
}
|
||||
}
|
||||
|
||||
func ExamplePacketConn_servingOneShotMulticastDNS() {
|
||||
c, err := net.ListenPacket("udp4", "0.0.0.0:5353") // mDNS over UDP
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
|
||||
en0, err := net.InterfaceByName("en0")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mDNSLinkLocal := net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}
|
||||
if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(en0, &mDNSLinkLocal)
|
||||
if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
b := make([]byte, 1500)
|
||||
for {
|
||||
_, cm, peer, err := p.ReadFrom(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if !cm.Dst.IsMulticast() || !cm.Dst.Equal(mDNSLinkLocal.IP) {
|
||||
continue
|
||||
}
|
||||
answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
|
||||
if _, err := p.WriteTo(answers, nil, peer); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExamplePacketConn_tracingIPPacketRoute() {
|
||||
// Tracing an IP packet route to www.google.com.
|
||||
|
||||
const host = "www.google.com"
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var dst net.IPAddr
|
||||
for _, ip := range ips {
|
||||
if ip.To4() != nil {
|
||||
dst.IP = ip
|
||||
fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
|
||||
break
|
||||
}
|
||||
}
|
||||
if dst.IP == nil {
|
||||
log.Fatal("no A record found")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
|
||||
if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
wm := icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}
|
||||
|
||||
rb := make([]byte, 1500)
|
||||
for i := 1; i <= 64; i++ { // up to 64 hops
|
||||
wm.Body.(*icmp.Echo).Seq = i
|
||||
wb, err := wm.Marshal(nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := p.SetTTL(i); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// In the real world usually there are several
|
||||
// multiple traffic-engineered paths for each hop.
|
||||
// You may need to probe a few times to each hop.
|
||||
begin := time.Now()
|
||||
if _, err := p.WriteTo(wb, nil, &dst); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
n, cm, peer, err := p.ReadFrom(rb)
|
||||
if err != nil {
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
fmt.Printf("%v\t*\n", i)
|
||||
continue
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
rm, err := icmp.ParseMessage(1, rb[:n])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
rtt := time.Since(begin)
|
||||
|
||||
// In the real world you need to determine whether the
|
||||
// received message is yours using ControlMessage.Src,
|
||||
// ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
|
||||
switch rm.Type {
|
||||
case ipv4.ICMPTypeTimeExceeded:
|
||||
names, _ := net.LookupAddr(peer.String())
|
||||
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
|
||||
case ipv4.ICMPTypeEchoReply:
|
||||
names, _ := net.LookupAddr(peer.String())
|
||||
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
|
||||
return
|
||||
default:
|
||||
log.Printf("unknown ICMP message: %+v\n", rm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleRawConn_advertisingOSPFHello() {
|
||||
c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
en0, err := net.InterfaceByName("en0")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)}
|
||||
if err := r.JoinGroup(en0, &allSPFRouters); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer r.LeaveGroup(en0, &allSPFRouters)
|
||||
|
||||
hello := make([]byte, 24) // fake hello data, you need to implement this
|
||||
ospf := make([]byte, 24) // fake ospf header, you need to implement this
|
||||
ospf[0] = 2 // version 2
|
||||
ospf[1] = 1 // hello packet
|
||||
ospf = append(ospf, hello...)
|
||||
iph := &ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TOS: 0xc0, // DSCP CS6
|
||||
TotalLen: ipv4.HeaderLen + len(ospf),
|
||||
TTL: 1,
|
||||
Protocol: 89,
|
||||
Dst: allSPFRouters.IP.To4(),
|
||||
}
|
||||
|
||||
var cm *ipv4.ControlMessage
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "linux":
|
||||
cm = &ipv4.ControlMessage{IfIndex: en0.Index}
|
||||
default:
|
||||
if err := r.SetMulticastInterface(en0); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := r.WriteTo(iph, ospf, cm); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
12
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
12
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
|
@ -51,6 +51,10 @@ func (h *Header) String() string {
|
|||
}
|
||||
|
||||
// Marshal returns the binary encoding of h.
|
||||
//
|
||||
// The returned slice is in the format used by a raw IP socket on the
|
||||
// local system.
|
||||
// This may differ from the wire format, depending on the system.
|
||||
func (h *Header) Marshal() ([]byte, error) {
|
||||
if h == nil {
|
||||
return nil, errInvalidConn
|
||||
|
@ -98,6 +102,10 @@ func (h *Header) Marshal() ([]byte, error) {
|
|||
}
|
||||
|
||||
// Parse parses b as an IPv4 header and stores the result in h.
|
||||
//
|
||||
// The provided b must be in the format used by a raw IP socket on the
|
||||
// local system.
|
||||
// This may differ from the wire format, depending on the system.
|
||||
func (h *Header) Parse(b []byte) error {
|
||||
if h == nil || len(b) < HeaderLen {
|
||||
return errHeaderTooShort
|
||||
|
@ -149,6 +157,10 @@ func (h *Header) Parse(b []byte) error {
|
|||
}
|
||||
|
||||
// ParseHeader parses b as an IPv4 header.
|
||||
//
|
||||
// The provided b must be in the format used by a raw IP socket on the
|
||||
// local system.
|
||||
// This may differ from the wire format, depending on the system.
|
||||
func ParseHeader(b []byte) (*Header, error) {
|
||||
h := new(Header)
|
||||
if err := h.Parse(b); err != nil {
|
||||
|
|
228
vendor/golang.org/x/net/ipv4/header_test.go
generated
vendored
228
vendor/golang.org/x/net/ipv4/header_test.go
generated
vendored
|
@ -1,228 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
)
|
||||
|
||||
type headerTest struct {
|
||||
wireHeaderFromKernel []byte
|
||||
wireHeaderToKernel []byte
|
||||
wireHeaderFromTradBSDKernel []byte
|
||||
wireHeaderToTradBSDKernel []byte
|
||||
wireHeaderFromFreeBSD10Kernel []byte
|
||||
wireHeaderToFreeBSD10Kernel []byte
|
||||
*Header
|
||||
}
|
||||
|
||||
var headerLittleEndianTests = []headerTest{
|
||||
// TODO(mikio): Add platform dependent wire header formats when
|
||||
// we support new platforms.
|
||||
{
|
||||
wireHeaderFromKernel: []byte{
|
||||
0x45, 0x01, 0xbe, 0xef,
|
||||
0xca, 0xfe, 0x45, 0xdc,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
wireHeaderToKernel: []byte{
|
||||
0x45, 0x01, 0xbe, 0xef,
|
||||
0xca, 0xfe, 0x45, 0xdc,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
wireHeaderFromTradBSDKernel: []byte{
|
||||
0x45, 0x01, 0xdb, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
wireHeaderToTradBSDKernel: []byte{
|
||||
0x45, 0x01, 0xef, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
wireHeaderFromFreeBSD10Kernel: []byte{
|
||||
0x45, 0x01, 0xef, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
wireHeaderToFreeBSD10Kernel: []byte{
|
||||
0x45, 0x01, 0xef, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
},
|
||||
Header: &Header{
|
||||
Version: Version,
|
||||
Len: HeaderLen,
|
||||
TOS: 1,
|
||||
TotalLen: 0xbeef,
|
||||
ID: 0xcafe,
|
||||
Flags: DontFragment,
|
||||
FragOff: 1500,
|
||||
TTL: 255,
|
||||
Protocol: 1,
|
||||
Checksum: 0xdead,
|
||||
Src: net.IPv4(172, 16, 254, 254),
|
||||
Dst: net.IPv4(192, 168, 0, 1),
|
||||
},
|
||||
},
|
||||
|
||||
// with option headers
|
||||
{
|
||||
wireHeaderFromKernel: []byte{
|
||||
0x46, 0x01, 0xbe, 0xf3,
|
||||
0xca, 0xfe, 0x45, 0xdc,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
wireHeaderToKernel: []byte{
|
||||
0x46, 0x01, 0xbe, 0xf3,
|
||||
0xca, 0xfe, 0x45, 0xdc,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
wireHeaderFromTradBSDKernel: []byte{
|
||||
0x46, 0x01, 0xdb, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
wireHeaderToTradBSDKernel: []byte{
|
||||
0x46, 0x01, 0xf3, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
wireHeaderFromFreeBSD10Kernel: []byte{
|
||||
0x46, 0x01, 0xf3, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
wireHeaderToFreeBSD10Kernel: []byte{
|
||||
0x46, 0x01, 0xf3, 0xbe,
|
||||
0xca, 0xfe, 0xdc, 0x45,
|
||||
0xff, 0x01, 0xde, 0xad,
|
||||
172, 16, 254, 254,
|
||||
192, 168, 0, 1,
|
||||
0xff, 0xfe, 0xfe, 0xff,
|
||||
},
|
||||
Header: &Header{
|
||||
Version: Version,
|
||||
Len: HeaderLen + 4,
|
||||
TOS: 1,
|
||||
TotalLen: 0xbef3,
|
||||
ID: 0xcafe,
|
||||
Flags: DontFragment,
|
||||
FragOff: 1500,
|
||||
TTL: 255,
|
||||
Protocol: 1,
|
||||
Checksum: 0xdead,
|
||||
Src: net.IPv4(172, 16, 254, 254),
|
||||
Dst: net.IPv4(192, 168, 0, 1),
|
||||
Options: []byte{0xff, 0xfe, 0xfe, 0xff},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMarshalHeader(t *testing.T) {
|
||||
if socket.NativeEndian != binary.LittleEndian {
|
||||
t.Skip("no test for non-little endian machine yet")
|
||||
}
|
||||
|
||||
for _, tt := range headerLittleEndianTests {
|
||||
b, err := tt.Header.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var wh []byte
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "dragonfly", "netbsd":
|
||||
wh = tt.wireHeaderToTradBSDKernel
|
||||
case "freebsd":
|
||||
switch {
|
||||
case freebsdVersion < 1000000:
|
||||
wh = tt.wireHeaderToTradBSDKernel
|
||||
case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
|
||||
wh = tt.wireHeaderToFreeBSD10Kernel
|
||||
default:
|
||||
wh = tt.wireHeaderToKernel
|
||||
}
|
||||
default:
|
||||
wh = tt.wireHeaderToKernel
|
||||
}
|
||||
if !bytes.Equal(b, wh) {
|
||||
t.Fatalf("got %#v; want %#v", b, wh)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseHeader(t *testing.T) {
|
||||
if socket.NativeEndian != binary.LittleEndian {
|
||||
t.Skip("no test for big endian machine yet")
|
||||
}
|
||||
|
||||
for _, tt := range headerLittleEndianTests {
|
||||
var wh []byte
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "dragonfly", "netbsd":
|
||||
wh = tt.wireHeaderFromTradBSDKernel
|
||||
case "freebsd":
|
||||
switch {
|
||||
case freebsdVersion < 1000000:
|
||||
wh = tt.wireHeaderFromTradBSDKernel
|
||||
case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
|
||||
wh = tt.wireHeaderFromFreeBSD10Kernel
|
||||
default:
|
||||
wh = tt.wireHeaderFromKernel
|
||||
}
|
||||
default:
|
||||
wh = tt.wireHeaderFromKernel
|
||||
}
|
||||
h, err := ParseHeader(wh)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := h.Parse(wh); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(h, tt.Header) {
|
||||
t.Fatalf("got %#v; want %#v", h, tt.Header)
|
||||
}
|
||||
s := h.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Fatalf("should be space-separated values: %s", s)
|
||||
}
|
||||
}
|
||||
}
|
95
vendor/golang.org/x/net/ipv4/icmp_test.go
generated
vendored
95
vendor/golang.org/x/net/ipv4/icmp_test.go
generated
vendored
|
@ -1,95 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
var icmpStringTests = []struct {
|
||||
in ipv4.ICMPType
|
||||
out string
|
||||
}{
|
||||
{ipv4.ICMPTypeDestinationUnreachable, "destination unreachable"},
|
||||
|
||||
{256, "<nil>"},
|
||||
}
|
||||
|
||||
func TestICMPString(t *testing.T) {
|
||||
for _, tt := range icmpStringTests {
|
||||
s := tt.in.String()
|
||||
if s != tt.out {
|
||||
t.Errorf("got %s; want %s", s, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
default:
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
var f ipv4.ICMPFilter
|
||||
for _, toggle := range []bool{false, true} {
|
||||
f.SetAll(toggle)
|
||||
for _, typ := range []ipv4.ICMPType{
|
||||
ipv4.ICMPTypeDestinationUnreachable,
|
||||
ipv4.ICMPTypeEchoReply,
|
||||
ipv4.ICMPTypeTimeExceeded,
|
||||
ipv4.ICMPTypeParameterProblem,
|
||||
} {
|
||||
f.Accept(typ)
|
||||
if f.WillBlock(typ) {
|
||||
t.Errorf("ipv4.ICMPFilter.Set(%v, false) failed", typ)
|
||||
}
|
||||
f.Block(typ)
|
||||
if !f.WillBlock(typ) {
|
||||
t.Errorf("ipv4.ICMPFilter.Set(%v, true) failed", typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
default:
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv4.NewPacketConn(c)
|
||||
|
||||
var f ipv4.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Accept(ipv4.ICMPTypeEcho)
|
||||
f.Accept(ipv4.ICMPTypeEchoReply)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kf, err := p.ICMPFilter()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(kf, &f) {
|
||||
t.Fatalf("got %#v; want %#v", kf, f)
|
||||
}
|
||||
}
|
334
vendor/golang.org/x/net/ipv4/multicast_test.go
generated
vendored
334
vendor/golang.org/x/net/ipv4/multicast_test.go
generated
vendored
|
@ -1,334 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
var packetConnReadWriteMulticastUDPTests = []struct {
|
||||
addr string
|
||||
grp, src *net.UDPAddr
|
||||
}{
|
||||
{"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||
|
||||
{"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range packetConnReadWriteMulticastUDPTests {
|
||||
c, err := net.ListenPacket("udp4", tt.addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
grp := *tt.grp
|
||||
grp.Port = c.LocalAddr().(*net.UDPAddr).Port
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if tt.src == nil {
|
||||
if err := p.JoinGroup(ifi, &grp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(ifi, &grp)
|
||||
} else {
|
||||
if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support IGMPv2/3 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.SetMulticastTTL(i + 1)
|
||||
if n, err := p.WriteTo(wb, nil, &grp); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Fatalf("got %v; want %v", rb[:n], wb)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var packetConnReadWriteMulticastICMPTests = []struct {
|
||||
grp, src *net.IPAddr
|
||||
}{
|
||||
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||
|
||||
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range packetConnReadWriteMulticastICMPTests {
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if tt.src == nil {
|
||||
if err := p.JoinGroup(ifi, tt.grp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(ifi, tt.grp)
|
||||
} else {
|
||||
if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support IGMPv2/3 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cf := ipv4.FlagDst | ipv4.FlagInterface
|
||||
if runtime.GOOS != "solaris" {
|
||||
// Solaris never allows to modify ICMP properties.
|
||||
cf |= ipv4.FlagTTL
|
||||
}
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
wb, err := (&icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.SetMulticastTTL(i + 1)
|
||||
if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
switch {
|
||||
case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
|
||||
case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
|
||||
default:
|
||||
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rawConnReadWriteMulticastICMPTests = []struct {
|
||||
grp, src *net.IPAddr
|
||||
}{
|
||||
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||
|
||||
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestRawConnReadWriteMulticastICMP(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range rawConnReadWriteMulticastICMPTests {
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Close()
|
||||
if tt.src == nil {
|
||||
if err := r.JoinGroup(ifi, tt.grp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.LeaveGroup(ifi, tt.grp)
|
||||
} else {
|
||||
if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support IGMPv2/3 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
|
||||
}
|
||||
if err := r.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := r.MulticastInterface(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := r.MulticastLoopback(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
wb, err := (&icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wh := &ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TOS: i + 1,
|
||||
TotalLen: ipv4.HeaderLen + len(wb),
|
||||
Protocol: 1,
|
||||
Dst: tt.grp.IP,
|
||||
}
|
||||
if err := r.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r.SetMulticastTTL(i + 1)
|
||||
if err := r.WriteTo(wh, wb, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rb := make([]byte, ipv4.HeaderLen+128)
|
||||
if rh, b, _, err := r.ReadFrom(rb); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
switch {
|
||||
case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
|
||||
case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
|
||||
default:
|
||||
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
265
vendor/golang.org/x/net/ipv4/multicastlistener_test.go
generated
vendored
265
vendor/golang.org/x/net/ipv4/multicastlistener_test.go
generated
vendored
|
@ -1,265 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
var udpMultipleGroupListenerTests = []net.Addr{
|
||||
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, // see RFC 4727
|
||||
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)},
|
||||
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)},
|
||||
}
|
||||
|
||||
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c, err := net.ListenPacket("udp4", "0.0.0.0:0") // wildcard address with no reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv4.NewPacketConn(c)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c1, err := net.ListenPacket("udp4", "224.0.0.0:0") // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c1.Close()
|
||||
_, port, err := net.SplitHostPort(c1.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c2, err := net.ListenPacket("udp4", net.JoinHostPort("224.0.0.0", port)) // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c2.Close()
|
||||
|
||||
var ps [2]*ipv4.PacketConn
|
||||
ps[0] = ipv4.NewPacketConn(c1)
|
||||
ps[1] = ipv4.NewPacketConn(c2)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
for _, p := range ps {
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
for _, p := range ps {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv4.PacketConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port := "0"
|
||||
for i, ifi := range ift {
|
||||
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("udp4", net.JoinHostPort(ip.String(), port)) // unicast address with non-reusable port
|
||||
if err != nil {
|
||||
// The listen may fail when the serivce is
|
||||
// already in use, but it's fine because the
|
||||
// purpose of this is not to test the
|
||||
// bookkeeping of IP control block inside the
|
||||
// kernel.
|
||||
t.Log(err)
|
||||
continue
|
||||
}
|
||||
defer c.Close()
|
||||
if port == "0" {
|
||||
_, port, err = net.SplitHostPort(c.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
p := ipv4.NewPacketConn(c)
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mlt = append(mlt, &ml{p, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := r.LeaveGroup(ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if testing.Short() {
|
||||
t.Skip("to avoid external network")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv4.RawConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mlt = append(mlt, &ml{r, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
195
vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
generated
vendored
195
vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
generated
vendored
|
@ -1,195 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
var packetConnMulticastSocketOptionTests = []struct {
|
||||
net, proto, addr string
|
||||
grp, src net.Addr
|
||||
}{
|
||||
{"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
|
||||
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
|
||||
|
||||
{"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnMulticastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
m, ok := nettest.SupportsRawIPSocket()
|
||||
for _, tt := range packetConnMulticastSocketOptionTests {
|
||||
if tt.net == "ip4" && !ok {
|
||||
t.Log(m)
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
if tt.src == nil {
|
||||
testMulticastSocketOptions(t, p, ifi, tt.grp)
|
||||
} else {
|
||||
testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rawConnMulticastSocketOptionTests = []struct {
|
||||
grp, src net.Addr
|
||||
}{
|
||||
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
|
||||
|
||||
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestRawConnMulticastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range rawConnMulticastSocketOptionTests {
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
if tt.src == nil {
|
||||
testMulticastSocketOptions(t, r, ifi, tt.grp)
|
||||
} else {
|
||||
testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testIPv4MulticastConn interface {
|
||||
MulticastTTL() (int, error)
|
||||
SetMulticastTTL(ttl int) error
|
||||
MulticastLoopback() (bool, error)
|
||||
SetMulticastLoopback(bool) error
|
||||
JoinGroup(*net.Interface, net.Addr) error
|
||||
LeaveGroup(*net.Interface, net.Addr) error
|
||||
JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
}
|
||||
|
||||
func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
|
||||
const ttl = 255
|
||||
if err := c.SetMulticastTTL(ttl); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if v, err := c.MulticastTTL(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if v != ttl {
|
||||
t.Errorf("got %v; want %v", v, ttl)
|
||||
return
|
||||
}
|
||||
|
||||
for _, toggle := range []bool{true, false} {
|
||||
if err := c.SetMulticastLoopback(toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if v, err := c.MulticastLoopback(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if v != toggle {
|
||||
t.Errorf("got %v; want %v", v, toggle)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
|
||||
// MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
|
||||
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support IGMPv2/3 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
|
||||
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
|
||||
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/net/ipv4/payload_cmsg.go
generated
vendored
2
vendor/golang.org/x/net/ipv4/payload_cmsg.go
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
|
2
vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go
generated
vendored
2
vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.9
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
|
2
vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go
generated
vendored
2
vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
|
2
vendor/golang.org/x/net/ipv4/payload_nocmsg.go
generated
vendored
2
vendor/golang.org/x/net/ipv4/payload_nocmsg.go
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build nacl plan9 windows
|
||||
// +build js nacl plan9 windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
|
248
vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go
generated
vendored
248
vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go
generated
vendored
|
@ -1,248 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.9
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
b.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
payload := []byte("HELLO-R-U-THERE")
|
||||
iph, err := (&ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TotalLen: ipv4.HeaderLen + len(payload),
|
||||
TTL: 1,
|
||||
Protocol: iana.ProtocolReserved,
|
||||
Src: net.IPv4(192, 0, 2, 1),
|
||||
Dst: net.IPv4(192, 0, 2, 254),
|
||||
}).Marshal()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
datagram := append(greh, append(iph, payload...)...)
|
||||
bb := make([]byte, 128)
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
|
||||
b.Run("UDP", func(b *testing.B) {
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
dst := c.LocalAddr()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.Run("Net", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := c.WriteTo(payload, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("ToFrom", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteTo(payload, &cm, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
b.Run("IP", func(b *testing.B) {
|
||||
switch runtime.GOOS {
|
||||
case "netbsd":
|
||||
b.Skip("need to configure gre on netbsd")
|
||||
case "openbsd":
|
||||
b.Skip("net.inet.gre.allow=0 by default on openbsd")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
dst := c.LocalAddr()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.Run("Net", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := c.WriteTo(datagram, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("ToFrom", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
payload := []byte("HELLO-R-U-THERE")
|
||||
iph, err := (&ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TotalLen: ipv4.HeaderLen + len(payload),
|
||||
TTL: 1,
|
||||
Protocol: iana.ProtocolReserved,
|
||||
Src: net.IPv4(192, 0, 2, 1),
|
||||
Dst: net.IPv4(192, 0, 2, 254),
|
||||
}).Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
datagram := append(greh, append(iph, payload...)...)
|
||||
|
||||
t.Run("UDP", func(t *testing.T) {
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
t.Run("ToFrom", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
|
||||
})
|
||||
})
|
||||
t.Run("IP", func(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "netbsd":
|
||||
t.Skip("need to configure gre on netbsd")
|
||||
case "openbsd":
|
||||
t.Skip("net.inet.gre.allow=0 by default on openbsd")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
t.Run("ToFrom", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr) {
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
|
||||
|
||||
if err := p.SetControlMessage(cf, true); err != nil { // probe before test
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
reader := func() {
|
||||
defer wg.Done()
|
||||
b := make([]byte, 128)
|
||||
n, cm, _, err := p.ReadFrom(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(b[:n], data) {
|
||||
t.Errorf("got %#v; want %#v", b[:n], data)
|
||||
return
|
||||
}
|
||||
s := cm.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Errorf("should be space-separated values: %s", s)
|
||||
return
|
||||
}
|
||||
}
|
||||
writer := func(toggle bool) {
|
||||
defer wg.Done()
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
n, err := p.WriteTo(data, &cm, dst)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if n != len(data) {
|
||||
t.Errorf("got %d; want %d", n, len(data))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const N = 10
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Add(2 * N)
|
||||
for i := 0; i < 2*N; i++ {
|
||||
go writer(i%2 != 0)
|
||||
|
||||
}
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
388
vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go
generated
vendored
388
vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go
generated
vendored
|
@ -1,388 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
b.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
payload := []byte("HELLO-R-U-THERE")
|
||||
iph, err := (&ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TotalLen: ipv4.HeaderLen + len(payload),
|
||||
TTL: 1,
|
||||
Protocol: iana.ProtocolReserved,
|
||||
Src: net.IPv4(192, 0, 2, 1),
|
||||
Dst: net.IPv4(192, 0, 2, 254),
|
||||
}).Marshal()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
datagram := append(greh, append(iph, payload...)...)
|
||||
bb := make([]byte, 128)
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
|
||||
b.Run("UDP", func(b *testing.B) {
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
dst := c.LocalAddr()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
wms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{payload},
|
||||
Addr: dst,
|
||||
OOB: cm.Marshal(),
|
||||
},
|
||||
}
|
||||
rms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{bb},
|
||||
OOB: ipv4.NewControlMessage(cf),
|
||||
},
|
||||
}
|
||||
b.Run("Net", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := c.WriteTo(payload, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("ToFrom", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteTo(payload, &cm, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("Batch", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteBatch(wms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, err := p.ReadBatch(rms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
b.Run("IP", func(b *testing.B) {
|
||||
switch runtime.GOOS {
|
||||
case "netbsd":
|
||||
b.Skip("need to configure gre on netbsd")
|
||||
case "openbsd":
|
||||
b.Skip("net.inet.gre.allow=0 by default on openbsd")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
dst := c.LocalAddr()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
wms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{datagram},
|
||||
Addr: dst,
|
||||
OOB: cm.Marshal(),
|
||||
},
|
||||
}
|
||||
rms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{bb},
|
||||
OOB: ipv4.NewControlMessage(cf),
|
||||
},
|
||||
}
|
||||
b.Run("Net", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := c.WriteTo(datagram, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("ToFrom", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(bb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("Batch", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteBatch(wms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, err := p.ReadBatch(rms, 0); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
payload := []byte("HELLO-R-U-THERE")
|
||||
iph, err := (&ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TotalLen: ipv4.HeaderLen + len(payload),
|
||||
TTL: 1,
|
||||
Protocol: iana.ProtocolReserved,
|
||||
Src: net.IPv4(192, 0, 2, 1),
|
||||
Dst: net.IPv4(192, 0, 2, 254),
|
||||
}).Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
datagram := append(greh, append(iph, payload...)...)
|
||||
|
||||
t.Run("UDP", func(t *testing.T) {
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
t.Run("ToFrom", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
|
||||
})
|
||||
t.Run("Batch", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
|
||||
})
|
||||
})
|
||||
t.Run("IP", func(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "netbsd":
|
||||
t.Skip("need to configure gre on netbsd")
|
||||
case "openbsd":
|
||||
t.Skip("net.inet.gre.allow=0 by default on openbsd")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
t.Run("ToFrom", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
|
||||
})
|
||||
t.Run("Batch", func(t *testing.T) {
|
||||
testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr, batch bool) {
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
|
||||
|
||||
if err := p.SetControlMessage(cf, true); err != nil { // probe before test
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
reader := func() {
|
||||
defer wg.Done()
|
||||
b := make([]byte, 128)
|
||||
n, cm, _, err := p.ReadFrom(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(b[:n], data) {
|
||||
t.Errorf("got %#v; want %#v", b[:n], data)
|
||||
return
|
||||
}
|
||||
s := cm.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Errorf("should be space-separated values: %s", s)
|
||||
return
|
||||
}
|
||||
}
|
||||
batchReader := func() {
|
||||
defer wg.Done()
|
||||
ms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{make([]byte, 128)},
|
||||
OOB: ipv4.NewControlMessage(cf),
|
||||
},
|
||||
}
|
||||
n, err := p.ReadBatch(ms, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if n != len(ms) {
|
||||
t.Errorf("got %d; want %d", n, len(ms))
|
||||
return
|
||||
}
|
||||
var cm ipv4.ControlMessage
|
||||
if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
var b []byte
|
||||
if _, ok := dst.(*net.IPAddr); ok {
|
||||
var h ipv4.Header
|
||||
if err := h.Parse(ms[0].Buffers[0][:ms[0].N]); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
b = ms[0].Buffers[0][h.Len:ms[0].N]
|
||||
} else {
|
||||
b = ms[0].Buffers[0][:ms[0].N]
|
||||
}
|
||||
if !bytes.Equal(b, data) {
|
||||
t.Errorf("got %#v; want %#v", b, data)
|
||||
return
|
||||
}
|
||||
s := cm.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Errorf("should be space-separated values: %s", s)
|
||||
return
|
||||
}
|
||||
}
|
||||
writer := func(toggle bool) {
|
||||
defer wg.Done()
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
n, err := p.WriteTo(data, &cm, dst)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if n != len(data) {
|
||||
t.Errorf("got %d; want %d", n, len(data))
|
||||
return
|
||||
}
|
||||
}
|
||||
batchWriter := func(toggle bool) {
|
||||
defer wg.Done()
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
ms := []ipv4.Message{
|
||||
{
|
||||
Buffers: [][]byte{data},
|
||||
OOB: cm.Marshal(),
|
||||
Addr: dst,
|
||||
},
|
||||
}
|
||||
n, err := p.WriteBatch(ms, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if n != len(ms) {
|
||||
t.Errorf("got %d; want %d", n, len(ms))
|
||||
return
|
||||
}
|
||||
if ms[0].N != len(data) {
|
||||
t.Errorf("got %d; want %d", ms[0].N, len(data))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const N = 10
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
if batch {
|
||||
go batchReader()
|
||||
} else {
|
||||
go reader()
|
||||
}
|
||||
}
|
||||
wg.Add(2 * N)
|
||||
for i := 0; i < 2*N; i++ {
|
||||
if batch {
|
||||
go batchWriter(i%2 != 0)
|
||||
} else {
|
||||
go writer(i%2 != 0)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
if batch {
|
||||
go batchReader()
|
||||
} else {
|
||||
go reader()
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
140
vendor/golang.org/x/net/ipv4/readwrite_test.go
generated
vendored
140
vendor/golang.org/x/net/ipv4/readwrite_test.go
generated
vendored
|
@ -1,140 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func BenchmarkReadWriteUnicast(b *testing.B) {
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst := c.LocalAddr()
|
||||
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||
|
||||
b.Run("NetUDP", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := c.WriteTo(wb, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(rb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("IPv4UDP", func(b *testing.B) {
|
||||
p := ipv4.NewPacketConn(c)
|
||||
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
cm := ipv4.ControlMessage{TTL: 1}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
dst := c.LocalAddr()
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
if err := p.SetControlMessage(cf, true); err != nil { // probe before test
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
reader := func() {
|
||||
defer wg.Done()
|
||||
rb := make([]byte, 128)
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Errorf("got %v; want %v", rb[:n], wb)
|
||||
return
|
||||
} else {
|
||||
s := cm.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Errorf("should be space-separated values: %s", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
writer := func(toggle bool) {
|
||||
defer wg.Done()
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: net.IPv4(127, 0, 0, 1),
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if n != len(wb) {
|
||||
t.Errorf("got %d; want %d", n, len(wb))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const N = 10
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Add(2 * N)
|
||||
for i := 0; i < 2*N; i++ {
|
||||
go writer(i%2 != 0)
|
||||
}
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
247
vendor/golang.org/x/net/ipv4/unicast_test.go
generated
vendored
247
vendor/golang.org/x/net/ipv4/unicast_test.go
generated
vendored
|
@ -1,247 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := nettest.NewLocalPacketListener("udp4")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
dst := c.LocalAddr()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.SetTTL(i + 1)
|
||||
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n, err := p.WriteTo(wb, nil, dst); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Fatalf("got %v; want %v", rb[:n], wb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p := ipv4.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
cf := ipv4.FlagDst | ipv4.FlagInterface
|
||||
if runtime.GOOS != "solaris" {
|
||||
// Solaris never allows to modify ICMP properties.
|
||||
cf |= ipv4.FlagTTL
|
||||
}
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
wb, err := (&icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.SetTTL(i + 1)
|
||||
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n, err := p.WriteTo(wb, nil, dst); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
loop:
|
||||
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
|
||||
// On Linux we must handle own sent packets.
|
||||
goto loop
|
||||
}
|
||||
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
|
||||
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawConnReadWriteUnicastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Close()
|
||||
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
wb, err := (&icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wh := &ipv4.Header{
|
||||
Version: ipv4.Version,
|
||||
Len: ipv4.HeaderLen,
|
||||
TOS: i + 1,
|
||||
TotalLen: ipv4.HeaderLen + len(wb),
|
||||
TTL: i + 1,
|
||||
Protocol: 1,
|
||||
Dst: dst.IP,
|
||||
}
|
||||
if err := r.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.WriteTo(wh, wb, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rb := make([]byte, ipv4.HeaderLen+128)
|
||||
loop:
|
||||
if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, b, _, err := r.ReadFrom(rb); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
|
||||
// On Linux we must handle own sent packets.
|
||||
goto loop
|
||||
}
|
||||
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
|
||||
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
148
vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
generated
vendored
148
vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
generated
vendored
|
@ -1,148 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestConnUnicastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp4", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
errc := make(chan error, 1)
|
||||
go func() {
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
errc <- c.Close()
|
||||
}()
|
||||
|
||||
c, err := net.Dial("tcp4", ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
testUnicastSocketOptions(t, ipv4.NewConn(c))
|
||||
|
||||
if err := <-errc; err != nil {
|
||||
t.Errorf("server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var packetConnUnicastSocketOptionTests = []struct {
|
||||
net, proto, addr string
|
||||
}{
|
||||
{"udp4", "", "127.0.0.1:0"},
|
||||
{"ip4", ":icmp", "127.0.0.1"},
|
||||
}
|
||||
|
||||
func TestPacketConnUnicastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
m, ok := nettest.SupportsRawIPSocket()
|
||||
for _, tt := range packetConnUnicastSocketOptionTests {
|
||||
if tt.net == "ip4" && !ok {
|
||||
t.Log(m)
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
testUnicastSocketOptions(t, ipv4.NewPacketConn(c))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawConnUnicastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
r, err := ipv4.NewRawConn(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testUnicastSocketOptions(t, r)
|
||||
}
|
||||
|
||||
type testIPv4UnicastConn interface {
|
||||
TOS() (int, error)
|
||||
SetTOS(int) error
|
||||
TTL() (int, error)
|
||||
SetTTL(int) error
|
||||
}
|
||||
|
||||
func testUnicastSocketOptions(t *testing.T, c testIPv4UnicastConn) {
|
||||
tos := iana.DiffServCS0 | iana.NotECNTransport
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
// IP_TOS option is supported on Windows 8 and beyond.
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
if err := c.SetTOS(tos); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v, err := c.TOS(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if v != tos {
|
||||
t.Fatalf("got %v; want %v", v, tos)
|
||||
}
|
||||
const ttl = 255
|
||||
if err := c.SetTTL(ttl); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v, err := c.TTL(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if v != ttl {
|
||||
t.Fatalf("got %v; want %v", v, ttl)
|
||||
}
|
||||
}
|
96
vendor/golang.org/x/net/ipv6/bpf_test.go
generated
vendored
96
vendor/golang.org/x/net/ipv6/bpf_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func TestBPF(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
l, err := net.ListenPacket("udp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(l)
|
||||
|
||||
// This filter accepts UDP packets whose first payload byte is
|
||||
// even.
|
||||
prog, err := bpf.Assemble([]bpf.Instruction{
|
||||
// Load the first byte of the payload (skipping UDP header).
|
||||
bpf.LoadAbsolute{Off: 8, Size: 1},
|
||||
// Select LSB of the byte.
|
||||
bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
|
||||
// Byte is even?
|
||||
bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
|
||||
// Accept.
|
||||
bpf.RetConstant{Val: 4096},
|
||||
// Ignore.
|
||||
bpf.RetConstant{Val: 0},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("compiling BPF: %s", err)
|
||||
}
|
||||
|
||||
if err = p.SetBPF(prog); err != nil {
|
||||
t.Fatalf("attaching filter to Conn: %s", err)
|
||||
}
|
||||
|
||||
s, err := net.Dial("udp6", l.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
go func() {
|
||||
for i := byte(0); i < 10; i++ {
|
||||
s.Write([]byte{i})
|
||||
}
|
||||
}()
|
||||
|
||||
l.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
seen := make([]bool, 5)
|
||||
for {
|
||||
var b [512]byte
|
||||
n, _, err := l.ReadFrom(b[:])
|
||||
if err != nil {
|
||||
t.Fatalf("reading from listener: %s", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Fatalf("unexpected packet length, want 1, got %d", n)
|
||||
}
|
||||
if b[0] >= 10 {
|
||||
t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
|
||||
}
|
||||
if b[0]%2 != 0 {
|
||||
t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
|
||||
}
|
||||
seen[b[0]/2] = true
|
||||
|
||||
seenAll := true
|
||||
for _, v := range seen {
|
||||
if !v {
|
||||
seenAll = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if seenAll {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
21
vendor/golang.org/x/net/ipv6/control_test.go
generated
vendored
21
vendor/golang.org/x/net/ipv6/control_test.go
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func TestControlMessageParseWithFuzz(t *testing.T) {
|
||||
var cm ipv6.ControlMessage
|
||||
for _, fuzz := range []string{
|
||||
"\f\x00\x00\x00)\x00\x00\x00.\x00\x00\x00",
|
||||
"\f\x00\x00\x00)\x00\x00\x00,\x00\x00\x00",
|
||||
} {
|
||||
cm.Parse([]byte(fuzz))
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/net/ipv6/doc.go
generated
vendored
2
vendor/golang.org/x/net/ipv6/doc.go
generated
vendored
|
@ -56,7 +56,7 @@
|
|||
// Multicasting
|
||||
//
|
||||
// The options for multicasting are available for net.UDPConn and
|
||||
// net.IPconn which are created as network connections that use the
|
||||
// net.IPConn which are created as network connections that use the
|
||||
// IPv6 transport. A few network facilities must be prepared before
|
||||
// you begin multicasting, at a minimum joining network interfaces and
|
||||
// multicast groups.
|
||||
|
|
216
vendor/golang.org/x/net/ipv6/example_test.go
generated
vendored
216
vendor/golang.org/x/net/ipv6/example_test.go
generated
vendored
|
@ -1,216 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func ExampleConn_markingTCP() {
|
||||
ln, err := net.Listen("tcp", "[::]:1024")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
for {
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
defer c.Close()
|
||||
if c.RemoteAddr().(*net.TCPAddr).IP.To16() != nil && c.RemoteAddr().(*net.TCPAddr).IP.To4() == nil {
|
||||
p := ipv6.NewConn(c)
|
||||
if err := p.SetTrafficClass(0x28); err != nil { // DSCP AF11
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := p.SetHopLimit(128); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(c)
|
||||
}
|
||||
}
|
||||
|
||||
func ExamplePacketConn_servingOneShotMulticastDNS() {
|
||||
c, err := net.ListenPacket("udp6", "[::]:5353") // mDNS over UDP
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
en0, err := net.InterfaceByName("en0")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")}
|
||||
if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(en0, &mDNSLinkLocal)
|
||||
if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var wcm ipv6.ControlMessage
|
||||
b := make([]byte, 1500)
|
||||
for {
|
||||
_, rcm, peer, err := p.ReadFrom(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) {
|
||||
continue
|
||||
}
|
||||
wcm.IfIndex = rcm.IfIndex
|
||||
answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
|
||||
if _, err := p.WriteTo(answers, &wcm, peer); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExamplePacketConn_tracingIPPacketRoute() {
|
||||
// Tracing an IP packet route to www.google.com.
|
||||
|
||||
const host = "www.google.com"
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var dst net.IPAddr
|
||||
for _, ip := range ips {
|
||||
if ip.To16() != nil && ip.To4() == nil {
|
||||
dst.IP = ip
|
||||
fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
|
||||
break
|
||||
}
|
||||
}
|
||||
if dst.IP == nil {
|
||||
log.Fatal("no AAAA record found")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
wm := icmp.Message{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Accept(ipv6.ICMPTypeTimeExceeded)
|
||||
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var wcm ipv6.ControlMessage
|
||||
rb := make([]byte, 1500)
|
||||
for i := 1; i <= 64; i++ { // up to 64 hops
|
||||
wm.Body.(*icmp.Echo).Seq = i
|
||||
wb, err := wm.Marshal(nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// In the real world usually there are several
|
||||
// multiple traffic-engineered paths for each hop.
|
||||
// You may need to probe a few times to each hop.
|
||||
begin := time.Now()
|
||||
wcm.HopLimit = i
|
||||
if _, err := p.WriteTo(wb, &wcm, &dst); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
n, rcm, peer, err := p.ReadFrom(rb)
|
||||
if err != nil {
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
fmt.Printf("%v\t*\n", i)
|
||||
continue
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
rm, err := icmp.ParseMessage(58, rb[:n])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
rtt := time.Since(begin)
|
||||
|
||||
// In the real world you need to determine whether the
|
||||
// received message is yours using ControlMessage.Src,
|
||||
// ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
|
||||
switch rm.Type {
|
||||
case ipv6.ICMPTypeTimeExceeded:
|
||||
names, _ := net.LookupAddr(peer.String())
|
||||
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
|
||||
case ipv6.ICMPTypeEchoReply:
|
||||
names, _ := net.LookupAddr(peer.String())
|
||||
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExamplePacketConn_advertisingOSPFHello() {
|
||||
c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
en0, err := net.InterfaceByName("en0")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
allSPFRouters := net.IPAddr{IP: net.ParseIP("ff02::5")}
|
||||
if err := p.JoinGroup(en0, &allSPFRouters); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(en0, &allSPFRouters)
|
||||
|
||||
hello := make([]byte, 24) // fake hello data, you need to implement this
|
||||
ospf := make([]byte, 16) // fake ospf header, you need to implement this
|
||||
ospf[0] = 3 // version 3
|
||||
ospf[1] = 1 // hello packet
|
||||
ospf = append(ospf, hello...)
|
||||
if err := p.SetChecksum(true, 12); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: 0xc0, // DSCP CS6
|
||||
HopLimit: 1,
|
||||
IfIndex: en0.Index,
|
||||
}
|
||||
if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
55
vendor/golang.org/x/net/ipv6/header_test.go
generated
vendored
55
vendor/golang.org/x/net/ipv6/header_test.go
generated
vendored
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var (
|
||||
wireHeaderFromKernel = [ipv6.HeaderLen]byte{
|
||||
0x69, 0x8b, 0xee, 0xf1,
|
||||
0xca, 0xfe, 0x2c, 0x01,
|
||||
0x20, 0x01, 0x0d, 0xb8,
|
||||
0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x20, 0x01, 0x0d, 0xb8,
|
||||
0x00, 0x02, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
}
|
||||
|
||||
testHeader = &ipv6.Header{
|
||||
Version: ipv6.Version,
|
||||
TrafficClass: iana.DiffServAF43,
|
||||
FlowLabel: 0xbeef1,
|
||||
PayloadLen: 0xcafe,
|
||||
NextHeader: iana.ProtocolIPv6Frag,
|
||||
HopLimit: 1,
|
||||
Src: net.ParseIP("2001:db8:1::1"),
|
||||
Dst: net.ParseIP("2001:db8:2::1"),
|
||||
}
|
||||
)
|
||||
|
||||
func TestParseHeader(t *testing.T) {
|
||||
h, err := ipv6.ParseHeader(wireHeaderFromKernel[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(h, testHeader) {
|
||||
t.Fatalf("got %#v; want %#v", h, testHeader)
|
||||
}
|
||||
s := h.String()
|
||||
if strings.Contains(s, ",") {
|
||||
t.Fatalf("should be space-separated values: %s", s)
|
||||
}
|
||||
}
|
96
vendor/golang.org/x/net/ipv6/icmp_test.go
generated
vendored
96
vendor/golang.org/x/net/ipv6/icmp_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var icmpStringTests = []struct {
|
||||
in ipv6.ICMPType
|
||||
out string
|
||||
}{
|
||||
{ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
|
||||
|
||||
{256, "<nil>"},
|
||||
}
|
||||
|
||||
func TestICMPString(t *testing.T) {
|
||||
for _, tt := range icmpStringTests {
|
||||
s := tt.in.String()
|
||||
if s != tt.out {
|
||||
t.Errorf("got %s; want %s", s, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
for _, toggle := range []bool{false, true} {
|
||||
f.SetAll(toggle)
|
||||
for _, typ := range []ipv6.ICMPType{
|
||||
ipv6.ICMPTypeDestinationUnreachable,
|
||||
ipv6.ICMPTypeEchoReply,
|
||||
ipv6.ICMPTypeNeighborSolicitation,
|
||||
ipv6.ICMPTypeDuplicateAddressConfirmation,
|
||||
} {
|
||||
f.Accept(typ)
|
||||
if f.WillBlock(typ) {
|
||||
t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ)
|
||||
}
|
||||
f.Block(typ)
|
||||
if !f.WillBlock(typ) {
|
||||
t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Accept(ipv6.ICMPTypeEchoRequest)
|
||||
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kf, err := p.ICMPFilter()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(kf, &f) {
|
||||
t.Fatalf("got %#v; want %#v", kf, f)
|
||||
}
|
||||
}
|
32
vendor/golang.org/x/net/ipv6/mocktransponder_test.go
generated
vendored
32
vendor/golang.org/x/net/ipv6/mocktransponder_test.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func connector(t *testing.T, network, addr string, done chan<- bool) {
|
||||
defer func() { done <- true }()
|
||||
|
||||
c, err := net.Dial(network, addr)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
|
||||
func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
|
||||
defer func() { done <- true }()
|
||||
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
c.Close()
|
||||
}
|
264
vendor/golang.org/x/net/ipv6/multicast_test.go
generated
vendored
264
vendor/golang.org/x/net/ipv6/multicast_test.go
generated
vendored
|
@ -1,264 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var packetConnReadWriteMulticastUDPTests = []struct {
|
||||
addr string
|
||||
grp, src *net.UDPAddr
|
||||
}{
|
||||
{"[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||
|
||||
{"[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() {
|
||||
t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range packetConnReadWriteMulticastUDPTests {
|
||||
c, err := net.ListenPacket("udp6", tt.addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
grp := *tt.grp
|
||||
grp.Port = c.LocalAddr().(*net.UDPAddr).Port
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if tt.src == nil {
|
||||
if err := p.JoinGroup(ifi, &grp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(ifi, &grp)
|
||||
} else {
|
||||
if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support MLDv2 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
IfIndex: ifi.Index,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if n, err := p.WriteTo(wb, &cm, &grp); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Fatalf("got %v; want %v", rb[:n], wb)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var packetConnReadWriteMulticastICMPTests = []struct {
|
||||
grp, src *net.IPAddr
|
||||
}{
|
||||
{&net.IPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||
|
||||
{&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() {
|
||||
t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS)
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range packetConnReadWriteMulticastICMPTests {
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP)
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if tt.src == nil {
|
||||
if err := p.JoinGroup(ifi, tt.grp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveGroup(ifi, tt.grp)
|
||||
} else {
|
||||
if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support MLDv2 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
IfIndex: ifi.Index,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var psh []byte
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if toggle {
|
||||
psh = nil
|
||||
if err := p.SetChecksum(true, 2); err != nil {
|
||||
// Solaris never allows to
|
||||
// modify ICMP properties.
|
||||
if runtime.GOOS != "solaris" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
psh = pshicmp
|
||||
// Some platforms never allow to
|
||||
// disable the kernel checksum
|
||||
// processing.
|
||||
p.SetChecksum(false, -1)
|
||||
}
|
||||
wb, err := (&icmp.Message{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(psh)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
if nettest.ProtocolNotSupported(err) {
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
|
||||
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
261
vendor/golang.org/x/net/ipv6/multicastlistener_test.go
generated
vendored
261
vendor/golang.org/x/net/ipv6/multicastlistener_test.go
generated
vendored
|
@ -1,261 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var udpMultipleGroupListenerTests = []net.Addr{
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
|
||||
}
|
||||
|
||||
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c1, err := net.ListenPacket("udp6", "[ff02::]:0") // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c1.Close()
|
||||
_, port, err := net.SplitHostPort(c1.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c2, err := net.ListenPacket("udp6", net.JoinHostPort("ff02::", port)) // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c2.Close()
|
||||
|
||||
var ps [2]*ipv6.PacketConn
|
||||
ps[0] = ipv6.NewPacketConn(c1)
|
||||
ps[1] = ipv6.NewPacketConn(c2)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
for _, p := range ps {
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
for _, p := range ps {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv6.PacketConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port := "0"
|
||||
for i, ifi := range ift {
|
||||
ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("udp6", net.JoinHostPort(ip.String()+"%"+ifi.Name, port)) // unicast address with non-reusable port
|
||||
if err != nil {
|
||||
// The listen may fail when the serivce is
|
||||
// already in use, but it's fine because the
|
||||
// purpose of this is not to test the
|
||||
// bookkeeping of IP control block inside the
|
||||
// kernel.
|
||||
t.Log(err)
|
||||
continue
|
||||
}
|
||||
defer c.Close()
|
||||
if port == "0" {
|
||||
_, port, err = net.SplitHostPort(c.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
p := ipv6.NewPacketConn(c)
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mlt = append(mlt, &ml{p, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := p.LeaveGroup(ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv6.PacketConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", ip.String()+"%"+ifi.Name) // unicast address
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mlt = append(mlt, &ml{p, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
157
vendor/golang.org/x/net/ipv6/multicastsockopt_test.go
generated
vendored
157
vendor/golang.org/x/net/ipv6/multicastsockopt_test.go
generated
vendored
|
@ -1,157 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var packetConnMulticastSocketOptionTests = []struct {
|
||||
net, proto, addr string
|
||||
grp, src net.Addr
|
||||
}{
|
||||
{"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
|
||||
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::115")}, nil}, // see RFC 4727
|
||||
|
||||
{"udp6", "", "[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff30::8000:2")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
|
||||
}
|
||||
|
||||
func TestPacketConnMulticastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "js", "nacl", "plan9", "windows":
|
||||
t.Skipf("not supported on %s", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
m, ok := nettest.SupportsRawIPSocket()
|
||||
for _, tt := range packetConnMulticastSocketOptionTests {
|
||||
if tt.net == "ip6" && !ok {
|
||||
t.Log(m)
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
if tt.src == nil {
|
||||
testMulticastSocketOptions(t, p, ifi, tt.grp)
|
||||
} else {
|
||||
testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testIPv6MulticastConn interface {
|
||||
MulticastHopLimit() (int, error)
|
||||
SetMulticastHopLimit(ttl int) error
|
||||
MulticastLoopback() (bool, error)
|
||||
SetMulticastLoopback(bool) error
|
||||
JoinGroup(*net.Interface, net.Addr) error
|
||||
LeaveGroup(*net.Interface, net.Addr) error
|
||||
JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||
}
|
||||
|
||||
func testMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) {
|
||||
const hoplim = 255
|
||||
if err := c.SetMulticastHopLimit(hoplim); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if v, err := c.MulticastHopLimit(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if v != hoplim {
|
||||
t.Errorf("got %v; want %v", v, hoplim)
|
||||
return
|
||||
}
|
||||
|
||||
for _, toggle := range []bool{true, false} {
|
||||
if err := c.SetMulticastLoopback(toggle); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if v, err := c.MulticastLoopback(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if v != toggle {
|
||||
t.Errorf("got %v; want %v", v, toggle)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp, src net.Addr) {
|
||||
// MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
|
||||
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
default: // platforms that don't support MLDv2 fail here
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
|
||||
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
|
||||
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/net/ipv6/payload_cmsg.go
generated
vendored
2
vendor/golang.org/x/net/ipv6/payload_cmsg.go
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv6
|
||||
|
||||
|
|
2
vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go
generated
vendored
2
vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.9
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv6
|
||||
|
||||
|
|
2
vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go
generated
vendored
2
vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
// +build !nacl,!plan9,!windows
|
||||
// +build !js,!nacl,!plan9,!windows
|
||||
|
||||
package ipv6
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue