Unverified Commit 13925a87 authored by Erik Wilson's avatar Erik Wilson Committed by GitHub

Merge pull request #1352 from erikwilson/update-k8s-v1.16.6

Update k8s to v1.16.6
parents 36586100 2381a01b
...@@ -32,31 +32,31 @@ replace ( ...@@ -32,31 +32,31 @@ replace (
github.com/prometheus/client_model => github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 github.com/prometheus/client_model => github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910
github.com/prometheus/common => github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 github.com/prometheus/common => github.com/prometheus/common v0.0.0-20181126121408-4724e9255275
github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a
k8s.io/api => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.3-k3s.2 k8s.io/api => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.6-k3s1
k8s.io/apiextensions-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.3-k3s.2 k8s.io/apiextensions-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.6-k3s1
k8s.io/apimachinery => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.3-k3s.2 k8s.io/apimachinery => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.6-k3s1
k8s.io/apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiserver v1.16.3-k3s.2 k8s.io/apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiserver v1.16.6-k3s1
k8s.io/cli-runtime => github.com/rancher/kubernetes/staging/src/k8s.io/cli-runtime v1.16.3-k3s.2 k8s.io/cli-runtime => github.com/rancher/kubernetes/staging/src/k8s.io/cli-runtime v1.16.6-k3s1
k8s.io/client-go => github.com/rancher/kubernetes/staging/src/k8s.io/client-go v1.16.3-k3s.2 k8s.io/client-go => github.com/rancher/kubernetes/staging/src/k8s.io/client-go v1.16.6-k3s1
k8s.io/cloud-provider => github.com/rancher/kubernetes/staging/src/k8s.io/cloud-provider v1.16.3-k3s.2 k8s.io/cloud-provider => github.com/rancher/kubernetes/staging/src/k8s.io/cloud-provider v1.16.6-k3s1
k8s.io/cluster-bootstrap => github.com/rancher/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.16.3-k3s.2 k8s.io/cluster-bootstrap => github.com/rancher/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.16.6-k3s1
k8s.io/code-generator => github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.3-k3s.2 k8s.io/code-generator => github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.6-k3s1
k8s.io/component-base => github.com/rancher/kubernetes/staging/src/k8s.io/component-base v1.16.3-k3s.2 k8s.io/component-base => github.com/rancher/kubernetes/staging/src/k8s.io/component-base v1.16.6-k3s1
k8s.io/cri-api => github.com/rancher/kubernetes/staging/src/k8s.io/cri-api v1.16.3-k3s.2 k8s.io/cri-api => github.com/rancher/kubernetes/staging/src/k8s.io/cri-api v1.16.6-k3s1
k8s.io/csi-translation-lib => github.com/rancher/kubernetes/staging/src/k8s.io/csi-translation-lib v1.16.3-k3s.2 k8s.io/csi-translation-lib => github.com/rancher/kubernetes/staging/src/k8s.io/csi-translation-lib v1.16.6-k3s1
k8s.io/kube-aggregator => github.com/rancher/kubernetes/staging/src/k8s.io/kube-aggregator v1.16.3-k3s.2 k8s.io/kube-aggregator => github.com/rancher/kubernetes/staging/src/k8s.io/kube-aggregator v1.16.6-k3s1
k8s.io/kube-controller-manager => github.com/rancher/kubernetes/staging/src/k8s.io/kube-controller-manager v1.16.3-k3s.2 k8s.io/kube-controller-manager => github.com/rancher/kubernetes/staging/src/k8s.io/kube-controller-manager v1.16.6-k3s1
k8s.io/kube-proxy => github.com/rancher/kubernetes/staging/src/k8s.io/kube-proxy v1.16.3-k3s.2 k8s.io/kube-proxy => github.com/rancher/kubernetes/staging/src/k8s.io/kube-proxy v1.16.6-k3s1
k8s.io/kube-scheduler => github.com/rancher/kubernetes/staging/src/k8s.io/kube-scheduler v1.16.3-k3s.2 k8s.io/kube-scheduler => github.com/rancher/kubernetes/staging/src/k8s.io/kube-scheduler v1.16.6-k3s1
k8s.io/kubectl => github.com/rancher/kubernetes/staging/src/k8s.io/kubectl v1.16.3-k3s.2 k8s.io/kubectl => github.com/rancher/kubernetes/staging/src/k8s.io/kubectl v1.16.6-k3s1
k8s.io/kubelet => github.com/rancher/kubernetes/staging/src/k8s.io/kubelet v1.16.3-k3s.2 k8s.io/kubelet => github.com/rancher/kubernetes/staging/src/k8s.io/kubelet v1.16.6-k3s1
k8s.io/kubernetes => github.com/rancher/kubernetes v1.16.3-k3s.2 k8s.io/kubernetes => github.com/rancher/kubernetes v1.16.6-k3s1
k8s.io/legacy-cloud-providers => github.com/rancher/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.16.3-k3s.2 k8s.io/legacy-cloud-providers => github.com/rancher/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.16.6-k3s1
k8s.io/metrics => github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.3-k3s.2 k8s.io/metrics => github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.6-k3s1
k8s.io/node-api => github.com/rancher/kubernetes/staging/src/k8s.io/node-api v1.16.3-k3s.2 k8s.io/node-api => github.com/rancher/kubernetes/staging/src/k8s.io/node-api v1.16.6-k3s1
k8s.io/sample-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/sample-apiserver v1.16.3-k3s.2 k8s.io/sample-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/sample-apiserver v1.16.6-k3s1
k8s.io/sample-cli-plugin => github.com/rancher/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.16.3-k3s.2 k8s.io/sample-cli-plugin => github.com/rancher/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.16.6-k3s1
k8s.io/sample-controller => github.com/rancher/kubernetes/staging/src/k8s.io/sample-controller v1.16.3-k3s.2 k8s.io/sample-controller => github.com/rancher/kubernetes/staging/src/k8s.io/sample-controller v1.16.6-k3s1
mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34 mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
) )
...@@ -108,12 +108,12 @@ require ( ...@@ -108,12 +108,12 @@ require (
github.com/rancher/wrangler-api v0.2.0 github.com/rancher/wrangler-api v0.2.0
github.com/rootless-containers/rootlesskit v0.6.0 github.com/rootless-containers/rootlesskit v0.6.0
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.4.2
github.com/spf13/pflag v1.0.3 github.com/spf13/pflag v1.0.5
github.com/tchap/go-patricia v2.3.0+incompatible // indirect github.com/tchap/go-patricia v2.3.0+incompatible // indirect
github.com/theckman/go-flock v0.7.1 // indirect github.com/theckman/go-flock v0.7.1 // indirect
github.com/urfave/cli v1.21.0 github.com/urfave/cli v1.21.0
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
google.golang.org/grpc v1.23.0 google.golang.org/grpc v1.23.0
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
...@@ -126,7 +126,7 @@ require ( ...@@ -126,7 +126,7 @@ require (
k8s.io/cloud-provider v0.0.0 k8s.io/cloud-provider v0.0.0
k8s.io/component-base v0.0.0 k8s.io/component-base v0.0.0
k8s.io/cri-api v0.0.0 k8s.io/cri-api v0.0.0
k8s.io/klog v0.4.0 k8s.io/klog v1.0.0
k8s.io/kubernetes v1.16.0 k8s.io/kubernetes v1.16.0
k8s.io/utils v0.0.0-20190829053155-3a4a5477acf8 // indirect k8s.io/utils v0.0.0-20190829053155-3a4a5477acf8 // indirect
) )
module github.com/go-openapi/jsonpointer module github.com/go-openapi/jsonpointer
require ( require (
github.com/go-openapi/swag v0.19.2 github.com/go-openapi/swag v0.19.5
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
) )
go 1.13
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
...@@ -10,6 +10,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= ...@@ -10,6 +10,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
......
...@@ -135,7 +135,7 @@ func getSingleImpl(node interface{}, decodedToken string, nameProvider *swag.Nam ...@@ -135,7 +135,7 @@ func getSingleImpl(node interface{}, decodedToken string, nameProvider *swag.Nam
kv := reflect.ValueOf(decodedToken) kv := reflect.ValueOf(decodedToken)
mv := rValue.MapIndex(kv) mv := rValue.MapIndex(kv)
if mv.IsValid() && !swag.IsZero(mv) { if mv.IsValid() {
return mv.Interface(), kind, nil return mv.Interface(), kind, nil
} }
return nil, kind, fmt.Errorf("object has no key %q", decodedToken) return nil, kind, fmt.Errorf("object has no key %q", decodedToken)
......
secrets.yml secrets.yml
vendor vendor
Godeps Godeps
.idea
...@@ -39,11 +39,12 @@ func IsFloat64AJSONInteger(f float64) bool { ...@@ -39,11 +39,12 @@ func IsFloat64AJSONInteger(f float64) bool {
diff := math.Abs(f - g) diff := math.Abs(f - g)
// more info: https://floating-point-gui.de/errors/comparison/#look-out-for-edge-cases // more info: https://floating-point-gui.de/errors/comparison/#look-out-for-edge-cases
if f == g { // best case switch {
case f == g: // best case
return true return true
} else if f == float64(int64(f)) || f == float64(uint64(f)) { // optimistic case case f == float64(int64(f)) || f == float64(uint64(f)): // optimistic case
return true return true
} else if f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64 { // very close to 0 values case f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64: // very close to 0 values
return diff < (epsilon * math.SmallestNonzeroFloat64) return diff < (epsilon * math.SmallestNonzeroFloat64)
} }
// check the relative error // check the relative error
......
...@@ -99,7 +99,7 @@ func ConcatJSON(blobs ...[]byte) []byte { ...@@ -99,7 +99,7 @@ func ConcatJSON(blobs ...[]byte) []byte {
last := len(blobs) - 1 last := len(blobs) - 1
for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) { for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
// strips trailing null objects // strips trailing null objects
last = last - 1 last--
if last < 0 { if last < 0 {
// there was nothing but "null"s or nil... // there was nothing but "null"s or nil...
return nil return nil
......
...@@ -28,6 +28,14 @@ var initialisms []string ...@@ -28,6 +28,14 @@ var initialisms []string
var isInitialism func(string) bool var isInitialism func(string) bool
// GoNamePrefixFunc sets an optional rule to prefix go names
// which do not start with a letter.
//
// e.g. to help converting "123" into "{prefix}123"
//
// The default is to prefix with "X"
var GoNamePrefixFunc func(string) string
func init() { func init() {
// Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769 // Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769
var configuredInitialisms = map[string]bool{ var configuredInitialisms = map[string]bool{
...@@ -288,8 +296,17 @@ func ToGoName(name string) string { ...@@ -288,8 +296,17 @@ func ToGoName(name string) string {
} }
if len(result) > 0 { if len(result) > 0 {
if !unicode.IsUpper([]rune(result)[0]) { // Only prefix with X when the first character isn't an ascii letter
result = "X" + result first := []rune(result)[0]
if !unicode.IsLetter(first) || (first > unicode.MaxASCII && !unicode.IsUpper(first)) {
if GoNamePrefixFunc == nil {
return "X" + result
}
result = GoNamePrefixFunc(name) + result
}
first = []rune(result)[0]
if unicode.IsLetter(first) && !unicode.IsUpper(first) {
result = string(append([]rune{unicode.ToUpper(first)}, []rune(result)[1:]...))
} }
} }
......
...@@ -143,19 +143,43 @@ func (s *JSONMapItem) UnmarshalEasyJSON(in *jlexer.Lexer) { ...@@ -143,19 +143,43 @@ func (s *JSONMapItem) UnmarshalEasyJSON(in *jlexer.Lexer) {
} }
func transformData(input interface{}) (out interface{}, err error) { func transformData(input interface{}) (out interface{}, err error) {
format := func(t interface{}) (string, error) {
switch k := t.(type) {
case string:
return k, nil
case uint:
return strconv.FormatUint(uint64(k), 10), nil
case uint8:
return strconv.FormatUint(uint64(k), 10), nil
case uint16:
return strconv.FormatUint(uint64(k), 10), nil
case uint32:
return strconv.FormatUint(uint64(k), 10), nil
case uint64:
return strconv.FormatUint(k, 10), nil
case int:
return strconv.Itoa(k), nil
case int8:
return strconv.FormatInt(int64(k), 10), nil
case int16:
return strconv.FormatInt(int64(k), 10), nil
case int32:
return strconv.FormatInt(int64(k), 10), nil
case int64:
return strconv.FormatInt(k, 10), nil
default:
return "", fmt.Errorf("unexpected map key type, got: %T", k)
}
}
switch in := input.(type) { switch in := input.(type) {
case yaml.MapSlice: case yaml.MapSlice:
o := make(JSONMapSlice, len(in)) o := make(JSONMapSlice, len(in))
for i, mi := range in { for i, mi := range in {
var nmi JSONMapItem var nmi JSONMapItem
switch k := mi.Key.(type) { if nmi.Key, err = format(mi.Key); err != nil {
case string: return nil, err
nmi.Key = k
case int:
nmi.Key = strconv.Itoa(k)
default:
return nil, fmt.Errorf("types don't match expect map key string or int got: %T", mi.Key)
} }
v, ert := transformData(mi.Value) v, ert := transformData(mi.Value)
...@@ -170,13 +194,8 @@ func transformData(input interface{}) (out interface{}, err error) { ...@@ -170,13 +194,8 @@ func transformData(input interface{}) (out interface{}, err error) {
o := make(JSONMapSlice, 0, len(in)) o := make(JSONMapSlice, 0, len(in))
for ke, va := range in { for ke, va := range in {
var nmi JSONMapItem var nmi JSONMapItem
switch k := ke.(type) { if nmi.Key, err = format(ke); err != nil {
case string: return nil, err
nmi.Key = k
case int:
nmi.Key = strconv.Itoa(k)
default:
return nil, fmt.Errorf("types don't match expect map key string or int got: %T", ke)
} }
v, ert := transformData(va) v, ert := transformData(va)
......
...@@ -4,6 +4,7 @@ go: ...@@ -4,6 +4,7 @@ go:
- 1.6.x - 1.6.x
- 1.7.x - 1.7.x
- 1.8.x - 1.8.x
- 1.9.x
- master - master
matrix: matrix:
allow_failures: allow_failures:
......
...@@ -3,7 +3,7 @@ httpcache ...@@ -3,7 +3,7 @@ httpcache
[![Build Status](https://travis-ci.org/gregjones/httpcache.svg?branch=master)](https://travis-ci.org/gregjones/httpcache) [![GoDoc](https://godoc.org/github.com/gregjones/httpcache?status.svg)](https://godoc.org/github.com/gregjones/httpcache) [![Build Status](https://travis-ci.org/gregjones/httpcache.svg?branch=master)](https://travis-ci.org/gregjones/httpcache) [![GoDoc](https://godoc.org/github.com/gregjones/httpcache?status.svg)](https://godoc.org/github.com/gregjones/httpcache)
Package httpcache provides a http.RoundTripper implementation that works as a mostly RFC-compliant cache for http responses. Package httpcache provides a http.RoundTripper implementation that works as a mostly [RFC 7234](https://tools.ietf.org/html/rfc7234) compliant cache for http responses.
It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy). It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy).
...@@ -17,6 +17,7 @@ Cache Backends ...@@ -17,6 +17,7 @@ Cache Backends
- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb). - [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb).
- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries. - [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries.
- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache. - [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache.
- [`github.com/birkelund/boltdbcache`](https://github.com/birkelund/boltdbcache) provides a BoltDB implementation (based on the [bbolt](https://github.com/coreos/bbolt) fork).
License License
------- -------
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"errors" "errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
...@@ -41,7 +40,11 @@ type Cache interface { ...@@ -41,7 +40,11 @@ type Cache interface {
// cacheKey returns the cache key for req. // cacheKey returns the cache key for req.
func cacheKey(req *http.Request) string { func cacheKey(req *http.Request) string {
return req.URL.String() if req.Method == http.MethodGet {
return req.URL.String()
} else {
return req.Method + " " + req.URL.String()
}
} }
// CachedResponse returns the cached http.Response for req if present, and nil // CachedResponse returns the cached http.Response for req if present, and nil
...@@ -189,16 +192,11 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error ...@@ -189,16 +192,11 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error
for _, header := range endToEndHeaders { for _, header := range endToEndHeaders {
cachedResp.Header[header] = resp.Header[header] cachedResp.Header[header] = resp.Header[header]
} }
cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK))
cachedResp.StatusCode = http.StatusOK
resp = cachedResp resp = cachedResp
} else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) && } else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) &&
req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) { req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) {
// In case of transport failure and stale-if-error activated, returns cached content // In case of transport failure and stale-if-error activated, returns cached content
// when available // when available
cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK))
cachedResp.StatusCode = http.StatusOK
return cachedResp, nil return cachedResp, nil
} else { } else {
if err != nil || resp.StatusCode != http.StatusOK { if err != nil || resp.StatusCode != http.StatusOK {
......
...@@ -3,8 +3,9 @@ sudo: false ...@@ -3,8 +3,9 @@ sudo: false
language: go language: go
go: go:
- 1.7.3 - 1.9.x
- 1.8.1 - 1.10.x
- 1.11.x
- tip - tip
matrix: matrix:
...@@ -12,7 +13,7 @@ matrix: ...@@ -12,7 +13,7 @@ matrix:
- go: tip - go: tip
install: install:
- go get github.com/golang/lint/golint - go get golang.org/x/lint/golint
- export PATH=$GOPATH/bin:$PATH - export PATH=$GOPATH/bin:$PATH
- go install ./... - go install ./...
......
...@@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip) ...@@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar) fmt.Println("flagvar has value ", flagvar)
``` ```
There are helpers function to get values later if you have the FlagSet but There are helper functions available to get the value stored in a Flag if you have a FlagSet but find
it was difficult to keep up with all of the flag pointers in your code. it difficult to keep up with all of the pointers in your code.
If you have a pflag.FlagSet with a flag called 'flagname' of type int you If you have a pflag.FlagSet with a flag called 'flagname' of type int you
can use GetInt() to get the int value. But notice that 'flagname' must exist can use GetInt() to get the int value. But notice that 'flagname' must exist
and it must be an int. GetString("flagname") will fail. and it must be an int. GetString("flagname") will fail.
......
...@@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string { ...@@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string {
return "[" + out + "]" return "[" + out + "]"
} }
func (s *boolSliceValue) fromString(val string) (bool, error) {
return strconv.ParseBool(val)
}
func (s *boolSliceValue) toString(val bool) string {
return strconv.FormatBool(val)
}
func (s *boolSliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *boolSliceValue) Replace(val []string) error {
out := make([]bool, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *boolSliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func boolSliceConv(val string) (interface{}, error) { func boolSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry // Empty string would cause a slice with one (empty) entry
......
...@@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) { ...@@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) {
// CountVar defines a count flag with specified name, default value, and usage string. // CountVar defines a count flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag. // The argument p points to an int variable in which to store the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line // A count flag will add 1 to its value every time it is found on the command line
func (f *FlagSet) CountVar(p *int, name string, usage string) { func (f *FlagSet) CountVar(p *int, name string, usage string) {
f.CountVarP(p, name, "", usage) f.CountVarP(p, name, "", usage)
} }
...@@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) { ...@@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) {
// Count defines a count flag with specified name, default value, and usage string. // Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag. // The return value is the address of an int variable that stores the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line // A count flag will add 1 to its value every time it is found on the command line
func (f *FlagSet) Count(name string, usage string) *int { func (f *FlagSet) Count(name string, usage string) *int {
p := new(int) p := new(int)
f.CountVarP(p, name, "", usage) f.CountVarP(p, name, "", usage)
......
...@@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string { ...@@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string {
return "[" + strings.Join(out, ",") + "]" return "[" + strings.Join(out, ",") + "]"
} }
func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
return time.ParseDuration(val)
}
func (s *durationSliceValue) toString(val time.Duration) string {
return fmt.Sprintf("%s", val)
}
func (s *durationSliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *durationSliceValue) Replace(val []string) error {
out := make([]time.Duration, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *durationSliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func durationSliceConv(val string) (interface{}, error) { func durationSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry // Empty string would cause a slice with one (empty) entry
......
...@@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending ...@@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending
var ip = flag.IntP("flagname", "f", 1234, "help message") var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool var flagvar bool
func init() { func init() {
flag.BoolVarP("boolname", "b", true, "help message") flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
} }
flag.VarP(&flagVar, "varname", "v", 1234, "help message") flag.VarP(&flagval, "varname", "v", "help message")
Shorthand letters can be used with single dashes on the command line. Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags. Boolean shorthand flags can be combined with other shorthand flags.
...@@ -190,6 +190,18 @@ type Value interface { ...@@ -190,6 +190,18 @@ type Value interface {
Type() string Type() string
} }
// SliceValue is a secondary interface to all flags which hold a list
// of values. This allows full control over the value of list flags,
// and avoids complicated marshalling and unmarshalling to csv.
type SliceValue interface {
// Append adds the specified value to the end of the flag value list.
Append(string) error
// Replace will fully overwrite any data currently in the flag value list.
Replace([]string) error
// GetSlice returns the flag value list as an array of strings.
GetSlice() []string
}
// sortFlags returns the flags as a slice in lexicographical sorted order. // sortFlags returns the flags as a slice in lexicographical sorted order.
func sortFlags(flags map[NormalizedName]*Flag) []*Flag { func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
list := make(sort.StringSlice, len(flags)) list := make(sort.StringSlice, len(flags))
......
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- float32Slice Value
type float32SliceValue struct {
value *[]float32
changed bool
}
func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue {
isv := new(float32SliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *float32SliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]float32, len(ss))
for i, d := range ss {
var err error
var temp64 float64
temp64, err = strconv.ParseFloat(d, 32)
if err != nil {
return err
}
out[i] = float32(temp64)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *float32SliceValue) Type() string {
return "float32Slice"
}
func (s *float32SliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%f", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func (s *float32SliceValue) fromString(val string) (float32, error) {
t64, err := strconv.ParseFloat(val, 32)
if err != nil {
return 0, err
}
return float32(t64), nil
}
func (s *float32SliceValue) toString(val float32) string {
return fmt.Sprintf("%f", val)
}
func (s *float32SliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *float32SliceValue) Replace(val []string) error {
out := make([]float32, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *float32SliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func float32SliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []float32{}, nil
}
ss := strings.Split(val, ",")
out := make([]float32, len(ss))
for i, d := range ss {
var err error
var temp64 float64
temp64, err = strconv.ParseFloat(d, 32)
if err != nil {
return nil, err
}
out[i] = float32(temp64)
}
return out, nil
}
// GetFloat32Slice return the []float32 value of a flag with the given name
func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) {
val, err := f.getFlagType(name, "float32Slice", float32SliceConv)
if err != nil {
return []float32{}, err
}
return val.([]float32), nil
}
// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string.
// The argument p points to a []float32 variable in which to store the value of the flag.
func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
f.VarP(newFloat32SliceValue(value, p), name, "", usage)
}
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
}
// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string.
// The argument p points to a float32[] variable in which to store the value of the flag.
func Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage)
}
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
}
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
// The return value is the address of a []float32 variable that stores the value of the flag.
func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 {
p := []float32{}
f.Float32SliceVarP(&p, name, "", value, usage)
return &p
}
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
p := []float32{}
f.Float32SliceVarP(&p, name, shorthand, value, usage)
return &p
}
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
// The return value is the address of a []float32 variable that stores the value of the flag.
func Float32Slice(name string, value []float32, usage string) *[]float32 {
return CommandLine.Float32SliceP(name, "", value, usage)
}
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
return CommandLine.Float32SliceP(name, shorthand, value, usage)
}
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- float64Slice Value
type float64SliceValue struct {
value *[]float64
changed bool
}
func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue {
isv := new(float64SliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *float64SliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]float64, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.ParseFloat(d, 64)
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *float64SliceValue) Type() string {
return "float64Slice"
}
func (s *float64SliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%f", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func (s *float64SliceValue) fromString(val string) (float64, error) {
return strconv.ParseFloat(val, 64)
}
func (s *float64SliceValue) toString(val float64) string {
return fmt.Sprintf("%f", val)
}
func (s *float64SliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *float64SliceValue) Replace(val []string) error {
out := make([]float64, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *float64SliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func float64SliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []float64{}, nil
}
ss := strings.Split(val, ",")
out := make([]float64, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.ParseFloat(d, 64)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetFloat64Slice return the []float64 value of a flag with the given name
func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) {
val, err := f.getFlagType(name, "float64Slice", float64SliceConv)
if err != nil {
return []float64{}, err
}
return val.([]float64), nil
}
// Float64SliceVar defines a float64Slice flag with specified name, default value, and usage string.
// The argument p points to a []float64 variable in which to store the value of the flag.
func (f *FlagSet) Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
f.VarP(newFloat64SliceValue(value, p), name, "", usage)
}
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
}
// Float64SliceVar defines a float64[] flag with specified name, default value, and usage string.
// The argument p points to a float64[] variable in which to store the value of the flag.
func Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage)
}
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
}
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
// The return value is the address of a []float64 variable that stores the value of the flag.
func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 {
p := []float64{}
f.Float64SliceVarP(&p, name, "", value, usage)
return &p
}
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
p := []float64{}
f.Float64SliceVarP(&p, name, shorthand, value, usage)
return &p
}
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
// The return value is the address of a []float64 variable that stores the value of the flag.
func Float64Slice(name string, value []float64, usage string) *[]float64 {
return CommandLine.Float64SliceP(name, "", value, usage)
}
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
return CommandLine.Float64SliceP(name, shorthand, value, usage)
}
module github.com/spf13/pflag
go 1.12
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- int32Slice Value
type int32SliceValue struct {
value *[]int32
changed bool
}
func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue {
isv := new(int32SliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *int32SliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]int32, len(ss))
for i, d := range ss {
var err error
var temp64 int64
temp64, err = strconv.ParseInt(d, 0, 32)
if err != nil {
return err
}
out[i] = int32(temp64)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *int32SliceValue) Type() string {
return "int32Slice"
}
func (s *int32SliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func (s *int32SliceValue) fromString(val string) (int32, error) {
t64, err := strconv.ParseInt(val, 0, 32)
if err != nil {
return 0, err
}
return int32(t64), nil
}
func (s *int32SliceValue) toString(val int32) string {
return fmt.Sprintf("%d", val)
}
func (s *int32SliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *int32SliceValue) Replace(val []string) error {
out := make([]int32, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *int32SliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func int32SliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []int32{}, nil
}
ss := strings.Split(val, ",")
out := make([]int32, len(ss))
for i, d := range ss {
var err error
var temp64 int64
temp64, err = strconv.ParseInt(d, 0, 32)
if err != nil {
return nil, err
}
out[i] = int32(temp64)
}
return out, nil
}
// GetInt32Slice return the []int32 value of a flag with the given name
func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) {
val, err := f.getFlagType(name, "int32Slice", int32SliceConv)
if err != nil {
return []int32{}, err
}
return val.([]int32), nil
}
// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string.
// The argument p points to a []int32 variable in which to store the value of the flag.
func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
f.VarP(newInt32SliceValue(value, p), name, "", usage)
}
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
f.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
}
// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string.
// The argument p points to a int32[] variable in which to store the value of the flag.
func Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage)
}
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
}
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
// The return value is the address of a []int32 variable that stores the value of the flag.
func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 {
p := []int32{}
f.Int32SliceVarP(&p, name, "", value, usage)
return &p
}
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
p := []int32{}
f.Int32SliceVarP(&p, name, shorthand, value, usage)
return &p
}
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
// The return value is the address of a []int32 variable that stores the value of the flag.
func Int32Slice(name string, value []int32, usage string) *[]int32 {
return CommandLine.Int32SliceP(name, "", value, usage)
}
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
return CommandLine.Int32SliceP(name, shorthand, value, usage)
}
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- int64Slice Value
type int64SliceValue struct {
value *[]int64
changed bool
}
func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue {
isv := new(int64SliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *int64SliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]int64, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.ParseInt(d, 0, 64)
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *int64SliceValue) Type() string {
return "int64Slice"
}
func (s *int64SliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func (s *int64SliceValue) fromString(val string) (int64, error) {
return strconv.ParseInt(val, 0, 64)
}
func (s *int64SliceValue) toString(val int64) string {
return fmt.Sprintf("%d", val)
}
func (s *int64SliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *int64SliceValue) Replace(val []string) error {
out := make([]int64, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *int64SliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func int64SliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []int64{}, nil
}
ss := strings.Split(val, ",")
out := make([]int64, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.ParseInt(d, 0, 64)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetInt64Slice return the []int64 value of a flag with the given name
func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) {
val, err := f.getFlagType(name, "int64Slice", int64SliceConv)
if err != nil {
return []int64{}, err
}
return val.([]int64), nil
}
// Int64SliceVar defines a int64Slice flag with specified name, default value, and usage string.
// The argument p points to a []int64 variable in which to store the value of the flag.
func (f *FlagSet) Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
f.VarP(newInt64SliceValue(value, p), name, "", usage)
}
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
f.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
}
// Int64SliceVar defines a int64[] flag with specified name, default value, and usage string.
// The argument p points to a int64[] variable in which to store the value of the flag.
func Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage)
}
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
}
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
// The return value is the address of a []int64 variable that stores the value of the flag.
func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 {
p := []int64{}
f.Int64SliceVarP(&p, name, "", value, usage)
return &p
}
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
p := []int64{}
f.Int64SliceVarP(&p, name, shorthand, value, usage)
return &p
}
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
// The return value is the address of a []int64 variable that stores the value of the flag.
func Int64Slice(name string, value []int64, usage string) *[]int64 {
return CommandLine.Int64SliceP(name, "", value, usage)
}
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
return CommandLine.Int64SliceP(name, shorthand, value, usage)
}
...@@ -51,6 +51,36 @@ func (s *intSliceValue) String() string { ...@@ -51,6 +51,36 @@ func (s *intSliceValue) String() string {
return "[" + strings.Join(out, ",") + "]" return "[" + strings.Join(out, ",") + "]"
} }
func (s *intSliceValue) Append(val string) error {
i, err := strconv.Atoi(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *intSliceValue) Replace(val []string) error {
out := make([]int, len(val))
for i, d := range val {
var err error
out[i], err = strconv.Atoi(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *intSliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = strconv.Itoa(d)
}
return out
}
func intSliceConv(val string) (interface{}, error) { func intSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry // Empty string would cause a slice with one (empty) entry
......
...@@ -72,9 +72,47 @@ func (s *ipSliceValue) String() string { ...@@ -72,9 +72,47 @@ func (s *ipSliceValue) String() string {
return "[" + out + "]" return "[" + out + "]"
} }
func (s *ipSliceValue) fromString(val string) (net.IP, error) {
return net.ParseIP(strings.TrimSpace(val)), nil
}
func (s *ipSliceValue) toString(val net.IP) string {
return val.String()
}
func (s *ipSliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *ipSliceValue) Replace(val []string) error {
out := make([]net.IP, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *ipSliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func ipSliceConv(val string) (interface{}, error) { func ipSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// Emtpy string would cause a slice with one (empty) entry // Empty string would cause a slice with one (empty) entry
if len(val) == 0 { if len(val) == 0 {
return []net.IP{}, nil return []net.IP{}, nil
} }
......
...@@ -23,6 +23,32 @@ func (s *stringArrayValue) Set(val string) error { ...@@ -23,6 +23,32 @@ func (s *stringArrayValue) Set(val string) error {
return nil return nil
} }
func (s *stringArrayValue) Append(val string) error {
*s.value = append(*s.value, val)
return nil
}
func (s *stringArrayValue) Replace(val []string) error {
out := make([]string, len(val))
for i, d := range val {
var err error
out[i] = d
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *stringArrayValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = d
}
return out
}
func (s *stringArrayValue) Type() string { func (s *stringArrayValue) Type() string {
return "stringArray" return "stringArray"
} }
......
...@@ -62,6 +62,20 @@ func (s *stringSliceValue) String() string { ...@@ -62,6 +62,20 @@ func (s *stringSliceValue) String() string {
return "[" + str + "]" return "[" + str + "]"
} }
func (s *stringSliceValue) Append(val string) error {
*s.value = append(*s.value, val)
return nil
}
func (s *stringSliceValue) Replace(val []string) error {
*s.value = val
return nil
}
func (s *stringSliceValue) GetSlice() []string {
return *s.value
}
func stringSliceConv(sval string) (interface{}, error) { func stringSliceConv(sval string) (interface{}, error) {
sval = sval[1 : len(sval)-1] sval = sval[1 : len(sval)-1]
// An empty string would cause a slice with one (empty) string // An empty string would cause a slice with one (empty) string
...@@ -84,7 +98,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) { ...@@ -84,7 +98,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
// The argument p points to a []string variable in which to store the value of the flag. // The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example: // For example:
// --ss="v1,v2" -ss="v3" // --ss="v1,v2" --ss="v3"
// will result in // will result in
// []string{"v1", "v2", "v3"} // []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
...@@ -100,7 +114,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s ...@@ -100,7 +114,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
// The argument p points to a []string variable in which to store the value of the flag. // The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example: // For example:
// --ss="v1,v2" -ss="v3" // --ss="v1,v2" --ss="v3"
// will result in // will result in
// []string{"v1", "v2", "v3"} // []string{"v1", "v2", "v3"}
func StringSliceVar(p *[]string, name string, value []string, usage string) { func StringSliceVar(p *[]string, name string, value []string, usage string) {
...@@ -116,7 +130,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage ...@@ -116,7 +130,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
// The return value is the address of a []string variable that stores the value of the flag. // The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example: // For example:
// --ss="v1,v2" -ss="v3" // --ss="v1,v2" --ss="v3"
// will result in // will result in
// []string{"v1", "v2", "v3"} // []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
...@@ -136,7 +150,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str ...@@ -136,7 +150,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
// The return value is the address of a []string variable that stores the value of the flag. // The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example: // For example:
// --ss="v1,v2" -ss="v3" // --ss="v1,v2" --ss="v3"
// will result in // will result in
// []string{"v1", "v2", "v3"} // []string{"v1", "v2", "v3"}
func StringSlice(name string, value []string, usage string) *[]string { func StringSlice(name string, value []string, usage string) *[]string {
......
package pflag
import (
"bytes"
"fmt"
"strconv"
"strings"
)
// -- stringToInt64 Value
type stringToInt64Value struct {
value *map[string]int64
changed bool
}
func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value {
ssv := new(stringToInt64Value)
ssv.value = p
*ssv.value = val
return ssv
}
// Format: a=1,b=2
func (s *stringToInt64Value) Set(val string) error {
ss := strings.Split(val, ",")
out := make(map[string]int64, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return fmt.Errorf("%s must be formatted as key=value", pair)
}
var err error
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
for k, v := range out {
(*s.value)[k] = v
}
}
s.changed = true
return nil
}
func (s *stringToInt64Value) Type() string {
return "stringToInt64"
}
func (s *stringToInt64Value) String() string {
var buf bytes.Buffer
i := 0
for k, v := range *s.value {
if i > 0 {
buf.WriteRune(',')
}
buf.WriteString(k)
buf.WriteRune('=')
buf.WriteString(strconv.FormatInt(v, 10))
i++
}
return "[" + buf.String() + "]"
}
func stringToInt64Conv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
return map[string]int64{}, nil
}
ss := strings.Split(val, ",")
out := make(map[string]int64, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
}
var err error
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetStringToInt64 return the map[string]int64 value of a flag with the given name
func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) {
val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv)
if err != nil {
return map[string]int64{}, err
}
return val.(map[string]int64), nil
}
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
f.VarP(newStringToInt64Value(value, p), name, "", usage)
}
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
f.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
}
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
// The argument p point64s to a map[string]int64 variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage)
}
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
}
// StringToInt64 defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
p := map[string]int64{}
f.StringToInt64VarP(&p, name, "", value, usage)
return &p
}
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
p := map[string]int64{}
f.StringToInt64VarP(&p, name, shorthand, value, usage)
return &p
}
// StringToInt64 defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
return CommandLine.StringToInt64P(name, "", value, usage)
}
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
return CommandLine.StringToInt64P(name, shorthand, value, usage)
}
...@@ -50,6 +50,48 @@ func (s *uintSliceValue) String() string { ...@@ -50,6 +50,48 @@ func (s *uintSliceValue) String() string {
return "[" + strings.Join(out, ",") + "]" return "[" + strings.Join(out, ",") + "]"
} }
func (s *uintSliceValue) fromString(val string) (uint, error) {
t, err := strconv.ParseUint(val, 10, 0)
if err != nil {
return 0, err
}
return uint(t), nil
}
func (s *uintSliceValue) toString(val uint) string {
return fmt.Sprintf("%d", val)
}
func (s *uintSliceValue) Append(val string) error {
i, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
return nil
}
func (s *uintSliceValue) Replace(val []string) error {
out := make([]uint, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}
func (s *uintSliceValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = s.toString(d)
}
return out
}
func uintSliceConv(val string) (interface{}, error) { func uintSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry // Empty string would cause a slice with one (empty) entry
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// In Go 1.13, the ed25519 package was promoted to the standard library as
// crypto/ed25519, and this package became a wrapper for the standard library one.
//
// +build !go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See // Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/. // https://ed25519.cr.yp.to/.
// //
......
// Copyright 2019 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.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
// Beginning with Go 1.13, the functionality of this package was moved to the
// standard library as crypto/ed25519. This package only acts as a compatibility
// wrapper.
package ed25519
import (
"crypto/ed25519"
"io"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
//
// This type is an alias for crypto/ed25519's PublicKey type.
// See the crypto/ed25519 package for the methods on this type.
type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
//
// This type is an alias for crypto/ed25519's PrivateKey type.
// See the crypto/ed25519 package for the methods on this type.
type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}
...@@ -51,6 +51,13 @@ var supportedKexAlgos = []string{ ...@@ -51,6 +51,13 @@ var supportedKexAlgos = []string{
kexAlgoDH14SHA1, kexAlgoDH1SHA1, kexAlgoDH14SHA1, kexAlgoDH1SHA1,
} }
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
// for the server half.
var serverForbiddenKexAlgos = map[string]struct{}{
kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order. // of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{ var supportedHostKeyAlgos = []string{
......
...@@ -10,7 +10,9 @@ import ( ...@@ -10,7 +10,9 @@ import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/subtle" "crypto/subtle"
"encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"math/big" "math/big"
...@@ -24,6 +26,12 @@ const ( ...@@ -24,6 +26,12 @@ const (
kexAlgoECDH384 = "ecdh-sha2-nistp384" kexAlgoECDH384 = "ecdh-sha2-nistp384"
kexAlgoECDH521 = "ecdh-sha2-nistp521" kexAlgoECDH521 = "ecdh-sha2-nistp521"
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
// For the following kex only the client half contains a production
// ready implementation. The server half only consists of a minimal
// implementation to satisfy the automated tests.
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
) )
// kexResult captures the outcome of a key exchange. // kexResult captures the outcome of a key exchange.
...@@ -402,6 +410,8 @@ func init() { ...@@ -402,6 +410,8 @@ func init() {
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
} }
// curve25519sha256 implements the curve25519-sha256@libssh.org key // curve25519sha256 implements the curve25519-sha256@libssh.org key
...@@ -538,3 +548,242 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh ...@@ -538,3 +548,242 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
Hash: crypto.SHA256, Hash: crypto.SHA256,
}, nil }, nil
} }
// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and
// diffie-hellman-group-exchange-sha256 key agreement protocols,
// as described in RFC 4419
type dhGEXSHA struct {
g, p *big.Int
hashFunc crypto.Hash
}
const numMRTests = 64
const (
dhGroupExchangeMinimumBits = 2048
dhGroupExchangePreferredBits = 2048
dhGroupExchangeMaximumBits = 8192
)
func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
return nil, fmt.Errorf("ssh: DH parameter out of bounds")
}
return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
}
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
// Send GexRequest
kexDHGexRequest := kexDHGexRequestMsg{
MinBits: dhGroupExchangeMinimumBits,
PreferedBits: dhGroupExchangePreferredBits,
MaxBits: dhGroupExchangeMaximumBits,
}
if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
return nil, err
}
// Receive GexGroup
packet, err := c.readPacket()
if err != nil {
return nil, err
}
var kexDHGexGroup kexDHGexGroupMsg
if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
return nil, err
}
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
}
gex.p = kexDHGexGroup.P
gex.g = kexDHGexGroup.G
// Check if p is safe by verifing that p and (p-1)/2 are primes
one := big.NewInt(1)
var pHalf = &big.Int{}
pHalf.Rsh(gex.p, 1)
if !gex.p.ProbablyPrime(numMRTests) || !pHalf.ProbablyPrime(numMRTests) {
return nil, fmt.Errorf("ssh: server provided gex p is not safe")
}
// Check if g is safe by verifing that g > 1 and g < p - 1
var pMinusOne = &big.Int{}
pMinusOne.Sub(gex.p, one)
if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
}
// Send GexInit
x, err := rand.Int(randSource, pHalf)
if err != nil {
return nil, err
}
X := new(big.Int).Exp(gex.g, x, gex.p)
kexDHGexInit := kexDHGexInitMsg{
X: X,
}
if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil {
return nil, err
}
// Receive GexReply
packet, err = c.readPacket()
if err != nil {
return nil, err
}
var kexDHGexReply kexDHGexReplyMsg
if err = Unmarshal(packet, &kexDHGexReply); err != nil {
return nil, err
}
kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
if err != nil {
return nil, err
}
// Check if k is safe by verifing that k > 1 and k < p - 1
if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
return nil, fmt.Errorf("ssh: derived k is not safe")
}
h := gex.hashFunc.New()
magics.write(h)
writeString(h, kexDHGexReply.HostKey)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(h, gex.p)
writeInt(h, gex.g)
writeInt(h, X)
writeInt(h, kexDHGexReply.Y)
K := make([]byte, intLength(kInt))
marshalInt(K, kInt)
h.Write(K)
return &kexResult{
H: h.Sum(nil),
K: K,
HostKey: kexDHGexReply.HostKey,
Signature: kexDHGexReply.Signature,
Hash: gex.hashFunc,
}, nil
}
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
//
// This is a minimal implementation to satisfy the automated tests.
func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
// Receive GexRequest
packet, err := c.readPacket()
if err != nil {
return
}
var kexDHGexRequest kexDHGexRequestMsg
if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
return
}
// smoosh the user's preferred size into our own limits
if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
}
if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
}
// fix min/max if they're inconsistent. technically, we could just pout
// and hang up, but there's no harm in giving them the benefit of the
// doubt and just picking a bitsize for them.
if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
}
if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
}
// Send GexGroup
// This is the group called diffie-hellman-group14-sha1 in RFC
// 4253 and Oakley Group 14 in RFC 3526.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
gex.p = p
gex.g = big.NewInt(2)
kexDHGexGroup := kexDHGexGroupMsg{
P: gex.p,
G: gex.g,
}
if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
return nil, err
}
// Receive GexInit
packet, err = c.readPacket()
if err != nil {
return
}
var kexDHGexInit kexDHGexInitMsg
if err = Unmarshal(packet, &kexDHGexInit); err != nil {
return
}
var pHalf = &big.Int{}
pHalf.Rsh(gex.p, 1)
y, err := rand.Int(randSource, pHalf)
if err != nil {
return
}
Y := new(big.Int).Exp(gex.g, y, gex.p)
kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
if err != nil {
return nil, err
}
hostKeyBytes := priv.PublicKey().Marshal()
h := gex.hashFunc.New()
magics.write(h)
writeString(h, hostKeyBytes)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(h, gex.p)
writeInt(h, gex.g)
writeInt(h, kexDHGexInit.X)
writeInt(h, Y)
K := make([]byte, intLength(kInt))
marshalInt(K, kInt)
h.Write(K)
H := h.Sum(nil)
// H is already a hash, but the hostkey signing will apply its
// own key-specific hash algorithm.
sig, err := signAndMarshal(priv, randSource, H)
if err != nil {
return nil, err
}
kexDHGexReply := kexDHGexReplyMsg{
HostKey: hostKeyBytes,
Y: Y,
Signature: sig,
}
packet = Marshal(&kexDHGexReply)
err = c.writePacket(packet)
return &kexResult{
H: H,
K: K,
HostKey: hostKeyBytes,
Signature: sig,
Hash: gex.hashFunc,
}, err
}
...@@ -97,6 +97,36 @@ type kexDHReplyMsg struct { ...@@ -97,6 +97,36 @@ type kexDHReplyMsg struct {
Signature []byte Signature []byte
} }
// See RFC 4419, section 5.
const msgKexDHGexGroup = 31
type kexDHGexGroupMsg struct {
P *big.Int `sshtype:"31"`
G *big.Int
}
const msgKexDHGexInit = 32
type kexDHGexInitMsg struct {
X *big.Int `sshtype:"32"`
}
const msgKexDHGexReply = 33
type kexDHGexReplyMsg struct {
HostKey []byte `sshtype:"33"`
Y *big.Int
Signature []byte
}
const msgKexDHGexRequest = 34
type kexDHGexRequestMsg struct {
MinBits uint32 `sshtype:"34"`
PreferedBits uint32
MaxBits uint32
}
// See RFC 4253, section 10. // See RFC 4253, section 10.
const msgServiceRequest = 5 const msgServiceRequest = 5
......
...@@ -193,6 +193,12 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha ...@@ -193,6 +193,12 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
if fullConf.MaxAuthTries == 0 { if fullConf.MaxAuthTries == 0 {
fullConf.MaxAuthTries = 6 fullConf.MaxAuthTries = 6
} }
// Check if the config contains any unsupported key exchanges
for _, kex := range fullConf.KeyExchanges {
if _, ok := serverForbiddenKexAlgos[kex]; ok {
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
}
}
s := &connection{ s := &connection{
sshConn: sshConn{conn: c}, sshConn: sshConn{conn: c},
......
...@@ -129,7 +129,8 @@ func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) { ...@@ -129,7 +129,8 @@ func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) { func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
offset := int(ins.Off) offset := int(ins.Off)
if !inBounds(len(in), offset, 0) { // Size of LoadMemShift is always 1 byte
if !inBounds(len(in), offset, 1) {
return 0, false return 0, false
} }
......
...@@ -439,9 +439,6 @@ func (p *parser) resetInsertionMode() { ...@@ -439,9 +439,6 @@ func (p *parser) resetInsertionMode() {
case a.Select: case a.Select:
if !last { if !last {
for ancestor, first := n, p.oe[0]; ancestor != first; { for ancestor, first := n, p.oe[0]; ancestor != first; {
if ancestor == first {
break
}
ancestor = p.oe[p.oe.index(ancestor)-1] ancestor = p.oe[p.oe.index(ancestor)-1]
switch ancestor.DataAtom { switch ancestor.DataAtom {
case a.Template: case a.Template:
...@@ -633,7 +630,16 @@ func inHeadIM(p *parser) bool { ...@@ -633,7 +630,16 @@ func inHeadIM(p *parser) bool {
p.oe.pop() p.oe.pop()
p.acknowledgeSelfClosingTag() p.acknowledgeSelfClosingTag()
return true return true
case a.Script, a.Title, a.Noscript, a.Noframes, a.Style: case a.Noscript:
p.addElement()
if p.scripting {
p.setOriginalIM()
p.im = textIM
} else {
p.im = inHeadNoscriptIM
}
return true
case a.Script, a.Title, a.Noframes, a.Style:
p.addElement() p.addElement()
p.setOriginalIM() p.setOriginalIM()
p.im = textIM p.im = textIM
...@@ -695,6 +701,49 @@ func inHeadIM(p *parser) bool { ...@@ -695,6 +701,49 @@ func inHeadIM(p *parser) bool {
return false return false
} }
// 12.2.6.4.5.
func inHeadNoscriptIM(p *parser) bool {
switch p.tok.Type {
case DoctypeToken:
// Ignore the token.
return true
case StartTagToken:
switch p.tok.DataAtom {
case a.Html:
return inBodyIM(p)
case a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Style:
return inHeadIM(p)
case a.Head, a.Noscript:
// Ignore the token.
return true
}
case EndTagToken:
switch p.tok.DataAtom {
case a.Noscript, a.Br:
default:
// Ignore the token.
return true
}
case TextToken:
s := strings.TrimLeft(p.tok.Data, whitespace)
if len(s) == 0 {
// It was all whitespace.
return inHeadIM(p)
}
case CommentToken:
return inHeadIM(p)
}
p.oe.pop()
if p.top().DataAtom != a.Head {
panic("html: the new current node will be a head element.")
}
p.im = inHeadIM
if p.tok.DataAtom == a.Noscript {
return true
}
return false
}
// Section 12.2.6.4.6. // Section 12.2.6.4.6.
func afterHeadIM(p *parser) bool { func afterHeadIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
...@@ -904,7 +953,7 @@ func inBodyIM(p *parser) bool { ...@@ -904,7 +953,7 @@ func inBodyIM(p *parser) bool {
case a.A: case a.A:
for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- { for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A { if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
p.inBodyEndTagFormatting(a.A) p.inBodyEndTagFormatting(a.A, "a")
p.oe.remove(n) p.oe.remove(n)
p.afe.remove(n) p.afe.remove(n)
break break
...@@ -918,7 +967,7 @@ func inBodyIM(p *parser) bool { ...@@ -918,7 +967,7 @@ func inBodyIM(p *parser) bool {
case a.Nobr: case a.Nobr:
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
if p.elementInScope(defaultScope, a.Nobr) { if p.elementInScope(defaultScope, a.Nobr) {
p.inBodyEndTagFormatting(a.Nobr) p.inBodyEndTagFormatting(a.Nobr, "nobr")
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
} }
p.addFormattingElement() p.addFormattingElement()
...@@ -1126,7 +1175,7 @@ func inBodyIM(p *parser) bool { ...@@ -1126,7 +1175,7 @@ func inBodyIM(p *parser) bool {
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6: case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6) p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U: case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
p.inBodyEndTagFormatting(p.tok.DataAtom) p.inBodyEndTagFormatting(p.tok.DataAtom, p.tok.Data)
case a.Applet, a.Marquee, a.Object: case a.Applet, a.Marquee, a.Object:
if p.popUntil(defaultScope, p.tok.DataAtom) { if p.popUntil(defaultScope, p.tok.DataAtom) {
p.clearActiveFormattingElements() p.clearActiveFormattingElements()
...@@ -1137,7 +1186,7 @@ func inBodyIM(p *parser) bool { ...@@ -1137,7 +1186,7 @@ func inBodyIM(p *parser) bool {
case a.Template: case a.Template:
return inHeadIM(p) return inHeadIM(p)
default: default:
p.inBodyEndTagOther(p.tok.DataAtom) p.inBodyEndTagOther(p.tok.DataAtom, p.tok.Data)
} }
case CommentToken: case CommentToken:
p.addChild(&Node{ p.addChild(&Node{
...@@ -1164,7 +1213,7 @@ func inBodyIM(p *parser) bool { ...@@ -1164,7 +1213,7 @@ func inBodyIM(p *parser) bool {
return true return true
} }
func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
// This is the "adoption agency" algorithm, described at // This is the "adoption agency" algorithm, described at
// https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
...@@ -1186,7 +1235,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { ...@@ -1186,7 +1235,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
} }
} }
if formattingElement == nil { if formattingElement == nil {
p.inBodyEndTagOther(tagAtom) p.inBodyEndTagOther(tagAtom, tagName)
return return
} }
feIndex := p.oe.index(formattingElement) feIndex := p.oe.index(formattingElement)
...@@ -1291,9 +1340,17 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { ...@@ -1291,9 +1340,17 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM. // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content // "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
func (p *parser) inBodyEndTagOther(tagAtom a.Atom) { func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
for i := len(p.oe) - 1; i >= 0; i-- { for i := len(p.oe) - 1; i >= 0; i-- {
if p.oe[i].DataAtom == tagAtom { // Two element nodes have the same tag if they have the same Data (a
// string-typed field). As an optimization, for common HTML tags, each
// Data string is assigned a unique, non-zero DataAtom (a uint32-typed
// field), since integer comparison is faster than string comparison.
// Uncommon (custom) tags get a zero DataAtom.
//
// The if condition here is equivalent to (p.oe[i].Data == tagName).
if (p.oe[i].DataAtom == tagAtom) &&
((tagAtom != 0) || (p.oe[i].Data == tagName)) {
p.oe = p.oe[:i] p.oe = p.oe[:i]
break break
} }
...@@ -1687,8 +1744,9 @@ func inCellIM(p *parser) bool { ...@@ -1687,8 +1744,9 @@ func inCellIM(p *parser) bool {
return true return true
} }
// Close the cell and reprocess. // Close the cell and reprocess.
p.popUntil(tableScope, a.Td, a.Th) if p.popUntil(tableScope, a.Td, a.Th) {
p.clearActiveFormattingElements() p.clearActiveFormattingElements()
}
p.im = inRowIM p.im = inRowIM
return false return false
} }
...@@ -2242,6 +2300,33 @@ func (p *parser) parse() error { ...@@ -2242,6 +2300,33 @@ func (p *parser) parse() error {
// //
// The input is assumed to be UTF-8 encoded. // The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) { func Parse(r io.Reader) (*Node, error) {
return ParseWithOptions(r)
}
// ParseFragment parses a fragment of HTML and returns the nodes that were
// found. If the fragment is the InnerHTML for an existing element, pass that
// element in context.
//
// It has the same intricacies as Parse.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
return ParseFragmentWithOptions(r, context)
}
// ParseOption configures a parser.
type ParseOption func(p *parser)
// ParseOptionEnableScripting configures the scripting flag.
// https://html.spec.whatwg.org/multipage/webappapis.html#enabling-and-disabling-scripting
//
// By default, scripting is enabled.
func ParseOptionEnableScripting(enable bool) ParseOption {
return func(p *parser) {
p.scripting = enable
}
}
// ParseWithOptions is like Parse, with options.
func ParseWithOptions(r io.Reader, opts ...ParseOption) (*Node, error) {
p := &parser{ p := &parser{
tokenizer: NewTokenizer(r), tokenizer: NewTokenizer(r),
doc: &Node{ doc: &Node{
...@@ -2251,6 +2336,11 @@ func Parse(r io.Reader) (*Node, error) { ...@@ -2251,6 +2336,11 @@ func Parse(r io.Reader) (*Node, error) {
framesetOK: true, framesetOK: true,
im: initialIM, im: initialIM,
} }
for _, f := range opts {
f(p)
}
err := p.parse() err := p.parse()
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -2258,12 +2348,8 @@ func Parse(r io.Reader) (*Node, error) { ...@@ -2258,12 +2348,8 @@ func Parse(r io.Reader) (*Node, error) {
return p.doc, nil return p.doc, nil
} }
// ParseFragment parses a fragment of HTML and returns the nodes that were // ParseFragmentWithOptions is like ParseFragment, with options.
// found. If the fragment is the InnerHTML for an existing element, pass that func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) ([]*Node, error) {
// element in context.
//
// It has the same intricacies as Parse.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
contextTag := "" contextTag := ""
if context != nil { if context != nil {
if context.Type != ElementNode { if context.Type != ElementNode {
...@@ -2287,6 +2373,10 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) { ...@@ -2287,6 +2373,10 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
context: context, context: context,
} }
for _, f := range opts {
f(p)
}
root := &Node{ root := &Node{
Type: ElementNode, Type: ElementNode,
DataAtom: a.Html, DataAtom: a.Html,
......
...@@ -643,7 +643,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error { ...@@ -643,7 +643,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
return f.WriteDataPadded(streamID, endStream, data, nil) return f.WriteDataPadded(streamID, endStream, data, nil)
} }
// WriteData writes a DATA frame with optional padding. // WriteDataPadded writes a DATA frame with optional padding.
// //
// If pad is nil, the padding bit is not sent. // If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes. // The length of pad must not exceed 255 bytes.
......
...@@ -283,7 +283,20 @@ func ConfigureServer(s *http.Server, conf *Server) error { ...@@ -283,7 +283,20 @@ func ConfigureServer(s *http.Server, conf *Server) error {
if testHookOnConn != nil { if testHookOnConn != nil {
testHookOnConn() testHookOnConn()
} }
// The TLSNextProto interface predates contexts, so
// the net/http package passes down its per-connection
// base context via an exported but unadvertised
// method on the Handler. This is for internal
// net/http<=>http2 use only.
var ctx context.Context
type baseContexter interface {
BaseContext() context.Context
}
if bc, ok := h.(baseContexter); ok {
ctx = bc.BaseContext()
}
conf.ServeConn(c, &ServeConnOpts{ conf.ServeConn(c, &ServeConnOpts{
Context: ctx,
Handler: h, Handler: h,
BaseConfig: hs, BaseConfig: hs,
}) })
...@@ -294,6 +307,10 @@ func ConfigureServer(s *http.Server, conf *Server) error { ...@@ -294,6 +307,10 @@ func ConfigureServer(s *http.Server, conf *Server) error {
// ServeConnOpts are options for the Server.ServeConn method. // ServeConnOpts are options for the Server.ServeConn method.
type ServeConnOpts struct { type ServeConnOpts struct {
// Context is the base context to use.
// If nil, context.Background is used.
Context context.Context
// BaseConfig optionally sets the base configuration // BaseConfig optionally sets the base configuration
// for values. If nil, defaults are used. // for values. If nil, defaults are used.
BaseConfig *http.Server BaseConfig *http.Server
...@@ -304,6 +321,13 @@ type ServeConnOpts struct { ...@@ -304,6 +321,13 @@ type ServeConnOpts struct {
Handler http.Handler Handler http.Handler
} }
func (o *ServeConnOpts) context() context.Context {
if o.Context != nil {
return o.Context
}
return context.Background()
}
func (o *ServeConnOpts) baseConfig() *http.Server { func (o *ServeConnOpts) baseConfig() *http.Server {
if o != nil && o.BaseConfig != nil { if o != nil && o.BaseConfig != nil {
return o.BaseConfig return o.BaseConfig
...@@ -449,7 +473,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { ...@@ -449,7 +473,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
} }
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) { func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
ctx, cancel = context.WithCancel(context.Background()) ctx, cancel = context.WithCancel(opts.context())
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr()) ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
if hs := opts.baseConfig(); hs != nil { if hs := opts.baseConfig(); hs != nil {
ctx = context.WithValue(ctx, http.ServerContextKey, hs) ctx = context.WithValue(ctx, http.ServerContextKey, hs)
...@@ -2337,7 +2361,16 @@ type chunkWriter struct{ rws *responseWriterState } ...@@ -2337,7 +2361,16 @@ type chunkWriter struct{ rws *responseWriterState }
func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) } func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) != 0 } func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
func (rws *responseWriterState) hasNonemptyTrailers() bool {
for _, trailer := range rws.trailers {
if _, ok := rws.handlerHeader[trailer]; ok {
return true
}
}
return false
}
// declareTrailer is called for each Trailer header when the // declareTrailer is called for each Trailer header when the
// response header is written. It notes that a header will need to be // response header is written. It notes that a header will need to be
...@@ -2437,7 +2470,10 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { ...@@ -2437,7 +2470,10 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
rws.promoteUndeclaredTrailers() rws.promoteUndeclaredTrailers()
} }
endStream := rws.handlerDone && !rws.hasTrailers() // only send trailers if they have actually been defined by the
// server handler.
hasNonemptyTrailers := rws.hasNonemptyTrailers()
endStream := rws.handlerDone && !hasNonemptyTrailers
if len(p) > 0 || endStream { if len(p) > 0 || endStream {
// only send a 0 byte DATA frame if we're ending the stream. // only send a 0 byte DATA frame if we're ending the stream.
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil { if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
...@@ -2446,7 +2482,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { ...@@ -2446,7 +2482,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
} }
} }
if rws.handlerDone && rws.hasTrailers() { if rws.handlerDone && hasNonemptyTrailers {
err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
streamID: rws.stream.id, streamID: rws.stream.id,
h: rws.handlerHeader, h: rws.handlerHeader,
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"golang.org/x/net/http/httpguts" "golang.org/x/net/http/httpguts"
...@@ -199,6 +200,7 @@ type ClientConn struct { ...@@ -199,6 +200,7 @@ type ClientConn struct {
t *Transport t *Transport
tconn net.Conn // usually *tls.Conn, except specialized impls tconn net.Conn // usually *tls.Conn, except specialized impls
tlsState *tls.ConnectionState // nil only for specialized impls tlsState *tls.ConnectionState // nil only for specialized impls
reused uint32 // whether conn is being reused; atomic
singleUse bool // whether being used for a single http.Request singleUse bool // whether being used for a single http.Request
// readLoop goroutine fields: // readLoop goroutine fields:
...@@ -440,7 +442,8 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res ...@@ -440,7 +442,8 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err) t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
return nil, err return nil, err
} }
traceGotConn(req, cc) reused := !atomic.CompareAndSwapUint32(&cc.reused, 0, 1)
traceGotConn(req, cc, reused)
res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req) res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
if err != nil && retry <= 6 { if err != nil && retry <= 6 {
if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil { if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
...@@ -989,7 +992,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf ...@@ -989,7 +992,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
req.Method != "HEAD" { req.Method != "HEAD" {
// Request gzip only, not deflate. Deflate is ambiguous and // Request gzip only, not deflate. Deflate is ambiguous and
// not as universally supported anyway. // not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38 // See: https://zlib.net/zlib_faq.html#faq39
// //
// Note that we don't request this for HEAD requests, // Note that we don't request this for HEAD requests,
// due to a bug in nginx: // due to a bug in nginx:
...@@ -1411,7 +1414,11 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail ...@@ -1411,7 +1414,11 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
// followed by the query production (see Sections 3.3 and 3.4 of // followed by the query production (see Sections 3.3 and 3.4 of
// [RFC3986]). // [RFC3986]).
f(":authority", host) f(":authority", host)
f(":method", req.Method) m := req.Method
if m == "" {
m = http.MethodGet
}
f(":method", m)
if req.Method != "CONNECT" { if req.Method != "CONNECT" {
f(":path", path) f(":path", path)
f(":scheme", req.URL.Scheme) f(":scheme", req.URL.Scheme)
...@@ -2555,15 +2562,15 @@ func traceGetConn(req *http.Request, hostPort string) { ...@@ -2555,15 +2562,15 @@ func traceGetConn(req *http.Request, hostPort string) {
trace.GetConn(hostPort) trace.GetConn(hostPort)
} }
func traceGotConn(req *http.Request, cc *ClientConn) { func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
trace := httptrace.ContextClientTrace(req.Context()) trace := httptrace.ContextClientTrace(req.Context())
if trace == nil || trace.GotConn == nil { if trace == nil || trace.GotConn == nil {
return return
} }
ci := httptrace.GotConnInfo{Conn: cc.tconn} ci := httptrace.GotConnInfo{Conn: cc.tconn}
ci.Reused = reused
cc.mu.Lock() cc.mu.Lock()
ci.Reused = cc.nextStreamID > 1 ci.WasIdle = len(cc.streams) == 0 && reused
ci.WasIdle = len(cc.streams) == 0 && ci.Reused
if ci.WasIdle && !cc.lastActive.IsZero() { if ci.WasIdle && !cc.lastActive.IsZero() {
ci.IdleTime = time.Now().Sub(cc.lastActive) ci.IdleTime = time.Now().Sub(cc.lastActive)
} }
......
...@@ -19,7 +19,8 @@ type randomWriteScheduler struct { ...@@ -19,7 +19,8 @@ type randomWriteScheduler struct {
zero writeQueue zero writeQueue
// sq contains the stream-specific queues, keyed by stream ID. // sq contains the stream-specific queues, keyed by stream ID.
// When a stream is idle or closed, it's deleted from the map. // When a stream is idle, closed, or emptied, it's deleted
// from the map.
sq map[uint32]*writeQueue sq map[uint32]*writeQueue
// pool of empty queues for reuse. // pool of empty queues for reuse.
...@@ -63,8 +64,12 @@ func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) { ...@@ -63,8 +64,12 @@ func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
return ws.zero.shift(), true return ws.zero.shift(), true
} }
// Iterate over all non-idle streams until finding one that can be consumed. // Iterate over all non-idle streams until finding one that can be consumed.
for _, q := range ws.sq { for streamID, q := range ws.sq {
if wr, ok := q.consume(math.MaxInt32); ok { if wr, ok := q.consume(math.MaxInt32); ok {
if q.empty() {
delete(ws.sq, streamID)
ws.queuePool.put(q)
}
return wr, true return wr, true
} }
} }
......
...@@ -4,14 +4,16 @@ ...@@ -4,14 +4,16 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.10
// Package idna implements IDNA2008 using the compatibility processing // Package idna implements IDNA2008 using the compatibility processing
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to // defined by UTS (Unicode Technical Standard) #46, which defines a standard to
// deal with the transition from IDNA2003. // deal with the transition from IDNA2003.
// //
// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC // IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894. // 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
// UTS #46 is defined in http://www.unicode.org/reports/tr46. // UTS #46 is defined in https://www.unicode.org/reports/tr46.
// See http://unicode.org/cldr/utility/idna.jsp for a visualization of the // See https://unicode.org/cldr/utility/idna.jsp for a visualization of the
// differences between these two standards. // differences between these two standards.
package idna // import "golang.org/x/net/idna" package idna // import "golang.org/x/net/idna"
...@@ -297,7 +299,7 @@ func (e runeError) Error() string { ...@@ -297,7 +299,7 @@ func (e runeError) Error() string {
} }
// process implements the algorithm described in section 4 of UTS #46, // process implements the algorithm described in section 4 of UTS #46,
// see http://www.unicode.org/reports/tr46. // see https://www.unicode.org/reports/tr46.
func (p *Profile) process(s string, toASCII bool) (string, error) { func (p *Profile) process(s string, toASCII bool) (string, error) {
var err error var err error
var isBidi bool var isBidi bool
......
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// +build go1.10,!go1.13
package idna package idna
// UnicodeVersion is the Unicode version from which the tables in this package are derived. // UnicodeVersion is the Unicode version from which the tables in this package are derived.
const UnicodeVersion = "10.0.0" const UnicodeVersion = "10.0.0"
var mappings string = "" + // Size: 8176 bytes var mappings string = "" + // Size: 8175 bytes
"\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" + "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" +
"\x053⁄4\x03\x03\x03ʼn\x01s\x03\x03\x03\x01h\x01j\x01r\x01w\x01y" + "\x053⁄4\x03\x03\x03ʼn\x01s\x03\x03\x03\x01h\x01j\x01r\x01w\x01y" +
"\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" + "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" +
...@@ -4554,4 +4556,4 @@ var idnaSparseValues = [1915]valueRange{ ...@@ -4554,4 +4556,4 @@ var idnaSparseValues = [1915]valueRange{
{value: 0x0040, lo: 0xb0, hi: 0xbf}, {value: 0x0040, lo: 0xb0, hi: 0xbf},
} }
// Total table size 42115 bytes (41KiB); checksum: F4A1FA4E // Total table size 42114 bytes (41KiB); checksum: 355A58A4
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd // +build aix darwin dragonfly freebsd netbsd openbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux // +build linux
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket package socket
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build darwin dragonfly freebsd linux netbsd openbsd // +build aix darwin dragonfly freebsd linux netbsd openbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !linux,!netbsd // +build !aix,!linux,!netbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux netbsd // +build aix linux netbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd // +build aix darwin dragonfly freebsd netbsd openbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd // +build aix darwin dragonfly freebsd netbsd
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x
// +build linux // +build linux
package socket package socket
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket package socket
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9
package socket package socket
import ( import (
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9
// +build linux // +build linux
package socket package socket
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package socket package socket
......
...@@ -2,17 +2,14 @@ ...@@ -2,17 +2,14 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9
// +build !linux // +build !linux
package socket package socket
import "errors"
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
...@@ -2,17 +2,14 @@ ...@@ -2,17 +2,14 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9 // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package socket package socket
import "errors"
func (c *Conn) recvMsg(m *Message, flags int) error { func (c *Conn) recvMsg(m *Message, flags int) error {
return errors.New("not implemented") return errNotImplemented
} }
func (c *Conn) sendMsg(m *Message, flags int) error { func (c *Conn) sendMsg(m *Message, flags int) error {
return errors.New("not implemented") return errNotImplemented
} }
// 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 socket
import "errors"
func (c *Conn) recvMsg(m *Message, flags int) error {
return errors.New("not implemented")
}
func (c *Conn) sendMsg(m *Message, flags int) error {
return errors.New("not implemented")
}
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
return 0, errors.New("not implemented")
}
// 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 socket
import (
"errors"
"net"
"os"
"reflect"
"runtime"
)
// A Conn represents a raw connection.
type Conn struct {
c net.Conn
}
// NewConn returns a new raw connection.
func NewConn(c net.Conn) (*Conn, error) {
return &Conn{c: c}, nil
}
func (o *Option) get(c *Conn, b []byte) (int, error) {
s, err := socketOf(c.c)
if err != nil {
return 0, err
}
n, err := getsockopt(s, o.Level, o.Name, b)
return n, os.NewSyscallError("getsockopt", err)
}
func (o *Option) set(c *Conn, b []byte) error {
s, err := socketOf(c.c)
if err != nil {
return err
}
return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
}
func socketOf(c net.Conn) (uintptr, error) {
switch c.(type) {
case *net.TCPConn, *net.UDPConn, *net.IPConn:
v := reflect.ValueOf(c)
switch e := v.Elem(); e.Kind() {
case reflect.Struct:
fd := e.FieldByName("conn").FieldByName("fd")
switch e := fd.Elem(); e.Kind() {
case reflect.Struct:
sysfd := e.FieldByName("sysfd")
if runtime.GOOS == "windows" {
return uintptr(sysfd.Uint()), nil
}
return uintptr(sysfd.Int()), nil
}
}
}
return 0, errors.New("invalid type")
}
...@@ -9,9 +9,12 @@ package socket // import "golang.org/x/net/internal/socket" ...@@ -9,9 +9,12 @@ package socket // import "golang.org/x/net/internal/socket"
import ( import (
"errors" "errors"
"net" "net"
"runtime"
"unsafe" "unsafe"
) )
var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
// An Option represents a sticky socket option. // An Option represents a sticky socket option.
type Option struct { type Option struct {
Level int // level Level int // level
......
...@@ -29,5 +29,5 @@ func init() { ...@@ -29,5 +29,5 @@ func init() {
} }
func roundup(l int) int { func roundup(l int) int {
return (l + kernelAlign - 1) & ^(kernelAlign - 1) return (l + kernelAlign - 1) &^ (kernelAlign - 1)
} }
...@@ -2,16 +2,14 @@ ...@@ -2,16 +2,14 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd openbsd // +build aix darwin dragonfly freebsd openbsd
package socket package socket
import "errors"
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build freebsd netbsd openbsd // +build aix freebsd netbsd openbsd
package socket package socket
...@@ -12,9 +12,12 @@ import ( ...@@ -12,9 +12,12 @@ import (
) )
func probeProtocolStack() int { func probeProtocolStack() int {
if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" { if (runtime.GOOS == "netbsd" || runtime.GOOS == "openbsd") && runtime.GOARCH == "arm" {
return 8 return 8
} }
if runtime.GOOS == "aix" {
return 1
}
var p uintptr var p uintptr
return int(unsafe.Sizeof(p)) return int(unsafe.Sizeof(p))
} }
// Copyright 2019 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
import "golang.org/x/sys/unix"
const (
sysAF_UNSPEC = unix.AF_UNSPEC
sysAF_INET = unix.AF_INET
sysAF_INET6 = unix.AF_INET6
sysSOCK_RAW = unix.SOCK_RAW
)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.12 // +build aix go1.12,darwin
package socket package socket
......
// Copyright 2019 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 riscv64
package socket
const (
sysRECVMMSG = 0xf3
sysSENDMMSG = 0x10d
)
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.9 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package socket package socket
...@@ -34,7 +33,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte { ...@@ -34,7 +33,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte {
if ip4 := ip.To4(); ip4 != nil { if ip4 := ip.To4(); ip4 != nil {
b := make([]byte, sizeofSockaddrInet) b := make([]byte, sizeofSockaddrInet)
switch runtime.GOOS { switch runtime.GOOS {
case "android", "linux", "solaris", "windows": case "android", "illumos", "linux", "solaris", "windows":
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET)) NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
default: default:
b[0] = sizeofSockaddrInet b[0] = sizeofSockaddrInet
...@@ -47,7 +46,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte { ...@@ -47,7 +46,7 @@ func marshalSockaddr(ip net.IP, port int, zone string) []byte {
if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil { if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
b := make([]byte, sizeofSockaddrInet6) b := make([]byte, sizeofSockaddrInet6)
switch runtime.GOOS { switch runtime.GOOS {
case "android", "linux", "solaris", "windows": case "android", "illumos", "linux", "solaris", "windows":
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6)) NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
default: default:
b[0] = sizeofSockaddrInet6 b[0] = sizeofSockaddrInet6
...@@ -69,7 +68,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) { ...@@ -69,7 +68,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) {
} }
var af int var af int
switch runtime.GOOS { switch runtime.GOOS {
case "android", "linux", "solaris", "windows": case "android", "illumos", "linux", "solaris", "windows":
af = int(NativeEndian.Uint16(b[:2])) af = int(NativeEndian.Uint16(b[:2]))
default: default:
af = int(b[1]) af = int(b[1])
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package socket package socket
import ( import (
"errors"
"runtime" "runtime"
"syscall" "syscall"
"unsafe" "unsafe"
...@@ -63,9 +62,9 @@ func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { ...@@ -63,9 +62,9 @@ func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
} }
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
...@@ -2,12 +2,11 @@ ...@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package socket package socket
import ( import (
"errors"
"net" "net"
"runtime" "runtime"
"unsafe" "unsafe"
...@@ -36,29 +35,29 @@ func marshalInetAddr(ip net.IP, port int, zone string) []byte { ...@@ -36,29 +35,29 @@ func marshalInetAddr(ip net.IP, port int, zone string) []byte {
} }
func parseInetAddr(b []byte, network string) (net.Addr, error) { func parseInetAddr(b []byte, network string) (net.Addr, error) {
return nil, errors.New("not implemented") return nil, errNotImplemented
} }
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func setsockopt(s uintptr, level, name int, b []byte) error { func setsockopt(s uintptr, level, name int, b []byte) error {
return errors.New("not implemented") return errNotImplemented
} }
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
package socket package socket
import ( import (
"errors"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
) )
func probeProtocolStack() int { func probeProtocolStack() int {
...@@ -16,11 +17,11 @@ func probeProtocolStack() int { ...@@ -16,11 +17,11 @@ func probeProtocolStack() int {
} }
const ( const (
sysAF_UNSPEC = 0x0 sysAF_UNSPEC = windows.AF_UNSPEC
sysAF_INET = 0x2 sysAF_INET = windows.AF_INET
sysAF_INET6 = 0x17 sysAF_INET6 = windows.AF_INET6
sysSOCK_RAW = 0x3 sysSOCK_RAW = windows.SOCK_RAW
) )
type sockaddrInet struct { type sockaddrInet struct {
...@@ -54,17 +55,17 @@ func setsockopt(s uintptr, level, name int, b []byte) error { ...@@ -54,17 +55,17 @@ func setsockopt(s uintptr, level, name int, b []byte) error {
} }
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
return 0, errors.New("not implemented") return 0, errNotImplemented
} }
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_aix.go
// Added for go1.11 compatibility
// +build aix
package socket
type iovec struct {
Base *byte
Len uint64
}
type msghdr struct {
Name *byte
Namelen uint32
Iov *iovec
Iovlen int32
Control *byte
Controllen uint32
Flags int32
}
type mmsghdr struct {
Hdr msghdr
Len uint32
Pad_cgo_0 [4]byte
}
type cmsghdr struct {
Len uint32
Level int32
Type int32
}
type sockaddrInet struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]uint8
}
type sockaddrInet6 struct {
Len uint8
Family uint8
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofMmsghdr = 0x38
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10
sizeofSockaddrInet6 = 0x1c
)
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_darwin.go // cgo -godefs defs_darwin.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1e
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_darwin.go // cgo -godefs defs_darwin.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1e
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_darwin.go // cgo -godefs defs_darwin.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1e
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_darwin.go // cgo -godefs defs_darwin.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1e
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_dragonfly.go // cgo -godefs defs_dragonfly.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1c
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go // cgo -godefs defs_freebsd.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1c
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go // cgo -godefs defs_freebsd.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1c
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go // cgo -godefs defs_freebsd.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0x1c
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go
package socket
type iovec struct {
Base *byte
Len uint64
}
type msghdr struct {
Name *byte
Namelen uint32
Pad_cgo_0 [4]byte
Iov *iovec
Iovlen int32
Pad_cgo_1 [4]byte
Control *byte
Controllen uint32
Flags int32
}
type cmsghdr struct {
Len uint32
Level int32
Type int32
}
type sockaddrInet struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]int8
}
type sockaddrInet6 struct {
Len uint8
Family uint8
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10
sizeofSockaddrInet6 = 0x1c
)
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint32 Len uint32
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Created by cgo -godefs - DO NOT EDIT // Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go // cgo -godefs defs_linux.go
package socket package socket
const (
sysAF_UNSPEC = 0x0
sysAF_INET = 0x2
sysAF_INET6 = 0xa
sysSOCK_RAW = 0x3
)
type iovec struct { type iovec struct {
Base *byte Base *byte
Len uint64 Len uint64
......
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_linux.go
// +build riscv64
package socket
type iovec struct {
Base *byte
Len uint64
}
type msghdr struct {
Name *byte
Namelen uint32
Iov *iovec
Iovlen uint64
Control *byte
Controllen uint64
Flags int32
Pad_cgo_0 [4]byte
}
type mmsghdr struct {
Hdr msghdr
Len uint32
Pad_cgo_0 [4]byte
}
type cmsghdr struct {
Len uint64
Level int32
Type int32
}
type sockaddrInet struct {
Family uint16
Port uint16
Addr [4]byte /* in_addr */
X__pad [8]uint8
}
type sockaddrInet6 struct {
Family uint16
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10
sizeofSockaddrInet6 = 0x1c
)
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment