Update dependencies

This commit is contained in:
Zlatko Čalušić
2017-06-25 12:06:41 +02:00
parent 0c22253d41
commit 4873fd9ffe
47 changed files with 11212 additions and 9462 deletions

8
glide.lock generated
View File

@@ -1,8 +1,8 @@
hash: fa6b47593c912fd3ce7a0a9bb3f2893f61e3e4b6f7a5772c5e602e1038d74015
updated: 2017-06-02T10:26:06.121356863+02:00
updated: 2017-06-25T12:05:26.132955333+02:00
imports:
- name: github.com/gorilla/handlers
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3
version: a4d79d4487c2430a17d9dc8a1f74d1a6ed6908ca
repo: https://github.com/gorilla/handlers
vcs: git
- name: github.com/inconshreveable/mousetrap
@@ -10,7 +10,7 @@ imports:
repo: https://github.com/inconshreveable/mousetrap
vcs: git
- name: github.com/spf13/cobra
version: 8d4ce3549a0bf0e3569df3aae7423b7743cd05a9
version: 4d647c8944eb42504a714e57e97f244ed6344722
repo: https://github.com/spf13/cobra
vcs: git
- name: github.com/spf13/pflag
@@ -27,7 +27,7 @@ imports:
- pat
- pattern
- name: golang.org/x/net
version: 3da985ce5951d99de868be4385f21ea6c2b22f24
version: 5f8847ae0d0e90b6a9dc8148e7ad616874625171
repo: https://github.com/golang/net
vcs: git
testImports: []

View File

@@ -7,6 +7,7 @@ matrix:
- go: 1.5
- go: 1.6
- go: 1.7
- go: 1.8
- go: tip
allow_failures:
- go: tip
@@ -16,3 +17,4 @@ script:
- diff -u <(echo -n) <(gofmt -d .)
- go vet $(go list ./... | grep -v /vendor/)
- go test -v -race ./...

View File

@@ -140,8 +140,8 @@ import "github.com/spf13/cobra"
# Getting Started
While you are welcome to provide your own organization, typically a Cobra based
application will follow the following organizational structure.
While you are welcome to provide your own organization, typically a Cobra-based
application will follow the following organizational structure:
```
▾ appName/
@@ -153,7 +153,7 @@ application will follow the following organizational structure.
main.go
```
In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra.
In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra.
```go
package main
@@ -216,10 +216,11 @@ cobra add create -p 'configCmd'
```
*Note: Use camelCase (not snake_case/snake-case) for command names.
Otherwise, you will become unexpected errors.
Otherwise, you will encounter errors.
For example, `cobra add add-user` is incorrect, but `cobra add addUser` is valid.*
Once you have run these three commands you would have an app structure that would look like:
Once you have run these three commands you would have an app structure similar to
the following:
```
▾ app/
@@ -232,14 +233,14 @@ Once you have run these three commands you would have an app structure that woul
At this point you can run `go run main.go` and it would run your app. `go run
main.go serve`, `go run main.go config`, `go run main.go config create` along
with `go run main.go help serve`, etc would all work.
with `go run main.go help serve`, etc. would all work.
Obviously you haven't added your own code to these yet, the commands are ready
Obviously you haven't added your own code to these yet. The commands are ready
for you to give them their tasks. Have fun!
### Configuring the cobra generator
The cobra generator will be easier to use if you provide a simple configuration
The Cobra generator will be easier to use if you provide a simple configuration
file which will help you eliminate providing a bunch of repeated information in
flags over and over.
@@ -269,7 +270,7 @@ You can also use built-in licenses. For example, **GPLv2**, **GPLv3**, **LGPL**,
## Manually implementing Cobra
To manually implement cobra you need to create a bare main.go file and a RootCmd file.
To manually implement Cobra you need to create a bare main.go file and a RootCmd file.
You will optionally provide additional commands as you see fit.
### Create the root command
@@ -323,7 +324,11 @@ func init() {
viper.SetDefault("license", "apache")
}
func main() {
func Execute() {
RootCmd.Execute()
}
func initConfig() {
// Don't forget to read config either from cfgFile or from home directory!
if cfgFile != "" {
// Use config file from the flag.
@@ -332,7 +337,7 @@ func main() {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(home)
fmt.Println(err)
os.Exit(1)
}

View File

@@ -132,7 +132,10 @@ __handle_reply()
declare -F __custom_func >/dev/null && __custom_func
fi
# available in bash-completion >= 2, not always present on macOS
if declare -F __ltrim_colon_completions >/dev/null; then
__ltrim_colon_completions "$cur"
fi
}
# The arguments should be in the form "ext1|ext2|extn"

View File

@@ -2,7 +2,6 @@ package cobra
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"strings"
@@ -181,15 +180,12 @@ func BenchmarkBashCompletion(b *testing.B) {
cmdEcho.AddCommand(cmdTimes)
c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated, cmdColon)
file, err := ioutil.TempFile("", "")
if err != nil {
b.Fatal(err)
}
defer os.Remove(file.Name())
buf := new(bytes.Buffer)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := c.GenBashCompletion(file); err != nil {
buf.Reset()
if err := c.GenBashCompletion(buf); err != nil {
b.Fatal(err)
}
}

View File

@@ -23,10 +23,11 @@ import (
)
func init() {
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
addCmd.Flags().StringVarP(&parentName, "parent", "p", "RootCmd", "name of parent command for this command")
}
var parentName string
var packageName, parentName string
var addCmd = &cobra.Command{
Use: "add [command name]",
@@ -45,11 +46,17 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
if len(args) < 1 {
er("add needs a name for the command")
}
var project *Project
if packageName != "" {
project = NewProject(packageName)
} else {
wd, err := os.Getwd()
if err != nil {
er(err)
}
project := NewProjectFromPath(wd)
project = NewProjectFromPath(wd)
}
cmdName := validateCmdName(args[0])
cmdPath := filepath.Join(project.CmdPath(), cmdName+".go")

View File

@@ -59,7 +59,7 @@ Init will not use an existing directory with contents.`,
project = NewProject(arg)
}
} else {
er("please enter the name")
er("please provide only one argument")
}
initializeProject(project)
@@ -142,13 +142,13 @@ package cmd
import (
"fmt"
"os"
{{if .viper}}
homedir "github.com/mitchellh/go-homedir"{{end}}
"github.com/spf13/cobra"{{if .viper}}
"github.com/spf13/viper"{{end}}
){{if .viper}}
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
{{if .viper}} "github.com/spf13/viper"{{end}}
)
{{if .viper}}var cfgFile string{{end}}
var cfgFile string{{end}}
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
@@ -165,7 +165,7 @@ to quickly create a Cobra application.` + "`" + `,
// Run: func(cmd *cobra.Command, args []string) { },
}
// Execute adds all child commands to the root command sets flags appropriately.
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
@@ -174,9 +174,9 @@ func Execute() {
}
}
func init() {
{{if .viper}} cobra.OnInitialize(initConfig){{end}}
func init() { {{if .viper}}
cobra.OnInitialize(initConfig)
{{end}}
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.{{ if .viper }}

View File

@@ -44,16 +44,15 @@ func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project (can provide `license` in config)")
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
rootCmd.AddCommand(initCmd)
rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(initCmd)
}
func initViper() {

View File

@@ -39,7 +39,7 @@ to quickly create a Cobra application.`,
// Run: func(cmd *cobra.Command, args []string) { },
}
// Execute adds all child commands to the root command sets flags appropriately.
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {

View File

@@ -1249,13 +1249,20 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
}
// ParseFlags parses persistent flag tree and local flags.
func (c *Command) ParseFlags(args []string) (err error) {
func (c *Command) ParseFlags(args []string) error {
if c.DisableFlagParsing {
return nil
}
beforeErrorBufLen := c.flagErrorBuf.Len()
c.mergePersistentFlags()
err = c.Flags().Parse(args)
return
err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
c.Print(c.flagErrorBuf.String())
}
return err
}
// Parent returns a commands parent command.

View File

@@ -298,3 +298,23 @@ func TestMergeCommandLineToFlags(t *testing.T) {
// Reset pflag.CommandLine flagset.
pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
}
// TestUseDeprecatedFlags checks,
// if cobra.Execute() prints a message, if a deprecated flag is used.
// Related to https://github.com/spf13/cobra/issues/463.
func TestUseDeprecatedFlags(t *testing.T) {
c := &Command{Use: "c", Run: func(*Command, []string) {}}
output := new(bytes.Buffer)
c.SetOutput(output)
c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
c.SetArgs([]string{"c", "-d"})
if err := c.Execute(); err != nil {
t.Error("Unexpected error:", err)
}
if !strings.Contains(output.String(), "This flag is deprecated") {
t.Errorf("Expected to contain deprecated message, but got %q", output.String())
}
}

View File

@@ -76,54 +76,54 @@ const (
// ExtLen returns the length of the packet.
ExtLen Extension = 1
// ExtProto returns the packet's L3 protocol type.
ExtProto = 0
ExtProto Extension = 0
// ExtType returns the packet's type (skb->pkt_type in the kernel)
//
// TODO: better documentation. How nice an API do we want to
// provide for these esoteric extensions?
ExtType = 4
ExtType Extension = 4
// ExtPayloadOffset returns the offset of the packet payload, or
// the first protocol header that the kernel does not know how to
// parse.
ExtPayloadOffset = 52
ExtPayloadOffset Extension = 52
// ExtInterfaceIndex returns the index of the interface on which
// the packet was received.
ExtInterfaceIndex = 8
ExtInterfaceIndex Extension = 8
// ExtNetlinkAttr returns the netlink attribute of type X at
// offset A.
ExtNetlinkAttr = 12
ExtNetlinkAttr Extension = 12
// ExtNetlinkAttrNested returns the nested netlink attribute of
// type X at offset A.
ExtNetlinkAttrNested = 16
ExtNetlinkAttrNested Extension = 16
// ExtMark returns the packet's mark value.
ExtMark = 20
ExtMark Extension = 20
// ExtQueue returns the packet's assigned hardware queue.
ExtQueue = 24
ExtQueue Extension = 24
// ExtLinkLayerType returns the packet's hardware address type
// (e.g. Ethernet, Infiniband).
ExtLinkLayerType = 28
ExtLinkLayerType Extension = 28
// ExtRXHash returns the packets receive hash.
//
// TODO: figure out what this rxhash actually is.
ExtRXHash = 32
ExtRXHash Extension = 32
// ExtCPUID returns the ID of the CPU processing the current
// packet.
ExtCPUID = 36
ExtCPUID Extension = 36
// ExtVLANTag returns the packet's VLAN tag.
ExtVLANTag = 44
ExtVLANTag Extension = 44
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
// tag.
//
// TODO: I think this might be a lie: it reads bit 0x1000 of the
// VLAN header, which changed meaning in recent revisions of the
// spec - this extension may now return meaningless information.
ExtVLANTagPresent = 48
ExtVLANTagPresent Extension = 48
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
// other value if no VLAN information is present.
ExtVLANProto = 60
ExtVLANProto Extension = 60
// ExtRand returns a uniformly random uint32.
ExtRand = 56
ExtRand Extension = 56
)
// The following gives names to various bit patterns used in opcode construction.

10
vendor/golang.org/x/net/bpf/setter.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
// 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 bpf
// A Setter is a type which can attach a compiled BPF filter to itself.
type Setter interface {
SetBPF(filter []RawInstruction) error
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@
package dnsmessage
import (
"bytes"
"fmt"
"net"
"reflect"
@@ -12,6 +13,14 @@ import (
"testing"
)
func mustNewName(name string) Name {
n, err := NewName(name)
if err != nil {
panic(err)
}
return n
}
func (m *Message) String() string {
s := fmt.Sprintf("Message: %#v\n", &m.Header)
if len(m.Questions) > 0 {
@@ -41,9 +50,17 @@ func (m *Message) String() string {
return s
}
func TestNameString(t *testing.T) {
want := "foo"
name := mustNewName(want)
if got := fmt.Sprint(name); got != want {
t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
}
}
func TestQuestionPackUnpack(t *testing.T) {
want := Question{
Name: ".",
Name: mustNewName("."),
Type: TypeA,
Class: ClassINET,
}
@@ -68,16 +85,42 @@ func TestQuestionPackUnpack(t *testing.T) {
}
}
func TestName(t *testing.T) {
tests := []string{
"",
".",
"google..com",
"google.com",
"google..com.",
"google.com.",
".google.com.",
"www..google.com.",
"www.google.com.",
}
for _, test := range tests {
n, err := NewName(test)
if err != nil {
t.Errorf("Creating name for %q: %v", test, err)
continue
}
if ns := n.String(); ns != test {
t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
continue
}
}
}
func TestNamePackUnpack(t *testing.T) {
tests := []struct {
in string
want string
err error
}{
{"", ".", nil},
{"", "", errNonCanonicalName},
{".", ".", nil},
{"google..com", "", errZeroSegLen},
{"google.com", "google.com.", nil},
{"google..com", "", errNonCanonicalName},
{"google.com", "", errNonCanonicalName},
{"google..com.", "", errZeroSegLen},
{"google.com.", "google.com.", nil},
{".google.com.", "", errZeroSegLen},
@@ -86,29 +129,91 @@ func TestNamePackUnpack(t *testing.T) {
}
for _, test := range tests {
buf, err := packName(make([]byte, 0, 30), test.in, map[string]int{})
in := mustNewName(test.in)
want := mustNewName(test.want)
buf, err := in.pack(make([]byte, 0, 30), map[string]int{})
if err != test.err {
t.Errorf("Packing of %s: got err = %v, want err = %v", test.in, err, test.err)
t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
continue
}
if test.err != nil {
continue
}
got, n, err := unpackName(buf, 0)
var got Name
n, err := got.unpack(buf, 0)
if err != nil {
t.Errorf("Unpacking for %s failed: %v", test.in, err)
t.Errorf("Unpacking for %q failed: %v", test.in, err)
continue
}
if n != len(buf) {
t.Errorf(
"Unpacked different amount than packed for %s: got n = %d, want = %d",
"Unpacked different amount than packed for %q: got n = %d, want = %d",
test.in,
n,
len(buf),
)
}
if got != test.want {
t.Errorf("Unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
if got != want {
t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
}
}
}
func checkErrorPrefix(err error, prefix string) bool {
e, ok := err.(*nestedError)
return ok && e.s == prefix
}
func TestHeaderUnpackError(t *testing.T) {
wants := []string{
"id",
"bits",
"questions",
"answers",
"authorities",
"additionals",
}
var buf []byte
var h header
for _, want := range wants {
n, err := h.unpack(buf, 0)
if n != 0 || !checkErrorPrefix(err, want) {
t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
}
buf = append(buf, 0, 0)
}
}
func TestParserStart(t *testing.T) {
const want = "unpacking header"
var p Parser
for i := 0; i <= 1; i++ {
_, err := p.Start([]byte{})
if !checkErrorPrefix(err, want) {
t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want)
}
}
}
func TestResourceNotStarted(t *testing.T) {
tests := []struct {
name string
fn func(*Parser) error
}{
{"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
{"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
{"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
{"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
{"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
{"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
{"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
{"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
{"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
}
for _, test := range tests {
if err := test.fn(&Parser{}); err != ErrNotStarted {
t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted)
}
}
}
@@ -118,7 +223,7 @@ func TestDNSPackUnpack(t *testing.T) {
{
Questions: []Question{
{
Name: ".",
Name: mustNewName("."),
Type: TypeAAAA,
Class: ClassINET,
},
@@ -238,32 +343,196 @@ func TestTooManyRecords(t *testing.T) {
}
func TestVeryLongTxt(t *testing.T) {
want := &TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
want := Resource{
ResourceHeader{
Name: mustNewName("foo.bar.example.com."),
Type: TypeTXT,
Class: ClassINET,
},
Txt: loremIpsum,
&TXTResource{loremIpsum},
}
buf, err := packResource(make([]byte, 0, 8000), want, map[string]int{})
buf, err := want.pack(make([]byte, 0, 8000), map[string]int{})
if err != nil {
t.Fatal("Packing failed:", err)
}
var hdr ResourceHeader
off, err := hdr.unpack(buf, 0)
var got Resource
off, err := got.Header.unpack(buf, 0)
if err != nil {
t.Fatal("Unpacking ResourceHeader failed:", err)
}
got, n, err := unpackResource(buf, off, hdr)
body, n, err := unpackResourceBody(buf, off, got.Header)
if err != nil {
t.Fatal("Unpacking failed:", err)
}
got.Body = body
if n != len(buf) {
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
}
if !reflect.DeepEqual(got, want) {
t.Errorf("Got = %+v, want = %+v", got, want)
t.Errorf("Got = %#v, want = %#v", got, want)
}
}
func TestStartError(t *testing.T) {
tests := []struct {
name string
fn func(*Builder) error
}{
{"Questions", func(b *Builder) error { return b.StartQuestions() }},
{"Answers", func(b *Builder) error { return b.StartAnswers() }},
{"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
{"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
}
envs := []struct {
name string
fn func() *Builder
want error
}{
{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
}
for _, env := range envs {
for _, test := range tests {
if got := test.fn(env.fn()); got != env.want {
t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
}
}
}
}
func TestBuilderResourceError(t *testing.T) {
tests := []struct {
name string
fn func(*Builder) error
}{
{"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
{"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
{"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
{"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
{"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
{"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
{"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
{"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
{"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
}
envs := []struct {
name string
fn func() *Builder
want error
}{
{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
{"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
{"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
}
for _, env := range envs {
for _, test := range tests {
if got := test.fn(env.fn()); got != env.want {
t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
}
}
}
}
func TestFinishError(t *testing.T) {
var b Builder
want := ErrNotStarted
if _, got := b.Finish(); got != want {
t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
}
}
func TestBuilder(t *testing.T) {
msg := largeTestMsg()
want, err := msg.Pack()
if err != nil {
t.Fatal("Packing without builder:", err)
}
var b Builder
b.Start(nil, msg.Header)
if err := b.StartQuestions(); err != nil {
t.Fatal("b.StartQuestions():", err)
}
for _, q := range msg.Questions {
if err := b.Question(q); err != nil {
t.Fatalf("b.Question(%#v): %v", q, err)
}
}
if err := b.StartAnswers(); err != nil {
t.Fatal("b.StartAnswers():", err)
}
for _, a := range msg.Answers {
switch a.Header.Type {
case TypeA:
if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
t.Fatalf("b.AResource(%#v): %v", a, err)
}
case TypeNS:
if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
t.Fatalf("b.NSResource(%#v): %v", a, err)
}
case TypeCNAME:
if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
t.Fatalf("b.CNAMEResource(%#v): %v", a, err)
}
case TypeSOA:
if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
t.Fatalf("b.SOAResource(%#v): %v", a, err)
}
case TypePTR:
if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
t.Fatalf("b.PTRResource(%#v): %v", a, err)
}
case TypeMX:
if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
t.Fatalf("b.MXResource(%#v): %v", a, err)
}
case TypeTXT:
if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
t.Fatalf("b.TXTResource(%#v): %v", a, err)
}
case TypeAAAA:
if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
t.Fatalf("b.AAAAResource(%#v): %v", a, err)
}
case TypeSRV:
if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
t.Fatalf("b.SRVResource(%#v): %v", a, err)
}
}
}
if err := b.StartAuthorities(); err != nil {
t.Fatal("b.StartAuthorities():", err)
}
for _, a := range msg.Authorities {
if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
t.Fatalf("b.NSResource(%#v): %v", a, err)
}
}
if err := b.StartAdditionals(); err != nil {
t.Fatal("b.StartAdditionals():", err)
}
for _, a := range msg.Additionals {
if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
t.Fatalf("b.TXTResource(%#v): %v", a, err)
}
}
got, err := b.Finish()
if err != nil {
t.Fatal("b.Finish():", err)
}
if !bytes.Equal(got, want) {
t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
}
}
@@ -272,32 +541,32 @@ func ExampleHeaderSearch() {
Header: Header{Response: true, Authoritative: true},
Questions: []Question{
{
Name: "foo.bar.example.com.",
Name: mustNewName("foo.bar.example.com."),
Type: TypeA,
Class: ClassINET,
},
{
Name: "bar.example.com.",
Name: mustNewName("bar.example.com."),
Type: TypeA,
Class: ClassINET,
},
},
Answers: []Resource{
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: mustNewName("foo.bar.example.com."),
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 1},
&AResource{[4]byte{127, 0, 0, 1}},
},
&AResource{
ResourceHeader: ResourceHeader{
Name: "bar.example.com.",
{
ResourceHeader{
Name: mustNewName("bar.example.com."),
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 2},
&AResource{[4]byte{127, 0, 0, 2}},
},
},
}
@@ -323,7 +592,7 @@ func ExampleHeaderSearch() {
panic(err)
}
if q.Name != wantName {
if q.Name.String() != wantName {
continue
}
@@ -348,23 +617,25 @@ func ExampleHeaderSearch() {
continue
}
if !strings.EqualFold(h.Name, wantName) {
if !strings.EqualFold(h.Name.String(), wantName) {
if err := p.SkipAnswer(); err != nil {
panic(err)
}
continue
}
a, err := p.Answer()
switch h.Type {
case TypeA:
r, err := p.AResource()
if err != nil {
panic(err)
}
switch r := a.(type) {
default:
panic(fmt.Sprintf("unknown type: %T", r))
case *AResource:
gotIPs = append(gotIPs, r.A[:])
case *AAAAResource:
case TypeAAAA:
r, err := p.AAAAResource()
if err != nil {
panic(err)
}
gotIPs = append(gotIPs, r.AAAA[:])
}
}
@@ -376,68 +647,288 @@ func ExampleHeaderSearch() {
// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
}
func largeTestMsg() Message {
return Message{
func BenchmarkParsing(b *testing.B) {
b.ReportAllocs()
name := mustNewName("foo.bar.example.com.")
msg := Message{
Header: Header{Response: true, Authoritative: true},
Questions: []Question{
{
Name: "foo.bar.example.com.",
Name: name,
Type: TypeA,
Class: ClassINET,
},
},
Answers: []Resource{
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: name,
Class: ClassINET,
},
&AResource{[4]byte{}},
},
{
ResourceHeader{
Name: name,
Class: ClassINET,
},
&AAAAResource{[16]byte{}},
},
{
ResourceHeader{
Name: name,
Class: ClassINET,
},
&CNAMEResource{name},
},
{
ResourceHeader{
Name: name,
Class: ClassINET,
},
&NSResource{name},
},
},
}
buf, err := msg.Pack()
if err != nil {
b.Fatal("msg.Pack():", err)
}
for i := 0; i < b.N; i++ {
var p Parser
if _, err := p.Start(buf); err != nil {
b.Fatal("p.Start(buf):", err)
}
for {
_, err := p.Question()
if err == ErrSectionDone {
break
}
if err != nil {
b.Fatal("p.Question():", err)
}
}
for {
h, err := p.AnswerHeader()
if err == ErrSectionDone {
break
}
if err != nil {
panic(err)
}
switch h.Type {
case TypeA:
if _, err := p.AResource(); err != nil {
b.Fatal("p.AResource():", err)
}
case TypeAAAA:
if _, err := p.AAAAResource(); err != nil {
b.Fatal("p.AAAAResource():", err)
}
case TypeCNAME:
if _, err := p.CNAMEResource(); err != nil {
b.Fatal("p.CNAMEResource():", err)
}
case TypeNS:
if _, err := p.NSResource(); err != nil {
b.Fatal("p.NSResource():", err)
}
default:
b.Fatalf("unknown type: %T", h)
}
}
}
}
func BenchmarkBuilding(b *testing.B) {
b.ReportAllocs()
name := mustNewName("foo.bar.example.com.")
buf := make([]byte, 0, packStartingCap)
for i := 0; i < b.N; i++ {
var bld Builder
bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true})
if err := bld.StartQuestions(); err != nil {
b.Fatal("bld.StartQuestions():", err)
}
q := Question{
Name: name,
Type: TypeA,
Class: ClassINET,
}
if err := bld.Question(q); err != nil {
b.Fatalf("bld.Question(%+v): %v", q, err)
}
hdr := ResourceHeader{
Name: name,
Class: ClassINET,
}
if err := bld.StartAnswers(); err != nil {
b.Fatal("bld.StartQuestions():", err)
}
ar := AResource{[4]byte{}}
if err := bld.AResource(hdr, ar); err != nil {
b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
}
aaar := AAAAResource{[16]byte{}}
if err := bld.AAAAResource(hdr, aaar); err != nil {
b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
}
cnr := CNAMEResource{name}
if err := bld.CNAMEResource(hdr, cnr); err != nil {
b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
}
nsr := NSResource{name}
if err := bld.NSResource(hdr, nsr); err != nil {
b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
}
if _, err := bld.Finish(); err != nil {
b.Fatal("bld.Finish():", err)
}
}
}
func largeTestMsg() Message {
name := mustNewName("foo.bar.example.com.")
return Message{
Header: Header{Response: true, Authoritative: true},
Questions: []Question{
{
Name: name,
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 1},
},
&AResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
Answers: []Resource{
{
ResourceHeader{
Name: name,
Type: TypeA,
Class: ClassINET,
},
A: [4]byte{127, 0, 0, 2},
&AResource{[4]byte{127, 0, 0, 1}},
},
{
ResourceHeader{
Name: name,
Type: TypeA,
Class: ClassINET,
},
&AResource{[4]byte{127, 0, 0, 2}},
},
{
ResourceHeader{
Name: name,
Type: TypeAAAA,
Class: ClassINET,
},
&AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
},
{
ResourceHeader{
Name: name,
Type: TypeCNAME,
Class: ClassINET,
},
&CNAMEResource{mustNewName("alias.example.com.")},
},
{
ResourceHeader{
Name: name,
Type: TypeSOA,
Class: ClassINET,
},
&SOAResource{
NS: mustNewName("ns1.example.com."),
MBox: mustNewName("mb.example.com."),
Serial: 1,
Refresh: 2,
Retry: 3,
Expire: 4,
MinTTL: 5,
},
},
{
ResourceHeader{
Name: name,
Type: TypePTR,
Class: ClassINET,
},
&PTRResource{mustNewName("ptr.example.com.")},
},
{
ResourceHeader{
Name: name,
Type: TypeMX,
Class: ClassINET,
},
&MXResource{
7,
mustNewName("mx.example.com."),
},
},
{
ResourceHeader{
Name: name,
Type: TypeSRV,
Class: ClassINET,
},
&SRVResource{
8,
9,
11,
mustNewName("srv.example.com."),
},
},
},
Authorities: []Resource{
&NSResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: name,
Type: TypeNS,
Class: ClassINET,
},
NS: "ns1.example.com.",
&NSResource{mustNewName("ns1.example.com.")},
},
&NSResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: name,
Type: TypeNS,
Class: ClassINET,
},
NS: "ns2.example.com.",
&NSResource{mustNewName("ns2.example.com.")},
},
},
Additionals: []Resource{
&TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: name,
Type: TypeTXT,
Class: ClassINET,
},
Txt: "So Long, and Thanks for All the Fish",
&TXTResource{"So Long, and Thanks for All the Fish"},
},
&TXTResource{
ResourceHeader: ResourceHeader{
Name: "foo.bar.example.com.",
{
ResourceHeader{
Name: name,
Type: TypeTXT,
Class: ClassINET,
},
Txt: "Hamster Huey and the Gooey Kablooie",
&TXTResource{"Hamster Huey and the Gooey Kablooie"},
},
},
}

View File

@@ -87,13 +87,16 @@ type goAwayFlowError struct{}
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
// connError represents an HTTP/2 ConnectionError error code, along
// with a string (for debugging) explaining why.
//
// Errors of this type are only returned by the frame parser functions
// and converted into ConnectionError(ErrCodeProtocol).
// and converted into ConnectionError(Code), after stashing away
// the Reason into the Framer's errDetail field, accessible via
// the (*Framer).ErrorDetail method.
type connError struct {
Code ErrCode
Reason string
Code ErrCode // the ConnectionError error code
Reason string // additional reason
}
func (e connError) Error() string {

View File

@@ -52,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
func reqBodyIsNoBody(body io.ReadCloser) bool {
return body == http.NoBody
}
func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only

View File

@@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) {
// validPseudoPath reports whether v is a valid :path pseudo-header
// value. It must be either:
//
// *) a non-empty string starting with '/', but not with with "//",
// *) a non-empty string starting with '/'
// *) the string '*', for OPTIONS requests.
//
// For now this is only used a quick check for deciding when to clean
// up Opaque URLs before sending requests from the Transport.
// See golang.org/issue/16847
//
// We used to enforce that the path also didn't start with "//", but
// Google's GFE accepts such paths and Chrome sends them, so ignore
// that part of the spec. See golang.org/issue/19103.
func validPseudoPath(v string) bool {
return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
return (len(v) > 0 && v[0] == '/') || v == "*"
}

View File

@@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
}
func reqBodyIsNoBody(io.ReadCloser) bool { return false }
func go18httpNoBody() io.ReadCloser { return nil } // for tests only

View File

@@ -2252,6 +2252,7 @@ type responseWriterState struct {
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
sentHeader bool // have we sent the header frame?
handlerDone bool // handler has finished
dirty bool // a Write failed; don't reuse this responseWriterState
sentContentLen int64 // non-zero if handler set a Content-Length header
wroteBytes int64
@@ -2333,6 +2334,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
date: date,
})
if err != nil {
rws.dirty = true
return 0, err
}
if endStream {
@@ -2354,6 +2356,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
if len(p) > 0 || endStream {
// only send a 0 byte DATA frame if we're ending the stream.
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
rws.dirty = true
return 0, err
}
}
@@ -2365,6 +2368,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
trailers: rws.trailers,
endStream: true,
})
if err != nil {
rws.dirty = true
}
return len(p), err
}
return len(p), nil
@@ -2504,7 +2510,7 @@ func cloneHeader(h http.Header) http.Header {
//
// * Handler calls w.Write or w.WriteString ->
// * -> rws.bw (*bufio.Writer) ->
// * (Handler migth call Flush)
// * (Handler might call Flush)
// * -> chunkWriter{rws}
// * -> responseWriterState.writeChunk(p []byte)
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
@@ -2543,10 +2549,19 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
func (w *responseWriter) handlerDone() {
rws := w.rws
dirty := rws.dirty
rws.handlerDone = true
w.Flush()
w.rws = nil
if !dirty {
// Only recycle the pool if all prior Write calls to
// the serverConn goroutine completed successfully. If
// they returned earlier due to resets from the peer
// there might still be write goroutines outstanding
// from the serverConn referencing the rws memory. See
// issue 20704.
responseWriterStatePool.Put(rws)
}
}
// Push errors.

View File

@@ -3685,3 +3685,37 @@ func TestRequestBodyReadCloseRace(t *testing.T) {
<-done
}
}
func TestIssue20704Race(t *testing.T) {
if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
t.Skip("skipping in short mode")
}
const (
itemSize = 1 << 10
itemCount = 100
)
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
for i := 0; i < itemCount; i++ {
_, err := w.Write(make([]byte, itemSize))
if err != nil {
return
}
}
}, optOnlyServer)
defer st.Close()
tr := &Transport{TLSClientConfig: tlsConfigInsecure}
defer tr.CloseIdleConnections()
cl := &http.Client{Transport: tr}
for i := 0; i < 1000; i++ {
resp, err := cl.Get(st.ts.URL)
if err != nil {
t.Fatal(err)
}
// Force a RST stream to the server by closing without
// reading the body:
resp.Body.Close()
}
}

View File

@@ -694,7 +694,7 @@ func checkConnHeaders(req *http.Request) error {
// req.ContentLength, where 0 actually means zero (not unknown) and -1
// means unknown.
func actualContentLength(req *http.Request) int64 {
if req.Body == nil {
if req.Body == nil || reqBodyIsNoBody(req.Body) {
return 0
}
if req.ContentLength != 0 {
@@ -725,8 +725,8 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
}
body := req.Body
hasBody := body != nil
contentLen := actualContentLength(req)
hasBody := contentLen != 0
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
var requestedGzip bool

View File

@@ -417,6 +417,11 @@ func TestActualContentLength(t *testing.T) {
req: &http.Request{Body: panicReader{}, ContentLength: 5},
want: 5,
},
// http.NoBody means 0, not -1.
3: {
req: &http.Request{Body: go18httpNoBody()},
want: 0,
},
}
for i, tt := range tests {
got := actualContentLength(tt.req)
@@ -2529,7 +2534,7 @@ func TestTransportBodyDoubleEndStream(t *testing.T) {
}
}
// golangorg/issue/16847
// golang.org/issue/16847, golang.org/issue/19103
func TestTransportRequestPathPseudo(t *testing.T) {
type result struct {
path string
@@ -2549,9 +2554,9 @@ func TestTransportRequestPathPseudo(t *testing.T) {
},
want: result{path: "/foo"},
},
// I guess we just don't let users request "//foo" as
// a path, since it's illegal to start with two
// slashes....
// In Go 1.7, we accepted paths of "//foo".
// In Go 1.8, we rejected it (issue 16847).
// In Go 1.9, we accepted it again (issue 19103).
1: {
req: &http.Request{
Method: "GET",
@@ -2560,7 +2565,7 @@ func TestTransportRequestPathPseudo(t *testing.T) {
Path: "//foo",
},
},
want: result{err: `invalid request :path "//foo"`},
want: result{path: "//foo"},
},
// Opaque with //$Matching_Hostname/path
@@ -2969,3 +2974,42 @@ func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
}
}
// Issue 18891: make sure Request.Body == NoBody means no DATA frame
// is ever sent, even if empty.
func TestTransportNoBodyMeansNoDATA(t *testing.T) {
ct := newClientTester(t)
unblockClient := make(chan bool)
ct.client = func() error {
req, _ := http.NewRequest("GET", "https://dummy.tld/", go18httpNoBody())
ct.tr.RoundTrip(req)
<-unblockClient
return nil
}
ct.server = func() error {
defer close(unblockClient)
defer ct.cc.(*net.TCPConn).Close()
ct.greet()
for {
f, err := ct.fr.ReadFrame()
if err != nil {
return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
}
switch f := f.(type) {
default:
return fmt.Errorf("Got %T; want HeadersFrame", f)
case *WindowUpdateFrame, *SettingsFrame:
continue
case *HeadersFrame:
if !f.StreamEnded() {
return fmt.Errorf("got headers frame without END_STREAM")
}
return nil
}
}
}
ct.run()
}

View File

@@ -1,27 +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 icmp
import (
"encoding/binary"
"unsafe"
)
var (
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
freebsdVersion uint32
nativeEndian binary.ByteOrder
)
func init() {
i := uint32(1)
b := (*[4]byte)(unsafe.Pointer(&i))
if b[0] == 1 {
nativeEndian = binary.LittleEndian
} else {
nativeEndian = binary.BigEndian
}
}

View File

@@ -9,9 +9,14 @@ import (
"net"
"runtime"
"golang.org/x/net/internal/socket"
"golang.org/x/net/ipv4"
)
// freebsdVersion is set in sys_freebsd.go.
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
var freebsdVersion uint32
// ParseIPv4Header parses b as an IPv4 header of ICMP error message
// invoking packet, which is contained in ICMP error message.
func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
@@ -36,12 +41,12 @@ func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
}
switch runtime.GOOS {
case "darwin":
h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
case "freebsd":
if freebsdVersion >= 1000000 {
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
} else {
h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
}
default:
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))

View File

@@ -11,6 +11,7 @@ import (
"runtime"
"testing"
"golang.org/x/net/internal/socket"
"golang.org/x/net/ipv4"
)
@@ -55,7 +56,7 @@ var ipv4HeaderLittleEndianTest = ipv4HeaderTest{
func TestParseIPv4Header(t *testing.T) {
tt := &ipv4HeaderLittleEndianTest
if nativeEndian != binary.LittleEndian {
if socket.NativeEndian != binary.LittleEndian {
t.Skip("no test for non-little endian machine yet")
}

View File

@@ -175,6 +175,9 @@ func (m ControlMessage) Parse() ([]ControlMessage, error) {
for len(m) >= controlHeaderLen() {
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
l := h.len()
if l <= 0 {
return nil, errors.New("invalid header length")
}
if uint64(l) < uint64(controlHeaderLen()) {
return nil, errors.New("invalid message length")
}

View File

@@ -83,14 +83,14 @@ func (cm *ControlMessage) Parse(b []byte) error {
if lvl != iana.ProtocolIP {
continue
}
switch typ {
case ctlOpts[ctlTTL].name:
switch {
case typ == ctlOpts[ctlTTL].name && l >= ctlOpts[ctlTTL].length:
ctlOpts[ctlTTL].parse(cm, m.Data(l))
case ctlOpts[ctlDst].name:
case typ == ctlOpts[ctlDst].name && l >= ctlOpts[ctlDst].length:
ctlOpts[ctlDst].parse(cm, m.Data(l))
case ctlOpts[ctlInterface].name:
case typ == ctlOpts[ctlInterface].name && l >= ctlOpts[ctlInterface].length:
ctlOpts[ctlInterface].parse(cm, m.Data(l))
case ctlOpts[ctlPacketInfo].name:
case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length:
ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
}
}

21
vendor/golang.org/x/net/ipv4/control_test.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// 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))
}
}

View File

@@ -43,3 +43,21 @@ func netAddrToIP4(a net.Addr) net.IP {
}
return nil
}
func opAddr(a net.Addr) net.Addr {
switch a.(type) {
case *net.TCPAddr:
if a == nil {
return nil
}
case *net.UDPAddr:
if a == nil {
return nil
}
case *net.IPAddr:
if a == nil {
return nil
}
}
return a
}

View File

@@ -69,13 +69,16 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
}
for _, gaddr := range udpMultipleGroupListenerTests {
c1, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
c1, err := net.ListenPacket("udp4", "224.0.0.0:0") // wildcard address with reusable port
if err != nil {
t.Fatal(err)
}
defer c1.Close()
c2, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
_, 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)
}
@@ -131,16 +134,29 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
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", ip.String()+":"+"1024") // unicast address with non-reusable port
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)
}
defer c.Close()
}
p := ipv4.NewPacketConn(c)
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatal(err)

View File

@@ -61,7 +61,7 @@ func (c *packetHandler) writeTo(h *Header, p []byte, cm *ControlMessage) error {
}
m.Addr = dst
if err := c.SendMsg(&m, 0); err != nil {
return &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
return &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Addr: opAddr(dst), Err: err}
}
return nil
}

View File

@@ -53,7 +53,7 @@ func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (n
case *net.IPConn:
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
default:
return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Err: errInvalidConnType}
return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Addr: opAddr(dst), Err: errInvalidConnType}
}
return
}

View File

@@ -61,7 +61,7 @@ func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (in
}
err := c.SendMsg(&m, 0)
if err != nil {
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err}
}
return m.N, err
}

View File

@@ -129,14 +129,14 @@ func (cm *ControlMessage) Parse(b []byte) error {
if lvl != iana.ProtocolIPv6 {
continue
}
switch typ {
case ctlOpts[ctlTrafficClass].name:
switch {
case typ == ctlOpts[ctlTrafficClass].name && l >= ctlOpts[ctlTrafficClass].length:
ctlOpts[ctlTrafficClass].parse(cm, m.Data(l))
case ctlOpts[ctlHopLimit].name:
case typ == ctlOpts[ctlHopLimit].name && l >= ctlOpts[ctlHopLimit].length:
ctlOpts[ctlHopLimit].parse(cm, m.Data(l))
case ctlOpts[ctlPacketInfo].name:
case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length:
ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
case ctlOpts[ctlPathMTU].name:
case typ == ctlOpts[ctlPathMTU].name && l >= ctlOpts[ctlPathMTU].length:
ctlOpts[ctlPathMTU].parse(cm, m.Data(l))
}
}

View File

@@ -17,7 +17,7 @@ func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_2292HOPLIMIT, 4)
if cm != nil {
nativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
}
return m.Next(4)
}

View File

@@ -18,26 +18,26 @@ func marshalTrafficClass(b []byte, cm *ControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_TCLASS, 4)
if cm != nil {
nativeEndian.PutUint32(m.Data(4), uint32(cm.TrafficClass))
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.TrafficClass))
}
return m.Next(4)
}
func parseTrafficClass(cm *ControlMessage, b []byte) {
cm.TrafficClass = int(nativeEndian.Uint32(b[:4]))
cm.TrafficClass = int(socket.NativeEndian.Uint32(b[:4]))
}
func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_HOPLIMIT, 4)
if cm != nil {
nativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
}
return m.Next(4)
}
func parseHopLimit(cm *ControlMessage, b []byte) {
cm.HopLimit = int(nativeEndian.Uint32(b[:4]))
cm.HopLimit = int(socket.NativeEndian.Uint32(b[:4]))
}
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {

21
vendor/golang.org/x/net/ipv6/control_test.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// 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))
}
}

View File

@@ -5,10 +5,8 @@
package ipv6
import (
"encoding/binary"
"errors"
"net"
"unsafe"
)
var (
@@ -17,20 +15,8 @@ var (
errInvalidConnType = errors.New("invalid conn type")
errOpNoSupport = errors.New("operation not supported")
errNoSuchInterface = errors.New("no such interface")
nativeEndian binary.ByteOrder
)
func init() {
i := uint32(1)
b := (*[4]byte)(unsafe.Pointer(&i))
if b[0] == 1 {
nativeEndian = binary.LittleEndian
} else {
nativeEndian = binary.BigEndian
}
}
func boolint(b bool) int {
if b {
return 1
@@ -51,3 +37,21 @@ func netAddrToIP16(a net.Addr) net.IP {
}
return nil
}
func opAddr(a net.Addr) net.Addr {
switch a.(type) {
case *net.TCPAddr:
if a == nil {
return nil
}
case *net.UDPAddr:
if a == nil {
return nil
}
case *net.IPAddr:
if a == nil {
return nil
}
}
return a
}

View File

@@ -5,7 +5,6 @@
package ipv6_test
import (
"fmt"
"net"
"runtime"
"testing"
@@ -70,13 +69,16 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
}
for _, gaddr := range udpMultipleGroupListenerTests {
c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
c1, err := net.ListenPacket("udp6", "[ff02::]:0") // wildcard address with reusable port
if err != nil {
t.Fatal(err)
}
defer c1.Close()
c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
_, 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)
}
@@ -132,16 +134,29 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
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", fmt.Sprintf("[%s%%%s]:1024", ip.String(), ifi.Name)) // unicast address with non-reusable port
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)
}
defer c.Close()
}
p := ipv6.NewPacketConn(c)
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
t.Fatal(err)
@@ -227,7 +242,7 @@ func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
if !ok {
continue
}
c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address
c, err := net.ListenPacket("ip6:ipv6-icmp", ip.String()+"%"+ifi.Name) // unicast address
if err != nil {
t.Fatal(err)
}

View File

@@ -49,7 +49,7 @@ func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (n
case *net.IPConn:
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
default:
return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Err: errInvalidConnType}
return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Addr: opAddr(dst), Err: errInvalidConnType}
}
return
}

View File

@@ -51,7 +51,7 @@ func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (in
}
err := c.SendMsg(&m, 0)
if err != nil {
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err}
}
return m.N, err
}

View File

@@ -216,13 +216,13 @@ var publicSuffixTestCases = []struct {
{"aaa.xn--p1ai", "xn--p1ai"},
{"www.xxx.yyy.xn--p1ai", "xn--p1ai"},
// The .zw rules are:
// *.zw
{"zw", "zw"},
{"www.zw", "www.zw"},
{"zzz.zw", "zzz.zw"},
{"www.zzz.zw", "zzz.zw"},
{"www.xxx.yyy.zzz.zw", "zzz.zw"},
// The .bd rules are:
// *.bd
{"bd", "bd"},
{"www.bd", "www.bd"},
{"zzz.bd", "zzz.bd"},
{"www.zzz.bd", "zzz.bd"},
{"www.xxx.yyy.zzz.bd", "zzz.bd"},
// There are no .nosuchtld rules.
{"nosuchtld", "nosuchtld"},

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -39,9 +39,9 @@ var buckets = []bucket{
}
// RenderEvents renders the HTML page typically served at /debug/events.
// It does not do any auth checking; see AuthRequest for the default auth check
// used by the handler registered on http.DefaultServeMux.
// req may be nil.
// It does not do any auth checking. The request may be nil.
//
// Most users will use the Events handler.
func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
now := time.Now()
data := &struct {

View File

@@ -110,7 +110,18 @@ var AuthRequest = func(req *http.Request) (any, sensitive bool) {
}
func init() {
http.HandleFunc("/debug/requests", func(w http.ResponseWriter, req *http.Request) {
// TODO(jbd): Serve Traces from /debug/traces in the future?
// There is no requirement for a request to be present to have traces.
http.HandleFunc("/debug/requests", Traces)
http.HandleFunc("/debug/events", Events)
}
// Traces responds with traces from the program.
// The package initialization registers it in http.DefaultServeMux
// at /debug/requests.
//
// It performs authorization by running AuthRequest.
func Traces(w http.ResponseWriter, req *http.Request) {
any, sensitive := AuthRequest(req)
if !any {
http.Error(w, "not allowed", http.StatusUnauthorized)
@@ -118,8 +129,14 @@ func init() {
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
Render(w, req, sensitive)
})
http.HandleFunc("/debug/events", func(w http.ResponseWriter, req *http.Request) {
}
// Events responds with a page of events collected by EventLogs.
// The package initialization registers it in http.DefaultServeMux
// at /debug/events.
//
// It performs authorization by running AuthRequest.
func Events(w http.ResponseWriter, req *http.Request) {
any, sensitive := AuthRequest(req)
if !any {
http.Error(w, "not allowed", http.StatusUnauthorized)
@@ -127,13 +144,12 @@ func init() {
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
RenderEvents(w, req, sensitive)
})
}
// Render renders the HTML page typically served at /debug/requests.
// It does not do any auth checking; see AuthRequest for the default auth check
// used by the handler registered on http.DefaultServeMux.
// req may be nil.
// It does not do any auth checking. The request may be nil.
//
// Most users will use the Traces handler.
func Render(w io.Writer, req *http.Request, sensitive bool) {
data := &struct {
Families []string