Update module labstack/echo/v4 to v4.1.16 (#241)
Update module labstack/echo/v4 to v4.1.16 Reviewed-on: https://kolaente.dev/vikunja/api/pulls/241
This commit is contained in:
parent
f776b799b8
commit
76f19db6e7
92 changed files with 13626 additions and 118 deletions
5
go.mod
5
go.mod
|
@ -45,12 +45,11 @@ require (
|
||||||
github.com/imdario/mergo v0.3.9
|
github.com/imdario/mergo v0.3.9
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/jgautheron/goconst v0.0.0-20200227150835-cda7ea3bf591
|
github.com/jgautheron/goconst v0.0.0-20200227150835-cda7ea3bf591
|
||||||
github.com/labstack/echo/v4 v4.1.14
|
github.com/labstack/echo/v4 v4.1.16
|
||||||
github.com/labstack/gommon v0.3.0
|
github.com/labstack/gommon v0.3.0
|
||||||
github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef
|
github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef
|
||||||
github.com/lib/pq v1.3.0
|
github.com/lib/pq v1.3.0
|
||||||
github.com/mailru/easyjson v0.7.0 // indirect
|
github.com/mailru/easyjson v0.7.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||||
github.com/olekukonko/tablewriter v0.0.4
|
github.com/olekukonko/tablewriter v0.0.4
|
||||||
|
@ -70,8 +69,6 @@ require (
|
||||||
github.com/urfave/cli v1.22.2 // indirect
|
github.com/urfave/cli v1.22.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71
|
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect
|
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/d4l3k/messagediff.v1 v1.2.1
|
gopkg.in/d4l3k/messagediff.v1 v1.2.1
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -195,6 +195,8 @@ github.com/labstack/echo/v4 v4.1.7-0.20190627175217-8fb7b5be270f h1:fNJtR+TNyxTd
|
||||||
github.com/labstack/echo/v4 v4.1.7-0.20190627175217-8fb7b5be270f/go.mod h1:kU/7PwzgNxZH4das4XNsSpBSOD09XIF5YEPzjpkGnGE=
|
github.com/labstack/echo/v4 v4.1.7-0.20190627175217-8fb7b5be270f/go.mod h1:kU/7PwzgNxZH4das4XNsSpBSOD09XIF5YEPzjpkGnGE=
|
||||||
github.com/labstack/echo/v4 v4.1.14 h1:h8XP66UfB3tUm+L3QPw7tmwAu3pJaA/nyfHPCcz46ic=
|
github.com/labstack/echo/v4 v4.1.14 h1:h8XP66UfB3tUm+L3QPw7tmwAu3pJaA/nyfHPCcz46ic=
|
||||||
github.com/labstack/echo/v4 v4.1.14/go.mod h1:Q5KZ1vD3V5FEzjM79hjwVrC3ABr7F5IdM23bXQMRDGg=
|
github.com/labstack/echo/v4 v4.1.14/go.mod h1:Q5KZ1vD3V5FEzjM79hjwVrC3ABr7F5IdM23bXQMRDGg=
|
||||||
|
github.com/labstack/echo/v4 v4.1.16 h1:8swiwjE5Jkai3RPfZoahp8kjVCRNq+y7Q0hPji2Kz0o=
|
||||||
|
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
|
||||||
github.com/labstack/gommon v0.2.9 h1:heVeuAYtevIQVYkGj6A41dtfT91LrvFG220lavpWhrU=
|
github.com/labstack/gommon v0.2.9 h1:heVeuAYtevIQVYkGj6A41dtfT91LrvFG220lavpWhrU=
|
||||||
github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4=
|
github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4=
|
||||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||||
|
@ -217,6 +219,8 @@ github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
||||||
|
@ -363,6 +367,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340 h1:KOcEaR10tFr7gdJV2GCKw8Os5yED1u1aOqHjOAb6d2Y=
|
golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340 h1:KOcEaR10tFr7gdJV2GCKw8Os5yED1u1aOqHjOAb6d2Y=
|
||||||
golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y=
|
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y=
|
||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -399,6 +404,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -430,6 +437,8 @@ golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
7
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
7
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
|
@ -50,6 +50,13 @@ Lower is better!
|
||||||
|
|
||||||
## [Guide](https://echo.labstack.com/guide)
|
## [Guide](https://echo.labstack.com/guide)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```go
|
||||||
|
// go get github.com/labstack/echo/{version}
|
||||||
|
go get github.com/labstack/echo/v4
|
||||||
|
```
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|
16
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
16
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
|
@ -43,6 +43,7 @@ type (
|
||||||
|
|
||||||
// RealIP returns the client's network address based on `X-Forwarded-For`
|
// RealIP returns the client's network address based on `X-Forwarded-For`
|
||||||
// or `X-Real-IP` request header.
|
// or `X-Real-IP` request header.
|
||||||
|
// The behavior can be configured using `Echo#IPExtractor`.
|
||||||
RealIP() string
|
RealIP() string
|
||||||
|
|
||||||
// Path returns the registered path for the handler.
|
// Path returns the registered path for the handler.
|
||||||
|
@ -270,6 +271,10 @@ func (c *context) Scheme() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) RealIP() string {
|
func (c *context) RealIP() string {
|
||||||
|
if c.echo != nil && c.echo.IPExtractor != nil {
|
||||||
|
return c.echo.IPExtractor(c.request)
|
||||||
|
}
|
||||||
|
// Fall back to legacy behavior
|
||||||
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
|
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
|
||||||
return strings.Split(ip, ", ")[0]
|
return strings.Split(ip, ", ")[0]
|
||||||
}
|
}
|
||||||
|
@ -305,6 +310,7 @@ func (c *context) ParamNames() []string {
|
||||||
|
|
||||||
func (c *context) SetParamNames(names ...string) {
|
func (c *context) SetParamNames(names ...string) {
|
||||||
c.pnames = names
|
c.pnames = names
|
||||||
|
*c.echo.maxParam = len(names)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) ParamValues() []string {
|
func (c *context) ParamValues() []string {
|
||||||
|
@ -312,10 +318,7 @@ func (c *context) ParamValues() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) SetParamValues(values ...string) {
|
func (c *context) SetParamValues(values ...string) {
|
||||||
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam at all times
|
c.pvalues = values
|
||||||
for i, val := range values {
|
|
||||||
c.pvalues[i] = val
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) QueryParam(name string) string {
|
func (c *context) QueryParam(name string) string {
|
||||||
|
@ -355,8 +358,11 @@ func (c *context) FormParams() (url.Values, error) {
|
||||||
|
|
||||||
func (c *context) FormFile(name string) (*multipart.FileHeader, error) {
|
func (c *context) FormFile(name string) (*multipart.FileHeader, error) {
|
||||||
f, fh, err := c.request.FormFile(name)
|
f, fh, err := c.request.FormFile(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
return fh, err
|
return fh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) MultipartForm() (*multipart.Form, error) {
|
func (c *context) MultipartForm() (*multipart.Form, error) {
|
||||||
|
|
41
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
41
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
|
@ -59,6 +59,8 @@ import (
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
"golang.org/x/net/http2/h2c"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -88,6 +90,7 @@ type (
|
||||||
Validator Validator
|
Validator Validator
|
||||||
Renderer Renderer
|
Renderer Renderer
|
||||||
Logger Logger
|
Logger Logger
|
||||||
|
IPExtractor IPExtractor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route contains a handler and information for matching against requests.
|
// Route contains a handler and information for matching against requests.
|
||||||
|
@ -227,7 +230,7 @@ const (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.1.14"
|
Version = "4.1.16"
|
||||||
website = "https://echo.labstack.com"
|
website = "https://echo.labstack.com"
|
||||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||||
banner = `
|
banner = `
|
||||||
|
@ -723,6 +726,34 @@ func (e *Echo) StartServer(s *http.Server) (err error) {
|
||||||
return s.Serve(e.TLSListener)
|
return s.Serve(e.TLSListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartH2CServer starts a custom http/2 server with h2c (HTTP/2 Cleartext).
|
||||||
|
func (e *Echo) StartH2CServer(address string, h2s *http2.Server) (err error) {
|
||||||
|
// Setup
|
||||||
|
s := e.Server
|
||||||
|
s.Addr = address
|
||||||
|
e.colorer.SetOutput(e.Logger.Output())
|
||||||
|
s.ErrorLog = e.StdLogger
|
||||||
|
s.Handler = h2c.NewHandler(e, h2s)
|
||||||
|
if e.Debug {
|
||||||
|
e.Logger.SetLevel(log.DEBUG)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !e.HideBanner {
|
||||||
|
e.colorer.Printf(banner, e.colorer.Red("v"+Version), e.colorer.Blue(website))
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Listener == nil {
|
||||||
|
e.Listener, err = newListener(s.Addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !e.HidePort {
|
||||||
|
e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr()))
|
||||||
|
}
|
||||||
|
return s.Serve(e.Listener)
|
||||||
|
}
|
||||||
|
|
||||||
// Close immediately stops the server.
|
// Close immediately stops the server.
|
||||||
// It internally calls `http.Server#Close()`.
|
// It internally calls `http.Server#Close()`.
|
||||||
func (e *Echo) Close() error {
|
func (e *Echo) Close() error {
|
||||||
|
@ -752,6 +783,9 @@ func NewHTTPError(code int, message ...interface{}) *HTTPError {
|
||||||
|
|
||||||
// Error makes it compatible with `error` interface.
|
// Error makes it compatible with `error` interface.
|
||||||
func (he *HTTPError) Error() string {
|
func (he *HTTPError) Error() string {
|
||||||
|
if he.Internal == nil {
|
||||||
|
return fmt.Sprintf("code=%d, message=%v", he.Code, he.Message)
|
||||||
|
}
|
||||||
return fmt.Sprintf("code=%d, message=%v, internal=%v", he.Code, he.Message, he.Internal)
|
return fmt.Sprintf("code=%d, message=%v, internal=%v", he.Code, he.Message, he.Internal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,9 +860,10 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||||
return
|
return
|
||||||
} else if err = c.(*net.TCPConn).SetKeepAlive(true); err != nil {
|
} else if err = c.(*net.TCPConn).SetKeepAlive(true); err != nil {
|
||||||
return
|
return
|
||||||
} else if err = c.(*net.TCPConn).SetKeepAlivePeriod(3 * time.Minute); err != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Ignore error from setting the KeepAlivePeriod as some systems, such as
|
||||||
|
// OpenBSD, do not support setting TCP_USER_TIMEOUT on IPPROTO_TCP
|
||||||
|
_ = c.(*net.TCPConn).SetKeepAlivePeriod(3 * time.Minute)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
|
@ -1,16 +1,14 @@
|
||||||
module github.com/labstack/echo/v4
|
module github.com/labstack/echo/v4
|
||||||
|
|
||||||
go 1.12
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/labstack/gommon v0.3.0
|
github.com/labstack/gommon v0.3.0
|
||||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.11 // indirect
|
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/valyala/fasttemplate v1.1.0
|
github.com/valyala/fasttemplate v1.1.0
|
||||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 // indirect
|
|
||||||
golang.org/x/text v0.3.2 // indirect
|
golang.org/x/text v0.3.2 // indirect
|
||||||
)
|
)
|
||||||
|
|
25
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
25
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
|
@ -1,18 +1,19 @@
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
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/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
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=
|
||||||
|
@ -25,26 +26,24 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||||
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
||||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
137
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
Normal file
137
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ipChecker struct {
|
||||||
|
trustLoopback bool
|
||||||
|
trustLinkLocal bool
|
||||||
|
trustPrivateNet bool
|
||||||
|
trustExtraRanges []*net.IPNet
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrustOption is config for which IP address to trust
|
||||||
|
type TrustOption func(*ipChecker)
|
||||||
|
|
||||||
|
// TrustLoopback configures if you trust loopback address (default: true).
|
||||||
|
func TrustLoopback(v bool) TrustOption {
|
||||||
|
return func(c *ipChecker) {
|
||||||
|
c.trustLoopback = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrustLinkLocal configures if you trust link-local address (default: true).
|
||||||
|
func TrustLinkLocal(v bool) TrustOption {
|
||||||
|
return func(c *ipChecker) {
|
||||||
|
c.trustLinkLocal = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrustPrivateNet configures if you trust private network address (default: true).
|
||||||
|
func TrustPrivateNet(v bool) TrustOption {
|
||||||
|
return func(c *ipChecker) {
|
||||||
|
c.trustPrivateNet = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrustIPRange add trustable IP ranges using CIDR notation.
|
||||||
|
func TrustIPRange(ipRange *net.IPNet) TrustOption {
|
||||||
|
return func(c *ipChecker) {
|
||||||
|
c.trustExtraRanges = append(c.trustExtraRanges, ipRange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIPChecker(configs []TrustOption) *ipChecker {
|
||||||
|
checker := &ipChecker{trustLoopback: true, trustLinkLocal: true, trustPrivateNet: true}
|
||||||
|
for _, configure := range configs {
|
||||||
|
configure(checker)
|
||||||
|
}
|
||||||
|
return checker
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPrivateIPRange(ip net.IP) bool {
|
||||||
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
|
return ip4[0] == 10 ||
|
||||||
|
ip4[0] == 172 && ip4[1]&0xf0 == 16 ||
|
||||||
|
ip4[0] == 192 && ip4[1] == 168
|
||||||
|
}
|
||||||
|
return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ipChecker) trust(ip net.IP) bool {
|
||||||
|
if c.trustLoopback && ip.IsLoopback() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c.trustLinkLocal && ip.IsLinkLocalUnicast() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c.trustPrivateNet && isPrivateIPRange(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, trustedRange := range c.trustExtraRanges {
|
||||||
|
if trustedRange.Contains(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPExtractor is a function to extract IP addr from http.Request.
|
||||||
|
// Set appropriate one to Echo#IPExtractor.
|
||||||
|
// See https://echo.labstack.com/guide/ip-address for more details.
|
||||||
|
type IPExtractor func(*http.Request) string
|
||||||
|
|
||||||
|
// ExtractIPDirect extracts IP address using actual IP address.
|
||||||
|
// Use this if your server faces to internet directory (i.e.: uses no proxy).
|
||||||
|
func ExtractIPDirect() IPExtractor {
|
||||||
|
return func(req *http.Request) string {
|
||||||
|
ra, _, _ := net.SplitHostPort(req.RemoteAddr)
|
||||||
|
return ra
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractIPFromRealIPHeader extracts IP address using x-real-ip header.
|
||||||
|
// Use this if you put proxy which uses this header.
|
||||||
|
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||||
|
checker := newIPChecker(options)
|
||||||
|
return func(req *http.Request) string {
|
||||||
|
directIP := ExtractIPDirect()(req)
|
||||||
|
realIP := req.Header.Get(HeaderXRealIP)
|
||||||
|
if realIP != "" {
|
||||||
|
if ip := net.ParseIP(directIP); ip != nil && checker.trust(ip) {
|
||||||
|
return realIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return directIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractIPFromXFFHeader extracts IP address using x-forwarded-for header.
|
||||||
|
// Use this if you put proxy which uses this header.
|
||||||
|
// This returns nearest untrustable IP. If all IPs are trustable, returns furthest one (i.e.: XFF[0]).
|
||||||
|
func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
|
||||||
|
checker := newIPChecker(options)
|
||||||
|
return func(req *http.Request) string {
|
||||||
|
directIP := ExtractIPDirect()(req)
|
||||||
|
xffs := req.Header[HeaderXForwardedFor]
|
||||||
|
if len(xffs) == 0 {
|
||||||
|
return directIP
|
||||||
|
}
|
||||||
|
ips := append(strings.Split(strings.Join(xffs, ","), ","), directIP)
|
||||||
|
for i := len(ips) - 1; i >= 0; i-- {
|
||||||
|
ip := net.ParseIP(strings.TrimSpace(ips[i]))
|
||||||
|
if ip == nil {
|
||||||
|
// Unable to parse IP; cannot trust entire records
|
||||||
|
return directIP
|
||||||
|
}
|
||||||
|
if !checker.trust(ip) {
|
||||||
|
return ip.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All of the IPs are trusted; return first element because it is furthest from server (best effort strategy).
|
||||||
|
return strings.TrimSpace(ips[0])
|
||||||
|
}
|
||||||
|
}
|
4
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
4
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
|
@ -231,7 +231,9 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix header
|
// Fix header
|
||||||
if req.Header.Get(echo.HeaderXRealIP) == "" {
|
// Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream.
|
||||||
|
// However, for backward compatibility, legacy behavior is preserved unless you configure Echo#IPExtractor.
|
||||||
|
if req.Header.Get(echo.HeaderXRealIP) == "" || c.Echo().IPExtractor != nil {
|
||||||
req.Header.Set(echo.HeaderXRealIP, c.RealIP())
|
req.Header.Set(echo.HeaderXRealIP, c.RealIP())
|
||||||
}
|
}
|
||||||
if req.Header.Get(echo.HeaderXForwardedProto) == "" {
|
if req.Header.Get(echo.HeaderXForwardedProto) == "" {
|
||||||
|
|
3
vendor/github.com/labstack/echo/v4/middleware/rewrite.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/rewrite.go
generated
vendored
|
@ -57,7 +57,8 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
for k, v := range config.Rules {
|
for k, v := range config.Rules {
|
||||||
k = strings.Replace(k, "*", "(.*)", -1)
|
k = regexp.QuoteMeta(k)
|
||||||
|
k = strings.Replace(k, `\*`, "(.*)", -1)
|
||||||
k = k + "$"
|
k = k + "$"
|
||||||
config.rulesRegex[regexp.MustCompile(k)] = v
|
config.rulesRegex[regexp.MustCompile(k)] = v
|
||||||
}
|
}
|
||||||
|
|
46
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
46
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
|
@ -347,7 +347,14 @@ func (r *Router) Find(method, path string, c Context) {
|
||||||
if l == pl {
|
if l == pl {
|
||||||
// Continue search
|
// Continue search
|
||||||
search = search[l:]
|
search = search[l:]
|
||||||
} else {
|
// Finish routing if no remaining search and we are on an leaf node
|
||||||
|
if search == "" && (nn == nil || cn.parent == nil || cn.ppath != "") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to go back up the tree on no matching prefix or no remaining search
|
||||||
|
if l != pl || search == "" {
|
||||||
if nn == nil { // Issue #1348
|
if nn == nil { // Issue #1348
|
||||||
return // Not found
|
return // Not found
|
||||||
}
|
}
|
||||||
|
@ -360,10 +367,6 @@ func (r *Router) Find(method, path string, c Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if search == "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static node
|
// Static node
|
||||||
if child = cn.findChild(search[0], skind); child != nil {
|
if child = cn.findChild(search[0], skind); child != nil {
|
||||||
// Save next
|
// Save next
|
||||||
|
@ -376,8 +379,8 @@ func (r *Router) Find(method, path string, c Context) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Param node
|
|
||||||
Param:
|
Param:
|
||||||
|
// Param node
|
||||||
if child = cn.findChildByKind(pkind); child != nil {
|
if child = cn.findChildByKind(pkind); child != nil {
|
||||||
// Issue #378
|
// Issue #378
|
||||||
if len(pvalues) == n {
|
if len(pvalues) == n {
|
||||||
|
@ -401,24 +404,37 @@ func (r *Router) Find(method, path string, c Context) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any node
|
|
||||||
Any:
|
Any:
|
||||||
if cn = cn.findChildByKind(akind); cn == nil {
|
// Any node
|
||||||
|
if cn = cn.findChildByKind(akind); cn != nil {
|
||||||
|
// If any node is found, use remaining path for pvalues
|
||||||
|
pvalues[len(cn.pnames)-1] = search
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// No node found, continue at stored next node
|
||||||
|
// or find nearest "any" route
|
||||||
if nn != nil {
|
if nn != nil {
|
||||||
// No next node to go down in routing (issue #954)
|
// No next node to go down in routing (issue #954)
|
||||||
// Find nearest "any" route going up the routing tree
|
// Find nearest "any" route going up the routing tree
|
||||||
search = ns
|
search = ns
|
||||||
np := nn.parent
|
np := nn.parent
|
||||||
// Consider param route one level up only
|
// Consider param route one level up only
|
||||||
// if no slash is remaining in search string
|
if cn = nn.findChildByKind(pkind); cn != nil {
|
||||||
if cn = nn.findChildByKind(pkind); cn != nil && strings.IndexByte(ns, '/') == -1 {
|
pos := strings.IndexByte(ns, '/')
|
||||||
|
if pos == -1 {
|
||||||
|
// If no slash is remaining in search string set param value
|
||||||
pvalues[len(cn.pnames)-1] = search
|
pvalues[len(cn.pnames)-1] = search
|
||||||
break
|
break
|
||||||
} else if cn != nil && strings.IndexByte(ns, '/') != 1 {
|
} else if pos > 0 {
|
||||||
// If slash is present, it means that this is a parameterized route.
|
// Otherwise continue route processing with restored next node
|
||||||
cn = cn.parent
|
cn = nn
|
||||||
|
nn = nil
|
||||||
|
ns = ""
|
||||||
goto Param
|
goto Param
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// No param route found, try to resolve nearest any route
|
||||||
for {
|
for {
|
||||||
np = nn.parent
|
np = nn.parent
|
||||||
if cn = nn.findChildByKind(akind); cn != nil {
|
if cn = nn.findChildByKind(akind); cn != nil {
|
||||||
|
@ -439,9 +455,7 @@ func (r *Router) Find(method, path string, c Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return // Not found
|
return // Not found
|
||||||
}
|
|
||||||
pvalues[len(cn.pnames)-1] = search
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.handler = cn.findHandler(method)
|
ctx.handler = cn.findHandler(method)
|
||||||
|
|
12
vendor/github.com/mattn/go-colorable/.travis.yml
generated
vendored
12
vendor/github.com/mattn/go-colorable/.travis.yml
generated
vendored
|
@ -1,9 +1,15 @@
|
||||||
language: go
|
language: go
|
||||||
|
sudo: false
|
||||||
go:
|
go:
|
||||||
|
- 1.13.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- go get github.com/mattn/goveralls
|
- go get -t -v ./...
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
script:
|
script:
|
||||||
- $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw
|
- ./go.test.sh
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
|
4
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
4
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
|
@ -1,8 +1,8 @@
|
||||||
# go-colorable
|
# go-colorable
|
||||||
|
|
||||||
[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
|
|
||||||
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
|
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master)
|
[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
|
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
|
||||||
|
|
||||||
Colorable writer for windows.
|
Colorable writer for windows.
|
||||||
|
|
8
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
8
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
|
@ -27,3 +27,11 @@ func NewColorableStdout() io.Writer {
|
||||||
func NewColorableStderr() io.Writer {
|
func NewColorableStderr() io.Writer {
|
||||||
return os.Stderr
|
return os.Stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableColorsStdout enable colors if possible.
|
||||||
|
func EnableColorsStdout(enabled *bool) func() {
|
||||||
|
if enabled != nil {
|
||||||
|
*enabled = true
|
||||||
|
}
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
8
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
8
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
|
@ -28,3 +28,11 @@ func NewColorableStdout() io.Writer {
|
||||||
func NewColorableStderr() io.Writer {
|
func NewColorableStderr() io.Writer {
|
||||||
return os.Stderr
|
return os.Stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableColorsStdout enable colors if possible.
|
||||||
|
func EnableColorsStdout(enabled *bool) func() {
|
||||||
|
if enabled != nil {
|
||||||
|
*enabled = true
|
||||||
|
}
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
28
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
28
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
|
@ -27,6 +27,8 @@ const (
|
||||||
backgroundRed = 0x40
|
backgroundRed = 0x40
|
||||||
backgroundIntensity = 0x80
|
backgroundIntensity = 0x80
|
||||||
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
||||||
|
|
||||||
|
cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -78,6 +80,8 @@ var (
|
||||||
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
||||||
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
||||||
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
||||||
|
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||||
|
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||||
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -98,6 +102,10 @@ func NewColorable(file *os.File) io.Writer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if isatty.IsTerminal(file.Fd()) {
|
if isatty.IsTerminal(file.Fd()) {
|
||||||
|
var mode uint32
|
||||||
|
if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 {
|
||||||
|
return file
|
||||||
|
}
|
||||||
var csbi consoleScreenBufferInfo
|
var csbi consoleScreenBufferInfo
|
||||||
handle := syscall.Handle(file.Fd())
|
handle := syscall.Handle(file.Fd())
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
@ -1003,3 +1011,23 @@ func n256setup() {
|
||||||
n256backAttr[i] = c.backgroundAttr()
|
n256backAttr[i] = c.backgroundAttr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableColorsStdout enable colors if possible.
|
||||||
|
func EnableColorsStdout(enabled *bool) func() {
|
||||||
|
var mode uint32
|
||||||
|
h := os.Stdout.Fd()
|
||||||
|
if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 {
|
||||||
|
if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 {
|
||||||
|
if enabled != nil {
|
||||||
|
*enabled = true
|
||||||
|
}
|
||||||
|
return func() {
|
||||||
|
procSetConsoleMode.Call(h, uintptr(mode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if enabled != nil {
|
||||||
|
*enabled = true
|
||||||
|
}
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
7
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
7
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
|
@ -1,3 +1,8 @@
|
||||||
module github.com/mattn/go-colorable
|
module github.com/mattn/go-colorable
|
||||||
|
|
||||||
require github.com/mattn/go-isatty v0.0.8
|
require (
|
||||||
|
github.com/mattn/go-isatty v0.0.12
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
9
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
9
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
|
@ -1,4 +1,5 @@
|
||||||
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
echo "" > coverage.txt
|
||||||
|
|
||||||
|
for d in $(go list ./... | grep -v vendor); do
|
||||||
|
go test -race -coverprofile=profile.out -covermode=atomic "$d"
|
||||||
|
if [ -f profile.out ]; then
|
||||||
|
cat profile.out >> coverage.txt
|
||||||
|
rm profile.out
|
||||||
|
fi
|
||||||
|
done
|
50
vendor/golang.org/x/net/http/httpguts/guts.go
generated
vendored
Normal file
50
vendor/golang.org/x/net/http/httpguts/guts.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package httpguts provides functions implementing various details
|
||||||
|
// of the HTTP specification.
|
||||||
|
//
|
||||||
|
// This package is shared by the standard library (which vendors it)
|
||||||
|
// and x/net/http2. It comes with no API stability promise.
|
||||||
|
package httpguts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/textproto"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidTrailerHeader reports whether name is a valid header field name to appear
|
||||||
|
// in trailers.
|
||||||
|
// See RFC 7230, Section 4.1.2
|
||||||
|
func ValidTrailerHeader(name string) bool {
|
||||||
|
name = textproto.CanonicalMIMEHeaderKey(name)
|
||||||
|
if strings.HasPrefix(name, "If-") || badTrailer[name] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var badTrailer = map[string]bool{
|
||||||
|
"Authorization": true,
|
||||||
|
"Cache-Control": true,
|
||||||
|
"Connection": true,
|
||||||
|
"Content-Encoding": true,
|
||||||
|
"Content-Length": true,
|
||||||
|
"Content-Range": true,
|
||||||
|
"Content-Type": true,
|
||||||
|
"Expect": true,
|
||||||
|
"Host": true,
|
||||||
|
"Keep-Alive": true,
|
||||||
|
"Max-Forwards": true,
|
||||||
|
"Pragma": true,
|
||||||
|
"Proxy-Authenticate": true,
|
||||||
|
"Proxy-Authorization": true,
|
||||||
|
"Proxy-Connection": true,
|
||||||
|
"Range": true,
|
||||||
|
"Realm": true,
|
||||||
|
"Te": true,
|
||||||
|
"Trailer": true,
|
||||||
|
"Transfer-Encoding": true,
|
||||||
|
"Www-Authenticate": true,
|
||||||
|
}
|
346
vendor/golang.org/x/net/http/httpguts/httplex.go
generated
vendored
Normal file
346
vendor/golang.org/x/net/http/httpguts/httplex.go
generated
vendored
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package httpguts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"golang.org/x/net/idna"
|
||||||
|
)
|
||||||
|
|
||||||
|
var isTokenTable = [127]bool{
|
||||||
|
'!': true,
|
||||||
|
'#': true,
|
||||||
|
'$': true,
|
||||||
|
'%': true,
|
||||||
|
'&': true,
|
||||||
|
'\'': true,
|
||||||
|
'*': true,
|
||||||
|
'+': true,
|
||||||
|
'-': true,
|
||||||
|
'.': true,
|
||||||
|
'0': true,
|
||||||
|
'1': true,
|
||||||
|
'2': true,
|
||||||
|
'3': true,
|
||||||
|
'4': true,
|
||||||
|
'5': true,
|
||||||
|
'6': true,
|
||||||
|
'7': true,
|
||||||
|
'8': true,
|
||||||
|
'9': true,
|
||||||
|
'A': true,
|
||||||
|
'B': true,
|
||||||
|
'C': true,
|
||||||
|
'D': true,
|
||||||
|
'E': true,
|
||||||
|
'F': true,
|
||||||
|
'G': true,
|
||||||
|
'H': true,
|
||||||
|
'I': true,
|
||||||
|
'J': true,
|
||||||
|
'K': true,
|
||||||
|
'L': true,
|
||||||
|
'M': true,
|
||||||
|
'N': true,
|
||||||
|
'O': true,
|
||||||
|
'P': true,
|
||||||
|
'Q': true,
|
||||||
|
'R': true,
|
||||||
|
'S': true,
|
||||||
|
'T': true,
|
||||||
|
'U': true,
|
||||||
|
'W': true,
|
||||||
|
'V': true,
|
||||||
|
'X': true,
|
||||||
|
'Y': true,
|
||||||
|
'Z': true,
|
||||||
|
'^': true,
|
||||||
|
'_': true,
|
||||||
|
'`': true,
|
||||||
|
'a': true,
|
||||||
|
'b': true,
|
||||||
|
'c': true,
|
||||||
|
'd': true,
|
||||||
|
'e': true,
|
||||||
|
'f': true,
|
||||||
|
'g': true,
|
||||||
|
'h': true,
|
||||||
|
'i': true,
|
||||||
|
'j': true,
|
||||||
|
'k': true,
|
||||||
|
'l': true,
|
||||||
|
'm': true,
|
||||||
|
'n': true,
|
||||||
|
'o': true,
|
||||||
|
'p': true,
|
||||||
|
'q': true,
|
||||||
|
'r': true,
|
||||||
|
's': true,
|
||||||
|
't': true,
|
||||||
|
'u': true,
|
||||||
|
'v': true,
|
||||||
|
'w': true,
|
||||||
|
'x': true,
|
||||||
|
'y': true,
|
||||||
|
'z': true,
|
||||||
|
'|': true,
|
||||||
|
'~': true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsTokenRune(r rune) bool {
|
||||||
|
i := int(r)
|
||||||
|
return i < len(isTokenTable) && isTokenTable[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNotToken(r rune) bool {
|
||||||
|
return !IsTokenRune(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderValuesContainsToken reports whether any string in values
|
||||||
|
// contains the provided token, ASCII case-insensitively.
|
||||||
|
func HeaderValuesContainsToken(values []string, token string) bool {
|
||||||
|
for _, v := range values {
|
||||||
|
if headerValueContainsToken(v, token) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isOWS reports whether b is an optional whitespace byte, as defined
|
||||||
|
// by RFC 7230 section 3.2.3.
|
||||||
|
func isOWS(b byte) bool { return b == ' ' || b == '\t' }
|
||||||
|
|
||||||
|
// trimOWS returns x with all optional whitespace removes from the
|
||||||
|
// beginning and end.
|
||||||
|
func trimOWS(x string) string {
|
||||||
|
// TODO: consider using strings.Trim(x, " \t") instead,
|
||||||
|
// if and when it's fast enough. See issue 10292.
|
||||||
|
// But this ASCII-only code will probably always beat UTF-8
|
||||||
|
// aware code.
|
||||||
|
for len(x) > 0 && isOWS(x[0]) {
|
||||||
|
x = x[1:]
|
||||||
|
}
|
||||||
|
for len(x) > 0 && isOWS(x[len(x)-1]) {
|
||||||
|
x = x[:len(x)-1]
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// headerValueContainsToken reports whether v (assumed to be a
|
||||||
|
// 0#element, in the ABNF extension described in RFC 7230 section 7)
|
||||||
|
// contains token amongst its comma-separated tokens, ASCII
|
||||||
|
// case-insensitively.
|
||||||
|
func headerValueContainsToken(v string, token string) bool {
|
||||||
|
v = trimOWS(v)
|
||||||
|
if comma := strings.IndexByte(v, ','); comma != -1 {
|
||||||
|
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
|
||||||
|
}
|
||||||
|
return tokenEqual(v, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lowerASCII returns the ASCII lowercase version of b.
|
||||||
|
func lowerASCII(b byte) byte {
|
||||||
|
if 'A' <= b && b <= 'Z' {
|
||||||
|
return b + ('a' - 'A')
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
|
||||||
|
func tokenEqual(t1, t2 string) bool {
|
||||||
|
if len(t1) != len(t2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, b := range t1 {
|
||||||
|
if b >= utf8.RuneSelf {
|
||||||
|
// No UTF-8 or non-ASCII allowed in tokens.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isLWS reports whether b is linear white space, according
|
||||||
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||||
|
// LWS = [CRLF] 1*( SP | HT )
|
||||||
|
func isLWS(b byte) bool { return b == ' ' || b == '\t' }
|
||||||
|
|
||||||
|
// isCTL reports whether b is a control byte, according
|
||||||
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||||
|
// CTL = <any US-ASCII control character
|
||||||
|
// (octets 0 - 31) and DEL (127)>
|
||||||
|
func isCTL(b byte) bool {
|
||||||
|
const del = 0x7f // a CTL
|
||||||
|
return b < ' ' || b == del
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
|
||||||
|
// HTTP/2 imposes the additional restriction that uppercase ASCII
|
||||||
|
// letters are not allowed.
|
||||||
|
//
|
||||||
|
// RFC 7230 says:
|
||||||
|
// header-field = field-name ":" OWS field-value OWS
|
||||||
|
// field-name = token
|
||||||
|
// token = 1*tchar
|
||||||
|
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
||||||
|
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
||||||
|
func ValidHeaderFieldName(v string) bool {
|
||||||
|
if len(v) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, r := range v {
|
||||||
|
if !IsTokenRune(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHostHeader reports whether h is a valid host header.
|
||||||
|
func ValidHostHeader(h string) bool {
|
||||||
|
// The latest spec is actually this:
|
||||||
|
//
|
||||||
|
// http://tools.ietf.org/html/rfc7230#section-5.4
|
||||||
|
// Host = uri-host [ ":" port ]
|
||||||
|
//
|
||||||
|
// Where uri-host is:
|
||||||
|
// http://tools.ietf.org/html/rfc3986#section-3.2.2
|
||||||
|
//
|
||||||
|
// But we're going to be much more lenient for now and just
|
||||||
|
// search for any byte that's not a valid byte in any of those
|
||||||
|
// expressions.
|
||||||
|
for i := 0; i < len(h); i++ {
|
||||||
|
if !validHostByte[h[i]] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the validHostHeader comment.
|
||||||
|
var validHostByte = [256]bool{
|
||||||
|
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
|
||||||
|
'8': true, '9': true,
|
||||||
|
|
||||||
|
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
|
||||||
|
'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
|
||||||
|
'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
|
||||||
|
'y': true, 'z': true,
|
||||||
|
|
||||||
|
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
|
||||||
|
'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
|
||||||
|
'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
|
||||||
|
'Y': true, 'Z': true,
|
||||||
|
|
||||||
|
'!': true, // sub-delims
|
||||||
|
'$': true, // sub-delims
|
||||||
|
'%': true, // pct-encoded (and used in IPv6 zones)
|
||||||
|
'&': true, // sub-delims
|
||||||
|
'(': true, // sub-delims
|
||||||
|
')': true, // sub-delims
|
||||||
|
'*': true, // sub-delims
|
||||||
|
'+': true, // sub-delims
|
||||||
|
',': true, // sub-delims
|
||||||
|
'-': true, // unreserved
|
||||||
|
'.': true, // unreserved
|
||||||
|
':': true, // IPv6address + Host expression's optional port
|
||||||
|
';': true, // sub-delims
|
||||||
|
'=': true, // sub-delims
|
||||||
|
'[': true,
|
||||||
|
'\'': true, // sub-delims
|
||||||
|
']': true,
|
||||||
|
'_': true, // unreserved
|
||||||
|
'~': true, // unreserved
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
|
||||||
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
|
||||||
|
//
|
||||||
|
// message-header = field-name ":" [ field-value ]
|
||||||
|
// field-value = *( field-content | LWS )
|
||||||
|
// field-content = <the OCTETs making up the field-value
|
||||||
|
// and consisting of either *TEXT or combinations
|
||||||
|
// of token, separators, and quoted-string>
|
||||||
|
//
|
||||||
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
|
||||||
|
//
|
||||||
|
// TEXT = <any OCTET except CTLs,
|
||||||
|
// but including LWS>
|
||||||
|
// LWS = [CRLF] 1*( SP | HT )
|
||||||
|
// CTL = <any US-ASCII control character
|
||||||
|
// (octets 0 - 31) and DEL (127)>
|
||||||
|
//
|
||||||
|
// RFC 7230 says:
|
||||||
|
// field-value = *( field-content / obs-fold )
|
||||||
|
// obj-fold = N/A to http2, and deprecated
|
||||||
|
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
|
// field-vchar = VCHAR / obs-text
|
||||||
|
// obs-text = %x80-FF
|
||||||
|
// VCHAR = "any visible [USASCII] character"
|
||||||
|
//
|
||||||
|
// http2 further says: "Similarly, HTTP/2 allows header field values
|
||||||
|
// that are not valid. While most of the values that can be encoded
|
||||||
|
// will not alter header field parsing, carriage return (CR, ASCII
|
||||||
|
// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
|
||||||
|
// 0x0) might be exploited by an attacker if they are translated
|
||||||
|
// verbatim. Any request or response that contains a character not
|
||||||
|
// permitted in a header field value MUST be treated as malformed
|
||||||
|
// (Section 8.1.2.6). Valid characters are defined by the
|
||||||
|
// field-content ABNF rule in Section 3.2 of [RFC7230]."
|
||||||
|
//
|
||||||
|
// This function does not (yet?) properly handle the rejection of
|
||||||
|
// strings that begin or end with SP or HTAB.
|
||||||
|
func ValidHeaderFieldValue(v string) bool {
|
||||||
|
for i := 0; i < len(v); i++ {
|
||||||
|
b := v[i]
|
||||||
|
if isCTL(b) && !isLWS(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isASCII(s string) bool {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] >= utf8.RuneSelf {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PunycodeHostPort returns the IDNA Punycode version
|
||||||
|
// of the provided "host" or "host:port" string.
|
||||||
|
func PunycodeHostPort(v string) (string, error) {
|
||||||
|
if isASCII(v) {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
host, port, err := net.SplitHostPort(v)
|
||||||
|
if err != nil {
|
||||||
|
// The input 'v' argument was just a "host" argument,
|
||||||
|
// without a port. This error should not be returned
|
||||||
|
// to the caller.
|
||||||
|
host = v
|
||||||
|
port = ""
|
||||||
|
}
|
||||||
|
host, err = idna.ToASCII(host)
|
||||||
|
if err != nil {
|
||||||
|
// Non-UTF-8? Not representable in Punycode, in any
|
||||||
|
// case.
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if port == "" {
|
||||||
|
return host, nil
|
||||||
|
}
|
||||||
|
return net.JoinHostPort(host, port), nil
|
||||||
|
}
|
2
vendor/golang.org/x/net/http2/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/net/http2/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*~
|
||||||
|
h2i/h2i
|
51
vendor/golang.org/x/net/http2/Dockerfile
generated
vendored
Normal file
51
vendor/golang.org/x/net/http2/Dockerfile
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#
|
||||||
|
# This Dockerfile builds a recent curl with HTTP/2 client support, using
|
||||||
|
# a recent nghttp2 build.
|
||||||
|
#
|
||||||
|
# See the Makefile for how to tag it. If Docker and that image is found, the
|
||||||
|
# Go tests use this curl binary for integration tests.
|
||||||
|
#
|
||||||
|
|
||||||
|
FROM ubuntu:trusty
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get upgrade -y && \
|
||||||
|
apt-get install -y git-core build-essential wget
|
||||||
|
|
||||||
|
RUN apt-get install -y --no-install-recommends \
|
||||||
|
autotools-dev libtool pkg-config zlib1g-dev \
|
||||||
|
libcunit1-dev libssl-dev libxml2-dev libevent-dev \
|
||||||
|
automake autoconf
|
||||||
|
|
||||||
|
# The list of packages nghttp2 recommends for h2load:
|
||||||
|
RUN apt-get install -y --no-install-recommends make binutils \
|
||||||
|
autoconf automake autotools-dev \
|
||||||
|
libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
|
||||||
|
libev-dev libevent-dev libjansson-dev libjemalloc-dev \
|
||||||
|
cython python3.4-dev python-setuptools
|
||||||
|
|
||||||
|
# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
|
||||||
|
ENV NGHTTP2_VER 895da9a
|
||||||
|
RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
|
||||||
|
|
||||||
|
WORKDIR /root/nghttp2
|
||||||
|
RUN git reset --hard $NGHTTP2_VER
|
||||||
|
RUN autoreconf -i
|
||||||
|
RUN automake
|
||||||
|
RUN autoconf
|
||||||
|
RUN ./configure
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
|
||||||
|
RUN tar -zxvf curl-7.45.0.tar.gz
|
||||||
|
WORKDIR /root/curl-7.45.0
|
||||||
|
RUN ./configure --with-ssl --with-nghttp2=/usr/local
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
RUN ldconfig
|
||||||
|
|
||||||
|
CMD ["-h"]
|
||||||
|
ENTRYPOINT ["/usr/local/bin/curl"]
|
||||||
|
|
3
vendor/golang.org/x/net/http2/Makefile
generated
vendored
Normal file
3
vendor/golang.org/x/net/http2/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
curlimage:
|
||||||
|
docker build -t gohttp2/curl .
|
||||||
|
|
20
vendor/golang.org/x/net/http2/README
generated
vendored
Normal file
20
vendor/golang.org/x/net/http2/README
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
This is a work-in-progress HTTP/2 implementation for Go.
|
||||||
|
|
||||||
|
It will eventually live in the Go standard library and won't require
|
||||||
|
any changes to your code to use. It will just be automatic.
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
* The server support is pretty good. A few things are missing
|
||||||
|
but are being worked on.
|
||||||
|
* The client work has just started but shares a lot of code
|
||||||
|
is coming along much quicker.
|
||||||
|
|
||||||
|
Docs are at https://godoc.org/golang.org/x/net/http2
|
||||||
|
|
||||||
|
Demo test server at https://http2.golang.org/
|
||||||
|
|
||||||
|
Help & bug reports welcome!
|
||||||
|
|
||||||
|
Contributing: https://golang.org/doc/contribute.html
|
||||||
|
Bugs: https://golang.org/issue/new?title=x/net/http2:+
|
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
// A list of the possible cipher suite ids. Taken from
|
||||||
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
|
||||||
|
|
||||||
|
const (
|
||||||
|
cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
|
||||||
|
// Reserved uint16 = 0x001C-1D
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
|
||||||
|
// Reserved uint16 = 0x0047-4F
|
||||||
|
// Reserved uint16 = 0x0050-58
|
||||||
|
// Reserved uint16 = 0x0059-5C
|
||||||
|
// Unassigned uint16 = 0x005D-5F
|
||||||
|
// Reserved uint16 = 0x0060-66
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
|
||||||
|
// Unassigned uint16 = 0x006E-83
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
|
||||||
|
// Unassigned uint16 = 0x00C6-FE
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
|
||||||
|
// Unassigned uint16 = 0x01-55,*
|
||||||
|
cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
|
||||||
|
// Unassigned uint16 = 0x5601 - 0xC000
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
|
||||||
|
// Unassigned uint16 = 0xC0B0-FF
|
||||||
|
// Unassigned uint16 = 0xC1-CB,*
|
||||||
|
// Unassigned uint16 = 0xCC00-A7
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
|
||||||
|
cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
|
||||||
|
)
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
// References:
|
||||||
|
// https://tools.ietf.org/html/rfc7540#appendix-A
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case cipher_TLS_NULL_WITH_NULL_NULL,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
282
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
Normal file
282
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// Transport code's client connection pooling.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClientConnPool manages a pool of HTTP/2 client connections.
|
||||||
|
type ClientConnPool interface {
|
||||||
|
GetClientConn(req *http.Request, addr string) (*ClientConn, error)
|
||||||
|
MarkDead(*ClientConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
|
||||||
|
// implementations which can close their idle connections.
|
||||||
|
type clientConnPoolIdleCloser interface {
|
||||||
|
ClientConnPool
|
||||||
|
closeIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ clientConnPoolIdleCloser = (*clientConnPool)(nil)
|
||||||
|
_ clientConnPoolIdleCloser = noDialClientConnPool{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: use singleflight for dialing and addConnCalls?
|
||||||
|
type clientConnPool struct {
|
||||||
|
t *Transport
|
||||||
|
|
||||||
|
mu sync.Mutex // TODO: maybe switch to RWMutex
|
||||||
|
// TODO: add support for sharing conns based on cert names
|
||||||
|
// (e.g. share conn for googleapis.com and appspot.com)
|
||||||
|
conns map[string][]*ClientConn // key is host:port
|
||||||
|
dialing map[string]*dialCall // currently in-flight dials
|
||||||
|
keys map[*ClientConn][]string
|
||||||
|
addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
||||||
|
return p.getClientConn(req, addr, dialOnMiss)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
dialOnMiss = true
|
||||||
|
noDialOnMiss = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// shouldTraceGetConn reports whether getClientConn should call any
|
||||||
|
// ClientTrace.GetConn hook associated with the http.Request.
|
||||||
|
//
|
||||||
|
// This complexity is needed to avoid double calls of the GetConn hook
|
||||||
|
// during the back-and-forth between net/http and x/net/http2 (when the
|
||||||
|
// net/http.Transport is upgraded to also speak http2), as well as support
|
||||||
|
// the case where x/net/http2 is being used directly.
|
||||||
|
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
|
||||||
|
// If our Transport wasn't made via ConfigureTransport, always
|
||||||
|
// trace the GetConn hook if provided, because that means the
|
||||||
|
// http2 package is being used directly and it's the one
|
||||||
|
// dialing, as opposed to net/http.
|
||||||
|
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Otherwise, only use the GetConn hook if this connection has
|
||||||
|
// been used previously for other requests. For fresh
|
||||||
|
// connections, the net/http package does the dialing.
|
||||||
|
return !st.freshConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
||||||
|
if isConnectionCloseRequest(req) && dialOnMiss {
|
||||||
|
// It gets its own connection.
|
||||||
|
traceGetConn(req, addr)
|
||||||
|
const singleUse = true
|
||||||
|
cc, err := p.t.dialClientConn(addr, singleUse)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
|
p.mu.Lock()
|
||||||
|
for _, cc := range p.conns[addr] {
|
||||||
|
if st := cc.idleState(); st.canTakeNewRequest {
|
||||||
|
if p.shouldTraceGetConn(st) {
|
||||||
|
traceGetConn(req, addr)
|
||||||
|
}
|
||||||
|
p.mu.Unlock()
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !dialOnMiss {
|
||||||
|
p.mu.Unlock()
|
||||||
|
return nil, ErrNoCachedConn
|
||||||
|
}
|
||||||
|
traceGetConn(req, addr)
|
||||||
|
call := p.getStartDialLocked(addr)
|
||||||
|
p.mu.Unlock()
|
||||||
|
<-call.done
|
||||||
|
return call.res, call.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// dialCall is an in-flight Transport dial call to a host.
|
||||||
|
type dialCall struct {
|
||||||
|
p *clientConnPool
|
||||||
|
done chan struct{} // closed when done
|
||||||
|
res *ClientConn // valid after done is closed
|
||||||
|
err error // valid after done is closed
|
||||||
|
}
|
||||||
|
|
||||||
|
// requires p.mu is held.
|
||||||
|
func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
|
||||||
|
if call, ok := p.dialing[addr]; ok {
|
||||||
|
// A dial is already in-flight. Don't start another.
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
call := &dialCall{p: p, done: make(chan struct{})}
|
||||||
|
if p.dialing == nil {
|
||||||
|
p.dialing = make(map[string]*dialCall)
|
||||||
|
}
|
||||||
|
p.dialing[addr] = call
|
||||||
|
go call.dial(addr)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
// run in its own goroutine.
|
||||||
|
func (c *dialCall) dial(addr string) {
|
||||||
|
const singleUse = false // shared conn
|
||||||
|
c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
|
||||||
|
close(c.done)
|
||||||
|
|
||||||
|
c.p.mu.Lock()
|
||||||
|
delete(c.p.dialing, addr)
|
||||||
|
if c.err == nil {
|
||||||
|
c.p.addConnLocked(addr, c.res)
|
||||||
|
}
|
||||||
|
c.p.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
|
||||||
|
// already exist. It coalesces concurrent calls with the same key.
|
||||||
|
// This is used by the http1 Transport code when it creates a new connection. Because
|
||||||
|
// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
|
||||||
|
// the protocol), it can get into a situation where it has multiple TLS connections.
|
||||||
|
// This code decides which ones live or die.
|
||||||
|
// The return value used is whether c was used.
|
||||||
|
// c is never closed.
|
||||||
|
func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
|
||||||
|
p.mu.Lock()
|
||||||
|
for _, cc := range p.conns[key] {
|
||||||
|
if cc.CanTakeNewRequest() {
|
||||||
|
p.mu.Unlock()
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call, dup := p.addConnCalls[key]
|
||||||
|
if !dup {
|
||||||
|
if p.addConnCalls == nil {
|
||||||
|
p.addConnCalls = make(map[string]*addConnCall)
|
||||||
|
}
|
||||||
|
call = &addConnCall{
|
||||||
|
p: p,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
p.addConnCalls[key] = call
|
||||||
|
go call.run(t, key, c)
|
||||||
|
}
|
||||||
|
p.mu.Unlock()
|
||||||
|
|
||||||
|
<-call.done
|
||||||
|
if call.err != nil {
|
||||||
|
return false, call.err
|
||||||
|
}
|
||||||
|
return !dup, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type addConnCall struct {
|
||||||
|
p *clientConnPool
|
||||||
|
done chan struct{} // closed when done
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
|
||||||
|
cc, err := t.NewClientConn(tc)
|
||||||
|
|
||||||
|
p := c.p
|
||||||
|
p.mu.Lock()
|
||||||
|
if err != nil {
|
||||||
|
c.err = err
|
||||||
|
} else {
|
||||||
|
p.addConnLocked(key, cc)
|
||||||
|
}
|
||||||
|
delete(p.addConnCalls, key)
|
||||||
|
p.mu.Unlock()
|
||||||
|
close(c.done)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *clientConnPool) addConn(key string, cc *ClientConn) {
|
||||||
|
p.mu.Lock()
|
||||||
|
p.addConnLocked(key, cc)
|
||||||
|
p.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// p.mu must be held
|
||||||
|
func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
|
||||||
|
for _, v := range p.conns[key] {
|
||||||
|
if v == cc {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.conns == nil {
|
||||||
|
p.conns = make(map[string][]*ClientConn)
|
||||||
|
}
|
||||||
|
if p.keys == nil {
|
||||||
|
p.keys = make(map[*ClientConn][]string)
|
||||||
|
}
|
||||||
|
p.conns[key] = append(p.conns[key], cc)
|
||||||
|
p.keys[cc] = append(p.keys[cc], key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *clientConnPool) MarkDead(cc *ClientConn) {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
for _, key := range p.keys[cc] {
|
||||||
|
vv, ok := p.conns[key]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newList := filterOutClientConn(vv, cc)
|
||||||
|
if len(newList) > 0 {
|
||||||
|
p.conns[key] = newList
|
||||||
|
} else {
|
||||||
|
delete(p.conns, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(p.keys, cc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *clientConnPool) closeIdleConnections() {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
// TODO: don't close a cc if it was just added to the pool
|
||||||
|
// milliseconds ago and has never been used. There's currently
|
||||||
|
// a small race window with the HTTP/1 Transport's integration
|
||||||
|
// where it can add an idle conn just before using it, and
|
||||||
|
// somebody else can concurrently call CloseIdleConns and
|
||||||
|
// break some caller's RoundTrip.
|
||||||
|
for _, vv := range p.conns {
|
||||||
|
for _, cc := range vv {
|
||||||
|
cc.closeIfIdle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
|
||||||
|
out := in[:0]
|
||||||
|
for _, v := range in {
|
||||||
|
if v != exclude {
|
||||||
|
out = append(out, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we filtered it out, zero out the last item to prevent
|
||||||
|
// the GC from seeing it.
|
||||||
|
if len(in) != len(out) {
|
||||||
|
in[len(in)-1] = nil
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// noDialClientConnPool is an implementation of http2.ClientConnPool
|
||||||
|
// which never dials. We let the HTTP/1.1 client dial and use its TLS
|
||||||
|
// connection instead.
|
||||||
|
type noDialClientConnPool struct{ *clientConnPool }
|
||||||
|
|
||||||
|
func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
||||||
|
return p.getClientConn(req, addr, noDialOnMiss)
|
||||||
|
}
|
146
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
Normal file
146
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Buffer chunks are allocated from a pool to reduce pressure on GC.
|
||||||
|
// The maximum wasted space per dataBuffer is 2x the largest size class,
|
||||||
|
// which happens when the dataBuffer has multiple chunks and there is
|
||||||
|
// one unread byte in both the first and last chunks. We use a few size
|
||||||
|
// classes to minimize overheads for servers that typically receive very
|
||||||
|
// small request bodies.
|
||||||
|
//
|
||||||
|
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
||||||
|
// improved enough that we can instead allocate chunks like this:
|
||||||
|
// make([]byte, max(16<<10, expectedBytesRemaining))
|
||||||
|
var (
|
||||||
|
dataChunkSizeClasses = []int{
|
||||||
|
1 << 10,
|
||||||
|
2 << 10,
|
||||||
|
4 << 10,
|
||||||
|
8 << 10,
|
||||||
|
16 << 10,
|
||||||
|
}
|
||||||
|
dataChunkPools = [...]sync.Pool{
|
||||||
|
{New: func() interface{} { return make([]byte, 1<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 2<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 4<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 8<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 16<<10) }},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDataBufferChunk(size int64) []byte {
|
||||||
|
i := 0
|
||||||
|
for ; i < len(dataChunkSizeClasses)-1; i++ {
|
||||||
|
if size <= int64(dataChunkSizeClasses[i]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataChunkPools[i].Get().([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putDataBufferChunk(p []byte) {
|
||||||
|
for i, n := range dataChunkSizeClasses {
|
||||||
|
if len(p) == n {
|
||||||
|
dataChunkPools[i].Put(p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
||||||
|
// Each dataBuffer is used to read DATA frames on a single stream.
|
||||||
|
// The buffer is divided into chunks so the server can limit the
|
||||||
|
// total memory used by a single connection without limiting the
|
||||||
|
// request body size on any single stream.
|
||||||
|
type dataBuffer struct {
|
||||||
|
chunks [][]byte
|
||||||
|
r int // next byte to read is chunks[0][r]
|
||||||
|
w int // next byte to write is chunks[len(chunks)-1][w]
|
||||||
|
size int // total buffered bytes
|
||||||
|
expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errReadEmpty = errors.New("read from empty dataBuffer")
|
||||||
|
|
||||||
|
// Read copies bytes from the buffer into p.
|
||||||
|
// It is an error to read when no data is available.
|
||||||
|
func (b *dataBuffer) Read(p []byte) (int, error) {
|
||||||
|
if b.size == 0 {
|
||||||
|
return 0, errReadEmpty
|
||||||
|
}
|
||||||
|
var ntotal int
|
||||||
|
for len(p) > 0 && b.size > 0 {
|
||||||
|
readFrom := b.bytesFromFirstChunk()
|
||||||
|
n := copy(p, readFrom)
|
||||||
|
p = p[n:]
|
||||||
|
ntotal += n
|
||||||
|
b.r += n
|
||||||
|
b.size -= n
|
||||||
|
// If the first chunk has been consumed, advance to the next chunk.
|
||||||
|
if b.r == len(b.chunks[0]) {
|
||||||
|
putDataBufferChunk(b.chunks[0])
|
||||||
|
end := len(b.chunks) - 1
|
||||||
|
copy(b.chunks[:end], b.chunks[1:])
|
||||||
|
b.chunks[end] = nil
|
||||||
|
b.chunks = b.chunks[:end]
|
||||||
|
b.r = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ntotal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *dataBuffer) bytesFromFirstChunk() []byte {
|
||||||
|
if len(b.chunks) == 1 {
|
||||||
|
return b.chunks[0][b.r:b.w]
|
||||||
|
}
|
||||||
|
return b.chunks[0][b.r:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of bytes of the unread portion of the buffer.
|
||||||
|
func (b *dataBuffer) Len() int {
|
||||||
|
return b.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write appends p to the buffer.
|
||||||
|
func (b *dataBuffer) Write(p []byte) (int, error) {
|
||||||
|
ntotal := len(p)
|
||||||
|
for len(p) > 0 {
|
||||||
|
// If the last chunk is empty, allocate a new chunk. Try to allocate
|
||||||
|
// enough to fully copy p plus any additional bytes we expect to
|
||||||
|
// receive. However, this may allocate less than len(p).
|
||||||
|
want := int64(len(p))
|
||||||
|
if b.expected > want {
|
||||||
|
want = b.expected
|
||||||
|
}
|
||||||
|
chunk := b.lastChunkOrAlloc(want)
|
||||||
|
n := copy(chunk[b.w:], p)
|
||||||
|
p = p[n:]
|
||||||
|
b.w += n
|
||||||
|
b.size += n
|
||||||
|
b.expected -= int64(n)
|
||||||
|
}
|
||||||
|
return ntotal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
|
||||||
|
if len(b.chunks) != 0 {
|
||||||
|
last := b.chunks[len(b.chunks)-1]
|
||||||
|
if b.w < len(last) {
|
||||||
|
return last
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chunk := getDataBufferChunk(want)
|
||||||
|
b.chunks = append(b.chunks, chunk)
|
||||||
|
b.w = 0
|
||||||
|
return chunk
|
||||||
|
}
|
133
vendor/golang.org/x/net/http2/errors.go
generated
vendored
Normal file
133
vendor/golang.org/x/net/http2/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
|
||||||
|
type ErrCode uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrCodeNo ErrCode = 0x0
|
||||||
|
ErrCodeProtocol ErrCode = 0x1
|
||||||
|
ErrCodeInternal ErrCode = 0x2
|
||||||
|
ErrCodeFlowControl ErrCode = 0x3
|
||||||
|
ErrCodeSettingsTimeout ErrCode = 0x4
|
||||||
|
ErrCodeStreamClosed ErrCode = 0x5
|
||||||
|
ErrCodeFrameSize ErrCode = 0x6
|
||||||
|
ErrCodeRefusedStream ErrCode = 0x7
|
||||||
|
ErrCodeCancel ErrCode = 0x8
|
||||||
|
ErrCodeCompression ErrCode = 0x9
|
||||||
|
ErrCodeConnect ErrCode = 0xa
|
||||||
|
ErrCodeEnhanceYourCalm ErrCode = 0xb
|
||||||
|
ErrCodeInadequateSecurity ErrCode = 0xc
|
||||||
|
ErrCodeHTTP11Required ErrCode = 0xd
|
||||||
|
)
|
||||||
|
|
||||||
|
var errCodeName = map[ErrCode]string{
|
||||||
|
ErrCodeNo: "NO_ERROR",
|
||||||
|
ErrCodeProtocol: "PROTOCOL_ERROR",
|
||||||
|
ErrCodeInternal: "INTERNAL_ERROR",
|
||||||
|
ErrCodeFlowControl: "FLOW_CONTROL_ERROR",
|
||||||
|
ErrCodeSettingsTimeout: "SETTINGS_TIMEOUT",
|
||||||
|
ErrCodeStreamClosed: "STREAM_CLOSED",
|
||||||
|
ErrCodeFrameSize: "FRAME_SIZE_ERROR",
|
||||||
|
ErrCodeRefusedStream: "REFUSED_STREAM",
|
||||||
|
ErrCodeCancel: "CANCEL",
|
||||||
|
ErrCodeCompression: "COMPRESSION_ERROR",
|
||||||
|
ErrCodeConnect: "CONNECT_ERROR",
|
||||||
|
ErrCodeEnhanceYourCalm: "ENHANCE_YOUR_CALM",
|
||||||
|
ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
|
||||||
|
ErrCodeHTTP11Required: "HTTP_1_1_REQUIRED",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrCode) String() string {
|
||||||
|
if s, ok := errCodeName[e]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectionError is an error that results in the termination of the
|
||||||
|
// entire connection.
|
||||||
|
type ConnectionError ErrCode
|
||||||
|
|
||||||
|
func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
|
||||||
|
|
||||||
|
// StreamError is an error that only affects one stream within an
|
||||||
|
// HTTP/2 connection.
|
||||||
|
type StreamError struct {
|
||||||
|
StreamID uint32
|
||||||
|
Code ErrCode
|
||||||
|
Cause error // optional additional detail
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamError(id uint32, code ErrCode) StreamError {
|
||||||
|
return StreamError{StreamID: id, Code: code}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e StreamError) Error() string {
|
||||||
|
if e.Cause != nil {
|
||||||
|
return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6.9.1 The Flow Control Window
|
||||||
|
// "If a sender receives a WINDOW_UPDATE that causes a flow control
|
||||||
|
// window to exceed this maximum it MUST terminate either the stream
|
||||||
|
// or the connection, as appropriate. For streams, [...]; for the
|
||||||
|
// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
|
||||||
|
type goAwayFlowError struct{}
|
||||||
|
|
||||||
|
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
||||||
|
|
||||||
|
// connError represents an HTTP/2 ConnectionError error code, along
|
||||||
|
// with a string (for debugging) explaining why.
|
||||||
|
//
|
||||||
|
// Errors of this type are only returned by the frame parser functions
|
||||||
|
// and converted into ConnectionError(Code), after stashing away
|
||||||
|
// the Reason into the Framer's errDetail field, accessible via
|
||||||
|
// the (*Framer).ErrorDetail method.
|
||||||
|
type connError struct {
|
||||||
|
Code ErrCode // the ConnectionError error code
|
||||||
|
Reason string // additional reason
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e connError) Error() string {
|
||||||
|
return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
type pseudoHeaderError string
|
||||||
|
|
||||||
|
func (e pseudoHeaderError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid pseudo-header %q", string(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
type duplicatePseudoHeaderError string
|
||||||
|
|
||||||
|
func (e duplicatePseudoHeaderError) Error() string {
|
||||||
|
return fmt.Sprintf("duplicate pseudo-header %q", string(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
type headerFieldNameError string
|
||||||
|
|
||||||
|
func (e headerFieldNameError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid header field name %q", string(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
type headerFieldValueError string
|
||||||
|
|
||||||
|
func (e headerFieldValueError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid header field value %q", string(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
|
||||||
|
errPseudoAfterRegular = errors.New("pseudo header field after regular")
|
||||||
|
)
|
50
vendor/golang.org/x/net/http2/flow.go
generated
vendored
Normal file
50
vendor/golang.org/x/net/http2/flow.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flow control
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
// flow is the flow control window's size.
|
||||||
|
type flow struct {
|
||||||
|
// n is the number of DATA bytes we're allowed to send.
|
||||||
|
// A flow is kept both on a conn and a per-stream.
|
||||||
|
n int32
|
||||||
|
|
||||||
|
// conn points to the shared connection-level flow that is
|
||||||
|
// shared by all streams on that conn. It is nil for the flow
|
||||||
|
// that's on the conn directly.
|
||||||
|
conn *flow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
|
||||||
|
|
||||||
|
func (f *flow) available() int32 {
|
||||||
|
n := f.n
|
||||||
|
if f.conn != nil && f.conn.n < n {
|
||||||
|
n = f.conn.n
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *flow) take(n int32) {
|
||||||
|
if n > f.available() {
|
||||||
|
panic("internal error: took too much")
|
||||||
|
}
|
||||||
|
f.n -= n
|
||||||
|
if f.conn != nil {
|
||||||
|
f.conn.n -= n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add adds n bytes (positive or negative) to the flow control window.
|
||||||
|
// It returns false if the sum would exceed 2^31-1.
|
||||||
|
func (f *flow) add(n int32) bool {
|
||||||
|
sum := f.n + n
|
||||||
|
if (sum > n) == (f.n > 0) {
|
||||||
|
f.n = sum
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
1614
vendor/golang.org/x/net/http2/frame.go
generated
vendored
Normal file
1614
vendor/golang.org/x/net/http2/frame.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
29
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
29
vendor/golang.org/x/net/http2/go111.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.11
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptrace"
|
||||||
|
"net/textproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
||||||
|
return trace != nil && trace.WroteHeaderField != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
||||||
|
if trace != nil && trace.WroteHeaderField != nil {
|
||||||
|
trace.WroteHeaderField(k, []string{v})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
if trace != nil {
|
||||||
|
return trace.Got1xxResponse
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
170
vendor/golang.org/x/net/http2/gotrack.go
generated
vendored
Normal file
170
vendor/golang.org/x/net/http2/gotrack.go
generated
vendored
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Defensive debug-only utility to track that functions run on the
|
||||||
|
// goroutine that they're supposed to.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
|
||||||
|
|
||||||
|
type goroutineLock uint64
|
||||||
|
|
||||||
|
func newGoroutineLock() goroutineLock {
|
||||||
|
if !DebugGoroutines {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return goroutineLock(curGoroutineID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g goroutineLock) check() {
|
||||||
|
if !DebugGoroutines {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if curGoroutineID() != uint64(g) {
|
||||||
|
panic("running on the wrong goroutine")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g goroutineLock) checkNotOn() {
|
||||||
|
if !DebugGoroutines {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if curGoroutineID() == uint64(g) {
|
||||||
|
panic("running on the wrong goroutine")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var goroutineSpace = []byte("goroutine ")
|
||||||
|
|
||||||
|
func curGoroutineID() uint64 {
|
||||||
|
bp := littleBuf.Get().(*[]byte)
|
||||||
|
defer littleBuf.Put(bp)
|
||||||
|
b := *bp
|
||||||
|
b = b[:runtime.Stack(b, false)]
|
||||||
|
// Parse the 4707 out of "goroutine 4707 ["
|
||||||
|
b = bytes.TrimPrefix(b, goroutineSpace)
|
||||||
|
i := bytes.IndexByte(b, ' ')
|
||||||
|
if i < 0 {
|
||||||
|
panic(fmt.Sprintf("No space found in %q", b))
|
||||||
|
}
|
||||||
|
b = b[:i]
|
||||||
|
n, err := parseUintBytes(b, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
var littleBuf = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
buf := make([]byte, 64)
|
||||||
|
return &buf
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseUintBytes is like strconv.ParseUint, but using a []byte.
|
||||||
|
func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
|
||||||
|
var cutoff, maxVal uint64
|
||||||
|
|
||||||
|
if bitSize == 0 {
|
||||||
|
bitSize = int(strconv.IntSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
s0 := s
|
||||||
|
switch {
|
||||||
|
case len(s) < 1:
|
||||||
|
err = strconv.ErrSyntax
|
||||||
|
goto Error
|
||||||
|
|
||||||
|
case 2 <= base && base <= 36:
|
||||||
|
// valid base; nothing to do
|
||||||
|
|
||||||
|
case base == 0:
|
||||||
|
// Look for octal, hex prefix.
|
||||||
|
switch {
|
||||||
|
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
|
||||||
|
base = 16
|
||||||
|
s = s[2:]
|
||||||
|
if len(s) < 1 {
|
||||||
|
err = strconv.ErrSyntax
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
case s[0] == '0':
|
||||||
|
base = 8
|
||||||
|
default:
|
||||||
|
base = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = errors.New("invalid base " + strconv.Itoa(base))
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
cutoff = cutoff64(base)
|
||||||
|
maxVal = 1<<uint(bitSize) - 1
|
||||||
|
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
var v byte
|
||||||
|
d := s[i]
|
||||||
|
switch {
|
||||||
|
case '0' <= d && d <= '9':
|
||||||
|
v = d - '0'
|
||||||
|
case 'a' <= d && d <= 'z':
|
||||||
|
v = d - 'a' + 10
|
||||||
|
case 'A' <= d && d <= 'Z':
|
||||||
|
v = d - 'A' + 10
|
||||||
|
default:
|
||||||
|
n = 0
|
||||||
|
err = strconv.ErrSyntax
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
if int(v) >= base {
|
||||||
|
n = 0
|
||||||
|
err = strconv.ErrSyntax
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if n >= cutoff {
|
||||||
|
// n*base overflows
|
||||||
|
n = 1<<64 - 1
|
||||||
|
err = strconv.ErrRange
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
n *= uint64(base)
|
||||||
|
|
||||||
|
n1 := n + uint64(v)
|
||||||
|
if n1 < n || n1 > maxVal {
|
||||||
|
// n+v overflows
|
||||||
|
n = 1<<64 - 1
|
||||||
|
err = strconv.ErrRange
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
|
n = n1
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
|
||||||
|
Error:
|
||||||
|
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the first number n such that n*base >= 1<<64.
|
||||||
|
func cutoff64(base int) uint64 {
|
||||||
|
if base < 2 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (1<<64-1)/uint64(base) + 1
|
||||||
|
}
|
495
vendor/golang.org/x/net/http2/h2c/h2c.go
generated
vendored
Normal file
495
vendor/golang.org/x/net/http2/h2c/h2c.go
generated
vendored
Normal file
|
@ -0,0 +1,495 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package h2c implements the unencrypted "h2c" form of HTTP/2.
|
||||||
|
//
|
||||||
|
// The h2c protocol is the non-TLS version of HTTP/2 which is not available from
|
||||||
|
// net/http or golang.org/x/net/http2.
|
||||||
|
package h2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
"golang.org/x/net/http2/hpack"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
http2VerboseLogs bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
e := os.Getenv("GODEBUG")
|
||||||
|
if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") {
|
||||||
|
http2VerboseLogs = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
|
||||||
|
// that should be h2c traffic. There are two ways to begin a h2c connection
|
||||||
|
// (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
|
||||||
|
// works by starting an h2c connection with a string of bytes that is valid
|
||||||
|
// HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
|
||||||
|
// h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
|
||||||
|
// h2c. When either of those situations occur we hijack the HTTP/1 connection,
|
||||||
|
// convert it to a HTTP/2 connection and pass the net.Conn to http2.ServeConn.
|
||||||
|
type h2cHandler struct {
|
||||||
|
Handler http.Handler
|
||||||
|
s *http2.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHandler returns an http.Handler that wraps h, intercepting any h2c
|
||||||
|
// traffic. If a request is an h2c connection, it's hijacked and redirected to
|
||||||
|
// s.ServeConn. Otherwise the returned Handler just forwards requests to h. This
|
||||||
|
// works because h2c is designed to be parseable as valid HTTP/1, but ignored by
|
||||||
|
// any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1
|
||||||
|
// compatible parts of the Go http library to parse and recognize h2c requests.
|
||||||
|
// Once a request is recognized as h2c, we hijack the connection and convert it
|
||||||
|
// to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn
|
||||||
|
// understands HTTP/2 except for the h2c part of it.)
|
||||||
|
func NewHandler(h http.Handler, s *http2.Server) http.Handler {
|
||||||
|
return &h2cHandler{
|
||||||
|
Handler: h,
|
||||||
|
s: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
|
||||||
|
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
|
||||||
|
if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" {
|
||||||
|
if http2VerboseLogs {
|
||||||
|
log.Print("h2c: attempting h2c with prior knowledge.")
|
||||||
|
}
|
||||||
|
conn, err := initH2CWithPriorKnowledge(w)
|
||||||
|
if err != nil {
|
||||||
|
if http2VerboseLogs {
|
||||||
|
log.Printf("h2c: error h2c with prior knowledge: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
s.s.ServeConn(conn, &http2.ServeConnOpts{Handler: s.Handler})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Handle Upgrade to h2c (RFC 7540 Section 3.2)
|
||||||
|
if conn, err := h2cUpgrade(w, r); err == nil {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
s.s.ServeConn(conn, &http2.ServeConnOpts{Handler: s.Handler})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// initH2CWithPriorKnowledge implements creating a h2c connection with prior
|
||||||
|
// knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn.
|
||||||
|
// All we have to do is look for the client preface that is suppose to be part
|
||||||
|
// of the body, and reforward the client preface on the net.Conn this function
|
||||||
|
// creates.
|
||||||
|
func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) {
|
||||||
|
hijacker, ok := w.(http.Hijacker)
|
||||||
|
if !ok {
|
||||||
|
panic("Hijack not supported.")
|
||||||
|
}
|
||||||
|
conn, rw, err := hijacker.Hijack()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Hijack failed: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
const expectedBody = "SM\r\n\r\n"
|
||||||
|
|
||||||
|
buf := make([]byte, len(expectedBody))
|
||||||
|
n, err := io.ReadFull(rw, buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read from the buffer: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(buf[:n]) == expectedBody {
|
||||||
|
c := &rwConn{
|
||||||
|
Conn: conn,
|
||||||
|
Reader: io.MultiReader(strings.NewReader(http2.ClientPreface), rw),
|
||||||
|
BufWriter: rw.Writer,
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
if http2VerboseLogs {
|
||||||
|
log.Printf(
|
||||||
|
"h2c: missing the request body portion of the client preface. Wanted: %v Got: %v",
|
||||||
|
[]byte(expectedBody),
|
||||||
|
buf[0:n],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid client preface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// drainClientPreface reads a single instance of the HTTP/2 client preface from
|
||||||
|
// the supplied reader.
|
||||||
|
func drainClientPreface(r io.Reader) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
prefaceLen := int64(len(http2.ClientPreface))
|
||||||
|
n, err := io.CopyN(&buf, r, prefaceLen)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if n != prefaceLen || buf.String() != http2.ClientPreface {
|
||||||
|
return fmt.Errorf("Client never sent: %s", http2.ClientPreface)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
|
||||||
|
func h2cUpgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
|
||||||
|
if !isH2CUpgrade(r.Header) {
|
||||||
|
return nil, errors.New("non-conforming h2c headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial bytes we put into conn to fool http2 server
|
||||||
|
initBytes, _, err := convertH1ReqToH2(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hijacker, ok := w.(http.Hijacker)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("hijack not supported.")
|
||||||
|
}
|
||||||
|
conn, rw, err := hijacker.Hijack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("hijack failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
|
||||||
|
"Connection: Upgrade\r\n" +
|
||||||
|
"Upgrade: h2c\r\n\r\n"))
|
||||||
|
rw.Flush()
|
||||||
|
|
||||||
|
// A conforming client will now send an H2 client preface which need to drain
|
||||||
|
// since we already sent this.
|
||||||
|
if err := drainClientPreface(rw); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &rwConn{
|
||||||
|
Conn: conn,
|
||||||
|
Reader: io.MultiReader(initBytes, rw),
|
||||||
|
BufWriter: newSettingsAckSwallowWriter(rw.Writer),
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the data contained in the HTTP/1 upgrade request into the HTTP/2
|
||||||
|
// version in byte form.
|
||||||
|
func convertH1ReqToH2(r *http.Request) (*bytes.Buffer, []http2.Setting, error) {
|
||||||
|
h2Bytes := bytes.NewBuffer([]byte((http2.ClientPreface)))
|
||||||
|
framer := http2.NewFramer(h2Bytes, nil)
|
||||||
|
settings, err := getH2Settings(r.Header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := framer.WriteSettings(settings...); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBytes, err := getH2HeaderBytes(r, getMaxHeaderTableSize(settings))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxFrameSize := int(getMaxFrameSize(settings))
|
||||||
|
needOneHeader := len(headerBytes) < maxFrameSize
|
||||||
|
err = framer.WriteHeaders(http2.HeadersFrameParam{
|
||||||
|
StreamID: 1,
|
||||||
|
BlockFragment: headerBytes,
|
||||||
|
EndHeaders: needOneHeader,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := maxFrameSize; i < len(headerBytes); i += maxFrameSize {
|
||||||
|
if len(headerBytes)-i > maxFrameSize {
|
||||||
|
if err := framer.WriteContinuation(1,
|
||||||
|
false, // endHeaders
|
||||||
|
headerBytes[i:maxFrameSize]); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := framer.WriteContinuation(1,
|
||||||
|
true, // endHeaders
|
||||||
|
headerBytes[i:]); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h2Bytes, settings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMaxFrameSize returns the SETTINGS_MAX_FRAME_SIZE. If not present default
|
||||||
|
// value is 16384 as specified by RFC 7540 Section 6.5.2.
|
||||||
|
func getMaxFrameSize(settings []http2.Setting) uint32 {
|
||||||
|
for _, setting := range settings {
|
||||||
|
if setting.ID == http2.SettingMaxFrameSize {
|
||||||
|
return setting.Val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 16384
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMaxHeaderTableSize returns the SETTINGS_HEADER_TABLE_SIZE. If not present
|
||||||
|
// default value is 4096 as specified by RFC 7540 Section 6.5.2.
|
||||||
|
func getMaxHeaderTableSize(settings []http2.Setting) uint32 {
|
||||||
|
for _, setting := range settings {
|
||||||
|
if setting.ID == http2.SettingHeaderTableSize {
|
||||||
|
return setting.Val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 4096
|
||||||
|
}
|
||||||
|
|
||||||
|
// bufWriter is a Writer interface that also has a Flush method.
|
||||||
|
type bufWriter interface {
|
||||||
|
io.Writer
|
||||||
|
Flush() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// rwConn implements net.Conn but overrides Read and Write so that reads and
|
||||||
|
// writes are forwarded to the provided io.Reader and bufWriter.
|
||||||
|
type rwConn struct {
|
||||||
|
net.Conn
|
||||||
|
io.Reader
|
||||||
|
BufWriter bufWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read forwards reads to the underlying Reader.
|
||||||
|
func (c *rwConn) Read(p []byte) (int, error) {
|
||||||
|
return c.Reader.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write forwards writes to the underlying bufWriter and immediately flushes.
|
||||||
|
func (c *rwConn) Write(p []byte) (int, error) {
|
||||||
|
n, err := c.BufWriter.Write(p)
|
||||||
|
if err := c.BufWriter.Flush(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// settingsAckSwallowWriter is a writer that normally forwards bytes to its
|
||||||
|
// underlying Writer, but swallows the first SettingsAck frame that it sees.
|
||||||
|
type settingsAckSwallowWriter struct {
|
||||||
|
Writer *bufio.Writer
|
||||||
|
buf []byte
|
||||||
|
didSwallow bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// newSettingsAckSwallowWriter returns a new settingsAckSwallowWriter.
|
||||||
|
func newSettingsAckSwallowWriter(w *bufio.Writer) *settingsAckSwallowWriter {
|
||||||
|
return &settingsAckSwallowWriter{
|
||||||
|
Writer: w,
|
||||||
|
buf: make([]byte, 0),
|
||||||
|
didSwallow: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements io.Writer interface. Normally forwards bytes to w.Writer,
|
||||||
|
// except for the first Settings ACK frame that it sees.
|
||||||
|
func (w *settingsAckSwallowWriter) Write(p []byte) (int, error) {
|
||||||
|
if !w.didSwallow {
|
||||||
|
w.buf = append(w.buf, p...)
|
||||||
|
// Process all the frames we have collected into w.buf
|
||||||
|
for {
|
||||||
|
// Append until we get full frame header which is 9 bytes
|
||||||
|
if len(w.buf) < 9 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Check if we have collected a whole frame.
|
||||||
|
fh, err := http2.ReadFrameHeader(bytes.NewBuffer(w.buf))
|
||||||
|
if err != nil {
|
||||||
|
// Corrupted frame, fail current Write
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
fSize := fh.Length + 9
|
||||||
|
if uint32(len(w.buf)) < fSize {
|
||||||
|
// Have not collected whole frame. Stop processing buf, and withold on
|
||||||
|
// forward bytes to w.Writer until we get the full frame.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have now collected a whole frame.
|
||||||
|
if fh.Type == http2.FrameSettings && fh.Flags.Has(http2.FlagSettingsAck) {
|
||||||
|
// If Settings ACK frame, do not forward to underlying writer, remove
|
||||||
|
// bytes from w.buf, and record that we have swallowed Settings Ack
|
||||||
|
// frame.
|
||||||
|
w.didSwallow = true
|
||||||
|
w.buf = w.buf[fSize:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not settings ack frame. Forward bytes to w.Writer.
|
||||||
|
if _, err := w.Writer.Write(w.buf[:fSize]); err != nil {
|
||||||
|
// Couldn't forward bytes. Fail current Write.
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
w.buf = w.buf[fSize:]
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
return w.Writer.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush calls w.Writer.Flush.
|
||||||
|
func (w *settingsAckSwallowWriter) Flush() error {
|
||||||
|
return w.Writer.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isH2CUpgrade returns true if the header properly request an upgrade to h2c
|
||||||
|
// as specified by Section 3.2.
|
||||||
|
func isH2CUpgrade(h http.Header) bool {
|
||||||
|
return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
|
||||||
|
httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getH2Settings returns the []http2.Setting that are encoded in the
|
||||||
|
// HTTP2-Settings header.
|
||||||
|
func getH2Settings(h http.Header) ([]http2.Setting, error) {
|
||||||
|
vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("missing HTTP2-Settings header")
|
||||||
|
}
|
||||||
|
if len(vals) != 1 {
|
||||||
|
return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
|
||||||
|
}
|
||||||
|
settings, err := decodeSettings(vals[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid HTTP2-Settings: %q", vals[0])
|
||||||
|
}
|
||||||
|
return settings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeSettings decodes the base64url header value of the HTTP2-Settings
|
||||||
|
// header. RFC 7540 Section 3.2.1.
|
||||||
|
func decodeSettings(headerVal string) ([]http2.Setting, error) {
|
||||||
|
b, err := base64.RawURLEncoding.DecodeString(headerVal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(b)%6 != 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
settings := make([]http2.Setting, 0)
|
||||||
|
for i := 0; i < len(b)/6; i++ {
|
||||||
|
settings = append(settings, http2.Setting{
|
||||||
|
ID: http2.SettingID(binary.BigEndian.Uint16(b[i*6 : i*6+2])),
|
||||||
|
Val: binary.BigEndian.Uint32(b[i*6+2 : i*6+6]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getH2HeaderBytes return the headers in r a []bytes encoded by HPACK.
|
||||||
|
func getH2HeaderBytes(r *http.Request, maxHeaderTableSize uint32) ([]byte, error) {
|
||||||
|
headerBytes := bytes.NewBuffer(nil)
|
||||||
|
hpackEnc := hpack.NewEncoder(headerBytes)
|
||||||
|
hpackEnc.SetMaxDynamicTableSize(maxHeaderTableSize)
|
||||||
|
|
||||||
|
// Section 8.1.2.3
|
||||||
|
err := hpackEnc.WriteField(hpack.HeaderField{
|
||||||
|
Name: ":method",
|
||||||
|
Value: r.Method,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hpackEnc.WriteField(hpack.HeaderField{
|
||||||
|
Name: ":scheme",
|
||||||
|
Value: "http",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hpackEnc.WriteField(hpack.HeaderField{
|
||||||
|
Name: ":authority",
|
||||||
|
Value: r.Host,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := r.URL.Path
|
||||||
|
if r.URL.RawQuery != "" {
|
||||||
|
path = strings.Join([]string{path, r.URL.RawQuery}, "?")
|
||||||
|
}
|
||||||
|
err = hpackEnc.WriteField(hpack.HeaderField{
|
||||||
|
Name: ":path",
|
||||||
|
Value: path,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Implement Section 8.3
|
||||||
|
|
||||||
|
for header, values := range r.Header {
|
||||||
|
// Skip non h2 headers
|
||||||
|
if isNonH2Header(header) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, v := range values {
|
||||||
|
err := hpackEnc.WriteField(hpack.HeaderField{
|
||||||
|
Name: strings.ToLower(header),
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headerBytes.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection specific headers listed in RFC 7540 Section 8.1.2.2 that are not
|
||||||
|
// suppose to be transferred to HTTP/2. The Http2-Settings header is skipped
|
||||||
|
// since already use to create the HTTP/2 SETTINGS frame.
|
||||||
|
var nonH2Headers = []string{
|
||||||
|
"Connection",
|
||||||
|
"Keep-Alive",
|
||||||
|
"Proxy-Connection",
|
||||||
|
"Transfer-Encoding",
|
||||||
|
"Upgrade",
|
||||||
|
"Http2-Settings",
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNonH2Header returns true if header should not be transferred to HTTP/2.
|
||||||
|
func isNonH2Header(header string) bool {
|
||||||
|
for _, nonH2h := range nonH2Headers {
|
||||||
|
if header == nonH2h {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
88
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
Normal file
88
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
commonBuildOnce sync.Once
|
||||||
|
commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
|
||||||
|
commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildCommonHeaderMapsOnce() {
|
||||||
|
commonBuildOnce.Do(buildCommonHeaderMaps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCommonHeaderMaps() {
|
||||||
|
common := []string{
|
||||||
|
"accept",
|
||||||
|
"accept-charset",
|
||||||
|
"accept-encoding",
|
||||||
|
"accept-language",
|
||||||
|
"accept-ranges",
|
||||||
|
"age",
|
||||||
|
"access-control-allow-origin",
|
||||||
|
"allow",
|
||||||
|
"authorization",
|
||||||
|
"cache-control",
|
||||||
|
"content-disposition",
|
||||||
|
"content-encoding",
|
||||||
|
"content-language",
|
||||||
|
"content-length",
|
||||||
|
"content-location",
|
||||||
|
"content-range",
|
||||||
|
"content-type",
|
||||||
|
"cookie",
|
||||||
|
"date",
|
||||||
|
"etag",
|
||||||
|
"expect",
|
||||||
|
"expires",
|
||||||
|
"from",
|
||||||
|
"host",
|
||||||
|
"if-match",
|
||||||
|
"if-modified-since",
|
||||||
|
"if-none-match",
|
||||||
|
"if-unmodified-since",
|
||||||
|
"last-modified",
|
||||||
|
"link",
|
||||||
|
"location",
|
||||||
|
"max-forwards",
|
||||||
|
"proxy-authenticate",
|
||||||
|
"proxy-authorization",
|
||||||
|
"range",
|
||||||
|
"referer",
|
||||||
|
"refresh",
|
||||||
|
"retry-after",
|
||||||
|
"server",
|
||||||
|
"set-cookie",
|
||||||
|
"strict-transport-security",
|
||||||
|
"trailer",
|
||||||
|
"transfer-encoding",
|
||||||
|
"user-agent",
|
||||||
|
"vary",
|
||||||
|
"via",
|
||||||
|
"www-authenticate",
|
||||||
|
}
|
||||||
|
commonLowerHeader = make(map[string]string, len(common))
|
||||||
|
commonCanonHeader = make(map[string]string, len(common))
|
||||||
|
for _, v := range common {
|
||||||
|
chk := http.CanonicalHeaderKey(v)
|
||||||
|
commonLowerHeader[chk] = v
|
||||||
|
commonCanonHeader[v] = chk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lowerHeader(v string) string {
|
||||||
|
buildCommonHeaderMapsOnce()
|
||||||
|
if s, ok := commonLowerHeader[v]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return strings.ToLower(v)
|
||||||
|
}
|
240
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
Normal file
240
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
uint32Max = ^uint32(0)
|
||||||
|
initialHeaderTableSize = 4096
|
||||||
|
)
|
||||||
|
|
||||||
|
type Encoder struct {
|
||||||
|
dynTab dynamicTable
|
||||||
|
// minSize is the minimum table size set by
|
||||||
|
// SetMaxDynamicTableSize after the previous Header Table Size
|
||||||
|
// Update.
|
||||||
|
minSize uint32
|
||||||
|
// maxSizeLimit is the maximum table size this encoder
|
||||||
|
// supports. This will protect the encoder from too large
|
||||||
|
// size.
|
||||||
|
maxSizeLimit uint32
|
||||||
|
// tableSizeUpdate indicates whether "Header Table Size
|
||||||
|
// Update" is required.
|
||||||
|
tableSizeUpdate bool
|
||||||
|
w io.Writer
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEncoder returns a new Encoder which performs HPACK encoding. An
|
||||||
|
// encoded data is written to w.
|
||||||
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
|
e := &Encoder{
|
||||||
|
minSize: uint32Max,
|
||||||
|
maxSizeLimit: initialHeaderTableSize,
|
||||||
|
tableSizeUpdate: false,
|
||||||
|
w: w,
|
||||||
|
}
|
||||||
|
e.dynTab.table.init()
|
||||||
|
e.dynTab.setMaxSize(initialHeaderTableSize)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteField encodes f into a single Write to e's underlying Writer.
|
||||||
|
// This function may also produce bytes for "Header Table Size Update"
|
||||||
|
// if necessary. If produced, it is done before encoding f.
|
||||||
|
func (e *Encoder) WriteField(f HeaderField) error {
|
||||||
|
e.buf = e.buf[:0]
|
||||||
|
|
||||||
|
if e.tableSizeUpdate {
|
||||||
|
e.tableSizeUpdate = false
|
||||||
|
if e.minSize < e.dynTab.maxSize {
|
||||||
|
e.buf = appendTableSize(e.buf, e.minSize)
|
||||||
|
}
|
||||||
|
e.minSize = uint32Max
|
||||||
|
e.buf = appendTableSize(e.buf, e.dynTab.maxSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
idx, nameValueMatch := e.searchTable(f)
|
||||||
|
if nameValueMatch {
|
||||||
|
e.buf = appendIndexed(e.buf, idx)
|
||||||
|
} else {
|
||||||
|
indexing := e.shouldIndex(f)
|
||||||
|
if indexing {
|
||||||
|
e.dynTab.add(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx == 0 {
|
||||||
|
e.buf = appendNewName(e.buf, f, indexing)
|
||||||
|
} else {
|
||||||
|
e.buf = appendIndexedName(e.buf, f, idx, indexing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n, err := e.w.Write(e.buf)
|
||||||
|
if err == nil && n != len(e.buf) {
|
||||||
|
err = io.ErrShortWrite
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// searchTable searches f in both stable and dynamic header tables.
|
||||||
|
// The static header table is searched first. Only when there is no
|
||||||
|
// exact match for both name and value, the dynamic header table is
|
||||||
|
// then searched. If there is no match, i is 0. If both name and value
|
||||||
|
// match, i is the matched index and nameValueMatch becomes true. If
|
||||||
|
// only name matches, i points to that index and nameValueMatch
|
||||||
|
// becomes false.
|
||||||
|
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
|
||||||
|
i, nameValueMatch = staticTable.search(f)
|
||||||
|
if nameValueMatch {
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
|
||||||
|
j, nameValueMatch := e.dynTab.table.search(f)
|
||||||
|
if nameValueMatch || (i == 0 && j != 0) {
|
||||||
|
return j + uint64(staticTable.len()), nameValueMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
return i, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMaxDynamicTableSize changes the dynamic header table size to v.
|
||||||
|
// The actual size is bounded by the value passed to
|
||||||
|
// SetMaxDynamicTableSizeLimit.
|
||||||
|
func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
|
||||||
|
if v > e.maxSizeLimit {
|
||||||
|
v = e.maxSizeLimit
|
||||||
|
}
|
||||||
|
if v < e.minSize {
|
||||||
|
e.minSize = v
|
||||||
|
}
|
||||||
|
e.tableSizeUpdate = true
|
||||||
|
e.dynTab.setMaxSize(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMaxDynamicTableSizeLimit changes the maximum value that can be
|
||||||
|
// specified in SetMaxDynamicTableSize to v. By default, it is set to
|
||||||
|
// 4096, which is the same size of the default dynamic header table
|
||||||
|
// size described in HPACK specification. If the current maximum
|
||||||
|
// dynamic header table size is strictly greater than v, "Header Table
|
||||||
|
// Size Update" will be done in the next WriteField call and the
|
||||||
|
// maximum dynamic header table size is truncated to v.
|
||||||
|
func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
|
||||||
|
e.maxSizeLimit = v
|
||||||
|
if e.dynTab.maxSize > v {
|
||||||
|
e.tableSizeUpdate = true
|
||||||
|
e.dynTab.setMaxSize(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shouldIndex reports whether f should be indexed.
|
||||||
|
func (e *Encoder) shouldIndex(f HeaderField) bool {
|
||||||
|
return !f.Sensitive && f.Size() <= e.dynTab.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendIndexed appends index i, as encoded in "Indexed Header Field"
|
||||||
|
// representation, to dst and returns the extended buffer.
|
||||||
|
func appendIndexed(dst []byte, i uint64) []byte {
|
||||||
|
first := len(dst)
|
||||||
|
dst = appendVarInt(dst, 7, i)
|
||||||
|
dst[first] |= 0x80
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendNewName appends f, as encoded in one of "Literal Header field
|
||||||
|
// - New Name" representation variants, to dst and returns the
|
||||||
|
// extended buffer.
|
||||||
|
//
|
||||||
|
// If f.Sensitive is true, "Never Indexed" representation is used. If
|
||||||
|
// f.Sensitive is false and indexing is true, "Incremental Indexing"
|
||||||
|
// representation is used.
|
||||||
|
func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
|
||||||
|
dst = append(dst, encodeTypeByte(indexing, f.Sensitive))
|
||||||
|
dst = appendHpackString(dst, f.Name)
|
||||||
|
return appendHpackString(dst, f.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendIndexedName appends f and index i referring indexed name
|
||||||
|
// entry, as encoded in one of "Literal Header field - Indexed Name"
|
||||||
|
// representation variants, to dst and returns the extended buffer.
|
||||||
|
//
|
||||||
|
// If f.Sensitive is true, "Never Indexed" representation is used. If
|
||||||
|
// f.Sensitive is false and indexing is true, "Incremental Indexing"
|
||||||
|
// representation is used.
|
||||||
|
func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte {
|
||||||
|
first := len(dst)
|
||||||
|
var n byte
|
||||||
|
if indexing {
|
||||||
|
n = 6
|
||||||
|
} else {
|
||||||
|
n = 4
|
||||||
|
}
|
||||||
|
dst = appendVarInt(dst, n, i)
|
||||||
|
dst[first] |= encodeTypeByte(indexing, f.Sensitive)
|
||||||
|
return appendHpackString(dst, f.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendTableSize appends v, as encoded in "Header Table Size Update"
|
||||||
|
// representation, to dst and returns the extended buffer.
|
||||||
|
func appendTableSize(dst []byte, v uint32) []byte {
|
||||||
|
first := len(dst)
|
||||||
|
dst = appendVarInt(dst, 5, uint64(v))
|
||||||
|
dst[first] |= 0x20
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendVarInt appends i, as encoded in variable integer form using n
|
||||||
|
// bit prefix, to dst and returns the extended buffer.
|
||||||
|
//
|
||||||
|
// See
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#integer.representation
|
||||||
|
func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
||||||
|
k := uint64((1 << n) - 1)
|
||||||
|
if i < k {
|
||||||
|
return append(dst, byte(i))
|
||||||
|
}
|
||||||
|
dst = append(dst, byte(k))
|
||||||
|
i -= k
|
||||||
|
for ; i >= 128; i >>= 7 {
|
||||||
|
dst = append(dst, byte(0x80|(i&0x7f)))
|
||||||
|
}
|
||||||
|
return append(dst, byte(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendHpackString appends s, as encoded in "String Literal"
|
||||||
|
// representation, to dst and returns the extended buffer.
|
||||||
|
//
|
||||||
|
// s will be encoded in Huffman codes only when it produces strictly
|
||||||
|
// shorter byte string.
|
||||||
|
func appendHpackString(dst []byte, s string) []byte {
|
||||||
|
huffmanLength := HuffmanEncodeLength(s)
|
||||||
|
if huffmanLength < uint64(len(s)) {
|
||||||
|
first := len(dst)
|
||||||
|
dst = appendVarInt(dst, 7, huffmanLength)
|
||||||
|
dst = AppendHuffmanString(dst, s)
|
||||||
|
dst[first] |= 0x80
|
||||||
|
} else {
|
||||||
|
dst = appendVarInt(dst, 7, uint64(len(s)))
|
||||||
|
dst = append(dst, s...)
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeTypeByte returns type byte. If sensitive is true, type byte
|
||||||
|
// for "Never Indexed" representation is returned. If sensitive is
|
||||||
|
// false and indexing is true, type byte for "Incremental Indexing"
|
||||||
|
// representation is returned. Otherwise, type byte for "Without
|
||||||
|
// Indexing" is returned.
|
||||||
|
func encodeTypeByte(indexing, sensitive bool) byte {
|
||||||
|
if sensitive {
|
||||||
|
return 0x10
|
||||||
|
}
|
||||||
|
if indexing {
|
||||||
|
return 0x40
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
504
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
Normal file
504
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
Normal file
|
@ -0,0 +1,504 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package hpack implements HPACK, a compression format for
|
||||||
|
// efficiently representing HTTP header fields in the context of HTTP/2.
|
||||||
|
//
|
||||||
|
// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A DecodingError is something the spec defines as a decoding error.
|
||||||
|
type DecodingError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (de DecodingError) Error() string {
|
||||||
|
return fmt.Sprintf("decoding error: %v", de.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An InvalidIndexError is returned when an encoder references a table
|
||||||
|
// entry before the static table or after the end of the dynamic table.
|
||||||
|
type InvalidIndexError int
|
||||||
|
|
||||||
|
func (e InvalidIndexError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid indexed representation index %d", int(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A HeaderField is a name-value pair. Both the name and value are
|
||||||
|
// treated as opaque sequences of octets.
|
||||||
|
type HeaderField struct {
|
||||||
|
Name, Value string
|
||||||
|
|
||||||
|
// Sensitive means that this header field should never be
|
||||||
|
// indexed.
|
||||||
|
Sensitive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPseudo reports whether the header field is an http2 pseudo header.
|
||||||
|
// That is, it reports whether it starts with a colon.
|
||||||
|
// It is not otherwise guaranteed to be a valid pseudo header field,
|
||||||
|
// though.
|
||||||
|
func (hf HeaderField) IsPseudo() bool {
|
||||||
|
return len(hf.Name) != 0 && hf.Name[0] == ':'
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hf HeaderField) String() string {
|
||||||
|
var suffix string
|
||||||
|
if hf.Sensitive {
|
||||||
|
suffix = " (sensitive)"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the size of an entry per RFC 7541 section 4.1.
|
||||||
|
func (hf HeaderField) Size() uint32 {
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
|
||||||
|
// "The size of the dynamic table is the sum of the size of
|
||||||
|
// its entries. The size of an entry is the sum of its name's
|
||||||
|
// length in octets (as defined in Section 5.2), its value's
|
||||||
|
// length in octets (see Section 5.2), plus 32. The size of
|
||||||
|
// an entry is calculated using the length of the name and
|
||||||
|
// value without any Huffman encoding applied."
|
||||||
|
|
||||||
|
// This can overflow if somebody makes a large HeaderField
|
||||||
|
// Name and/or Value by hand, but we don't care, because that
|
||||||
|
// won't happen on the wire because the encoding doesn't allow
|
||||||
|
// it.
|
||||||
|
return uint32(len(hf.Name) + len(hf.Value) + 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Decoder is the decoding context for incremental processing of
|
||||||
|
// header blocks.
|
||||||
|
type Decoder struct {
|
||||||
|
dynTab dynamicTable
|
||||||
|
emit func(f HeaderField)
|
||||||
|
|
||||||
|
emitEnabled bool // whether calls to emit are enabled
|
||||||
|
maxStrLen int // 0 means unlimited
|
||||||
|
|
||||||
|
// buf is the unparsed buffer. It's only written to
|
||||||
|
// saveBuf if it was truncated in the middle of a header
|
||||||
|
// block. Because it's usually not owned, we can only
|
||||||
|
// process it under Write.
|
||||||
|
buf []byte // not owned; only valid during Write
|
||||||
|
|
||||||
|
// saveBuf is previous data passed to Write which we weren't able
|
||||||
|
// to fully parse before. Unlike buf, we own this data.
|
||||||
|
saveBuf bytes.Buffer
|
||||||
|
|
||||||
|
firstField bool // processing the first field of the header block
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoder returns a new decoder with the provided maximum dynamic
|
||||||
|
// table size. The emitFunc will be called for each valid field
|
||||||
|
// parsed, in the same goroutine as calls to Write, before Write returns.
|
||||||
|
func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder {
|
||||||
|
d := &Decoder{
|
||||||
|
emit: emitFunc,
|
||||||
|
emitEnabled: true,
|
||||||
|
firstField: true,
|
||||||
|
}
|
||||||
|
d.dynTab.table.init()
|
||||||
|
d.dynTab.allowedMaxSize = maxDynamicTableSize
|
||||||
|
d.dynTab.setMaxSize(maxDynamicTableSize)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrStringLength is returned by Decoder.Write when the max string length
|
||||||
|
// (as configured by Decoder.SetMaxStringLength) would be violated.
|
||||||
|
var ErrStringLength = errors.New("hpack: string too long")
|
||||||
|
|
||||||
|
// SetMaxStringLength sets the maximum size of a HeaderField name or
|
||||||
|
// value string. If a string exceeds this length (even after any
|
||||||
|
// decompression), Write will return ErrStringLength.
|
||||||
|
// A value of 0 means unlimited and is the default from NewDecoder.
|
||||||
|
func (d *Decoder) SetMaxStringLength(n int) {
|
||||||
|
d.maxStrLen = n
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEmitFunc changes the callback used when new header fields
|
||||||
|
// are decoded.
|
||||||
|
// It must be non-nil. It does not affect EmitEnabled.
|
||||||
|
func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) {
|
||||||
|
d.emit = emitFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEmitEnabled controls whether the emitFunc provided to NewDecoder
|
||||||
|
// should be called. The default is true.
|
||||||
|
//
|
||||||
|
// This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
|
||||||
|
// while still decoding and keeping in-sync with decoder state, but
|
||||||
|
// without doing unnecessary decompression or generating unnecessary
|
||||||
|
// garbage for header fields past the limit.
|
||||||
|
func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v }
|
||||||
|
|
||||||
|
// EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
|
||||||
|
// are currently enabled. The default is true.
|
||||||
|
func (d *Decoder) EmitEnabled() bool { return d.emitEnabled }
|
||||||
|
|
||||||
|
// TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
|
||||||
|
// underlying buffers for garbage reasons.
|
||||||
|
|
||||||
|
func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
|
||||||
|
d.dynTab.setMaxSize(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
|
||||||
|
// stream (via dynamic table size updates) may set the maximum size
|
||||||
|
// to.
|
||||||
|
func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
|
||||||
|
d.dynTab.allowedMaxSize = v
|
||||||
|
}
|
||||||
|
|
||||||
|
type dynamicTable struct {
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
|
||||||
|
table headerFieldTable
|
||||||
|
size uint32 // in bytes
|
||||||
|
maxSize uint32 // current maxSize
|
||||||
|
allowedMaxSize uint32 // maxSize may go up to this, inclusive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt *dynamicTable) setMaxSize(v uint32) {
|
||||||
|
dt.maxSize = v
|
||||||
|
dt.evict()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt *dynamicTable) add(f HeaderField) {
|
||||||
|
dt.table.addEntry(f)
|
||||||
|
dt.size += f.Size()
|
||||||
|
dt.evict()
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're too big, evict old stuff.
|
||||||
|
func (dt *dynamicTable) evict() {
|
||||||
|
var n int
|
||||||
|
for dt.size > dt.maxSize && n < dt.table.len() {
|
||||||
|
dt.size -= dt.table.ents[n].Size()
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
dt.table.evictOldest(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) maxTableIndex() int {
|
||||||
|
// This should never overflow. RFC 7540 Section 6.5.2 limits the size of
|
||||||
|
// the dynamic table to 2^32 bytes, where each entry will occupy more than
|
||||||
|
// one byte. Further, the staticTable has a fixed, small length.
|
||||||
|
return d.dynTab.table.len() + staticTable.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
|
||||||
|
// See Section 2.3.3.
|
||||||
|
if i == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if i <= uint64(staticTable.len()) {
|
||||||
|
return staticTable.ents[i-1], true
|
||||||
|
}
|
||||||
|
if i > uint64(d.maxTableIndex()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// In the dynamic table, newer entries have lower indices.
|
||||||
|
// However, dt.ents[0] is the oldest entry. Hence, dt.ents is
|
||||||
|
// the reversed dynamic table.
|
||||||
|
dt := d.dynTab.table
|
||||||
|
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes an entire block.
|
||||||
|
//
|
||||||
|
// TODO: remove this method and make it incremental later? This is
|
||||||
|
// easier for debugging now.
|
||||||
|
func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
|
||||||
|
var hf []HeaderField
|
||||||
|
saveFunc := d.emit
|
||||||
|
defer func() { d.emit = saveFunc }()
|
||||||
|
d.emit = func(f HeaderField) { hf = append(hf, f) }
|
||||||
|
if _, err := d.Write(p); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := d.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close declares that the decoding is complete and resets the Decoder
|
||||||
|
// to be reused again for a new header block. If there is any remaining
|
||||||
|
// data in the decoder's buffer, Close returns an error.
|
||||||
|
func (d *Decoder) Close() error {
|
||||||
|
if d.saveBuf.Len() > 0 {
|
||||||
|
d.saveBuf.Reset()
|
||||||
|
return DecodingError{errors.New("truncated headers")}
|
||||||
|
}
|
||||||
|
d.firstField = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) Write(p []byte) (n int, err error) {
|
||||||
|
if len(p) == 0 {
|
||||||
|
// Prevent state machine CPU attacks (making us redo
|
||||||
|
// work up to the point of finding out we don't have
|
||||||
|
// enough data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Only copy the data if we have to. Optimistically assume
|
||||||
|
// that p will contain a complete header block.
|
||||||
|
if d.saveBuf.Len() == 0 {
|
||||||
|
d.buf = p
|
||||||
|
} else {
|
||||||
|
d.saveBuf.Write(p)
|
||||||
|
d.buf = d.saveBuf.Bytes()
|
||||||
|
d.saveBuf.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(d.buf) > 0 {
|
||||||
|
err = d.parseHeaderFieldRepr()
|
||||||
|
if err == errNeedMore {
|
||||||
|
// Extra paranoia, making sure saveBuf won't
|
||||||
|
// get too large. All the varint and string
|
||||||
|
// reading code earlier should already catch
|
||||||
|
// overlong things and return ErrStringLength,
|
||||||
|
// but keep this as a last resort.
|
||||||
|
const varIntOverhead = 8 // conservative
|
||||||
|
if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
|
||||||
|
return 0, ErrStringLength
|
||||||
|
}
|
||||||
|
d.saveBuf.Write(d.buf)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
d.firstField = false
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(p), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// errNeedMore is an internal sentinel error value that means the
|
||||||
|
// buffer is truncated and we need to read more data before we can
|
||||||
|
// continue parsing.
|
||||||
|
var errNeedMore = errors.New("need more data")
|
||||||
|
|
||||||
|
type indexType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
indexedTrue indexType = iota
|
||||||
|
indexedFalse
|
||||||
|
indexedNever
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v indexType) indexed() bool { return v == indexedTrue }
|
||||||
|
func (v indexType) sensitive() bool { return v == indexedNever }
|
||||||
|
|
||||||
|
// returns errNeedMore if there isn't enough data available.
|
||||||
|
// any other error is fatal.
|
||||||
|
// consumes d.buf iff it returns nil.
|
||||||
|
// precondition: must be called with len(d.buf) > 0
|
||||||
|
func (d *Decoder) parseHeaderFieldRepr() error {
|
||||||
|
b := d.buf[0]
|
||||||
|
switch {
|
||||||
|
case b&128 != 0:
|
||||||
|
// Indexed representation.
|
||||||
|
// High bit set?
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
|
||||||
|
return d.parseFieldIndexed()
|
||||||
|
case b&192 == 64:
|
||||||
|
// 6.2.1 Literal Header Field with Incremental Indexing
|
||||||
|
// 0b10xxxxxx: top two bits are 10
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
|
||||||
|
return d.parseFieldLiteral(6, indexedTrue)
|
||||||
|
case b&240 == 0:
|
||||||
|
// 6.2.2 Literal Header Field without Indexing
|
||||||
|
// 0b0000xxxx: top four bits are 0000
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
|
||||||
|
return d.parseFieldLiteral(4, indexedFalse)
|
||||||
|
case b&240 == 16:
|
||||||
|
// 6.2.3 Literal Header Field never Indexed
|
||||||
|
// 0b0001xxxx: top four bits are 0001
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
|
||||||
|
return d.parseFieldLiteral(4, indexedNever)
|
||||||
|
case b&224 == 32:
|
||||||
|
// 6.3 Dynamic Table Size Update
|
||||||
|
// Top three bits are '001'.
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
|
||||||
|
return d.parseDynamicTableSizeUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecodingError{errors.New("invalid encoding")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// (same invariants and behavior as parseHeaderFieldRepr)
|
||||||
|
func (d *Decoder) parseFieldIndexed() error {
|
||||||
|
buf := d.buf
|
||||||
|
idx, buf, err := readVarInt(7, buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hf, ok := d.at(idx)
|
||||||
|
if !ok {
|
||||||
|
return DecodingError{InvalidIndexError(idx)}
|
||||||
|
}
|
||||||
|
d.buf = buf
|
||||||
|
return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value})
|
||||||
|
}
|
||||||
|
|
||||||
|
// (same invariants and behavior as parseHeaderFieldRepr)
|
||||||
|
func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
|
||||||
|
buf := d.buf
|
||||||
|
nameIdx, buf, err := readVarInt(n, buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var hf HeaderField
|
||||||
|
wantStr := d.emitEnabled || it.indexed()
|
||||||
|
if nameIdx > 0 {
|
||||||
|
ihf, ok := d.at(nameIdx)
|
||||||
|
if !ok {
|
||||||
|
return DecodingError{InvalidIndexError(nameIdx)}
|
||||||
|
}
|
||||||
|
hf.Name = ihf.Name
|
||||||
|
} else {
|
||||||
|
hf.Name, buf, err = d.readString(buf, wantStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hf.Value, buf, err = d.readString(buf, wantStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.buf = buf
|
||||||
|
if it.indexed() {
|
||||||
|
d.dynTab.add(hf)
|
||||||
|
}
|
||||||
|
hf.Sensitive = it.sensitive()
|
||||||
|
return d.callEmit(hf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) callEmit(hf HeaderField) error {
|
||||||
|
if d.maxStrLen != 0 {
|
||||||
|
if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen {
|
||||||
|
return ErrStringLength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.emitEnabled {
|
||||||
|
d.emit(hf)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// (same invariants and behavior as parseHeaderFieldRepr)
|
||||||
|
func (d *Decoder) parseDynamicTableSizeUpdate() error {
|
||||||
|
// RFC 7541, sec 4.2: This dynamic table size update MUST occur at the
|
||||||
|
// beginning of the first header block following the change to the dynamic table size.
|
||||||
|
if !d.firstField && d.dynTab.size > 0 {
|
||||||
|
return DecodingError{errors.New("dynamic table size update MUST occur at the beginning of a header block")}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := d.buf
|
||||||
|
size, buf, err := readVarInt(5, buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if size > uint64(d.dynTab.allowedMaxSize) {
|
||||||
|
return DecodingError{errors.New("dynamic table size update too large")}
|
||||||
|
}
|
||||||
|
d.dynTab.setMaxSize(uint32(size))
|
||||||
|
d.buf = buf
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
|
||||||
|
|
||||||
|
// readVarInt reads an unsigned variable length integer off the
|
||||||
|
// beginning of p. n is the parameter as described in
|
||||||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
|
||||||
|
//
|
||||||
|
// n must always be between 1 and 8.
|
||||||
|
//
|
||||||
|
// The returned remain buffer is either a smaller suffix of p, or err != nil.
|
||||||
|
// The error is errNeedMore if p doesn't contain a complete integer.
|
||||||
|
func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
|
||||||
|
if n < 1 || n > 8 {
|
||||||
|
panic("bad n")
|
||||||
|
}
|
||||||
|
if len(p) == 0 {
|
||||||
|
return 0, p, errNeedMore
|
||||||
|
}
|
||||||
|
i = uint64(p[0])
|
||||||
|
if n < 8 {
|
||||||
|
i &= (1 << uint64(n)) - 1
|
||||||
|
}
|
||||||
|
if i < (1<<uint64(n))-1 {
|
||||||
|
return i, p[1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
origP := p
|
||||||
|
p = p[1:]
|
||||||
|
var m uint64
|
||||||
|
for len(p) > 0 {
|
||||||
|
b := p[0]
|
||||||
|
p = p[1:]
|
||||||
|
i += uint64(b&127) << m
|
||||||
|
if b&128 == 0 {
|
||||||
|
return i, p, nil
|
||||||
|
}
|
||||||
|
m += 7
|
||||||
|
if m >= 63 { // TODO: proper overflow check. making this up.
|
||||||
|
return 0, origP, errVarintOverflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, origP, errNeedMore
|
||||||
|
}
|
||||||
|
|
||||||
|
// readString decodes an hpack string from p.
|
||||||
|
//
|
||||||
|
// wantStr is whether s will be used. If false, decompression and
|
||||||
|
// []byte->string garbage are skipped if s will be ignored
|
||||||
|
// anyway. This does mean that huffman decoding errors for non-indexed
|
||||||
|
// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
|
||||||
|
// is returning an error anyway, and because they're not indexed, the error
|
||||||
|
// won't affect the decoding state.
|
||||||
|
func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return "", p, errNeedMore
|
||||||
|
}
|
||||||
|
isHuff := p[0]&128 != 0
|
||||||
|
strLen, p, err := readVarInt(7, p)
|
||||||
|
if err != nil {
|
||||||
|
return "", p, err
|
||||||
|
}
|
||||||
|
if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
|
||||||
|
return "", nil, ErrStringLength
|
||||||
|
}
|
||||||
|
if uint64(len(p)) < strLen {
|
||||||
|
return "", p, errNeedMore
|
||||||
|
}
|
||||||
|
if !isHuff {
|
||||||
|
if wantStr {
|
||||||
|
s = string(p[:strLen])
|
||||||
|
}
|
||||||
|
return s, p[strLen:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if wantStr {
|
||||||
|
buf := bufPool.Get().(*bytes.Buffer)
|
||||||
|
buf.Reset() // don't trust others
|
||||||
|
defer bufPool.Put(buf)
|
||||||
|
if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
|
||||||
|
buf.Reset()
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
s = buf.String()
|
||||||
|
buf.Reset() // be nice to GC
|
||||||
|
}
|
||||||
|
return s, p[strLen:], nil
|
||||||
|
}
|
222
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
Normal file
222
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var bufPool = sync.Pool{
|
||||||
|
New: func() interface{} { return new(bytes.Buffer) },
|
||||||
|
}
|
||||||
|
|
||||||
|
// HuffmanDecode decodes the string in v and writes the expanded
|
||||||
|
// result to w, returning the number of bytes written to w and the
|
||||||
|
// Write call's return value. At most one Write call is made.
|
||||||
|
func HuffmanDecode(w io.Writer, v []byte) (int, error) {
|
||||||
|
buf := bufPool.Get().(*bytes.Buffer)
|
||||||
|
buf.Reset()
|
||||||
|
defer bufPool.Put(buf)
|
||||||
|
if err := huffmanDecode(buf, 0, v); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return w.Write(buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// HuffmanDecodeToString decodes the string in v.
|
||||||
|
func HuffmanDecodeToString(v []byte) (string, error) {
|
||||||
|
buf := bufPool.Get().(*bytes.Buffer)
|
||||||
|
buf.Reset()
|
||||||
|
defer bufPool.Put(buf)
|
||||||
|
if err := huffmanDecode(buf, 0, v); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrInvalidHuffman is returned for errors found decoding
|
||||||
|
// Huffman-encoded strings.
|
||||||
|
var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
|
||||||
|
|
||||||
|
// huffmanDecode decodes v to buf.
|
||||||
|
// If maxLen is greater than 0, attempts to write more to buf than
|
||||||
|
// maxLen bytes will return ErrStringLength.
|
||||||
|
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
||||||
|
rootHuffmanNode := getRootHuffmanNode()
|
||||||
|
n := rootHuffmanNode
|
||||||
|
// cur is the bit buffer that has not been fed into n.
|
||||||
|
// cbits is the number of low order bits in cur that are valid.
|
||||||
|
// sbits is the number of bits of the symbol prefix being decoded.
|
||||||
|
cur, cbits, sbits := uint(0), uint8(0), uint8(0)
|
||||||
|
for _, b := range v {
|
||||||
|
cur = cur<<8 | uint(b)
|
||||||
|
cbits += 8
|
||||||
|
sbits += 8
|
||||||
|
for cbits >= 8 {
|
||||||
|
idx := byte(cur >> (cbits - 8))
|
||||||
|
n = n.children[idx]
|
||||||
|
if n == nil {
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
if n.children == nil {
|
||||||
|
if maxLen != 0 && buf.Len() == maxLen {
|
||||||
|
return ErrStringLength
|
||||||
|
}
|
||||||
|
buf.WriteByte(n.sym)
|
||||||
|
cbits -= n.codeLen
|
||||||
|
n = rootHuffmanNode
|
||||||
|
sbits = cbits
|
||||||
|
} else {
|
||||||
|
cbits -= 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for cbits > 0 {
|
||||||
|
n = n.children[byte(cur<<(8-cbits))]
|
||||||
|
if n == nil {
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
if n.children != nil || n.codeLen > cbits {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if maxLen != 0 && buf.Len() == maxLen {
|
||||||
|
return ErrStringLength
|
||||||
|
}
|
||||||
|
buf.WriteByte(n.sym)
|
||||||
|
cbits -= n.codeLen
|
||||||
|
n = rootHuffmanNode
|
||||||
|
sbits = cbits
|
||||||
|
}
|
||||||
|
if sbits > 7 {
|
||||||
|
// Either there was an incomplete symbol, or overlong padding.
|
||||||
|
// Both are decoding errors per RFC 7541 section 5.2.
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
if mask := uint(1<<cbits - 1); cur&mask != mask {
|
||||||
|
// Trailing bits must be a prefix of EOS per RFC 7541 section 5.2.
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
// children is non-nil for internal nodes
|
||||||
|
children *[256]*node
|
||||||
|
|
||||||
|
// The following are only valid if children is nil:
|
||||||
|
codeLen uint8 // number of bits that led to the output of sym
|
||||||
|
sym byte // output symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInternalNode() *node {
|
||||||
|
return &node{children: new([256]*node)}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
buildRootOnce sync.Once
|
||||||
|
lazyRootHuffmanNode *node
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRootHuffmanNode() *node {
|
||||||
|
buildRootOnce.Do(buildRootHuffmanNode)
|
||||||
|
return lazyRootHuffmanNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildRootHuffmanNode() {
|
||||||
|
if len(huffmanCodes) != 256 {
|
||||||
|
panic("unexpected size")
|
||||||
|
}
|
||||||
|
lazyRootHuffmanNode = newInternalNode()
|
||||||
|
for i, code := range huffmanCodes {
|
||||||
|
addDecoderNode(byte(i), code, huffmanCodeLen[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addDecoderNode(sym byte, code uint32, codeLen uint8) {
|
||||||
|
cur := lazyRootHuffmanNode
|
||||||
|
for codeLen > 8 {
|
||||||
|
codeLen -= 8
|
||||||
|
i := uint8(code >> codeLen)
|
||||||
|
if cur.children[i] == nil {
|
||||||
|
cur.children[i] = newInternalNode()
|
||||||
|
}
|
||||||
|
cur = cur.children[i]
|
||||||
|
}
|
||||||
|
shift := 8 - codeLen
|
||||||
|
start, end := int(uint8(code<<shift)), int(1<<shift)
|
||||||
|
for i := start; i < start+end; i++ {
|
||||||
|
cur.children[i] = &node{sym: sym, codeLen: codeLen}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendHuffmanString appends s, as encoded in Huffman codes, to dst
|
||||||
|
// and returns the extended buffer.
|
||||||
|
func AppendHuffmanString(dst []byte, s string) []byte {
|
||||||
|
rembits := uint8(8)
|
||||||
|
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if rembits == 8 {
|
||||||
|
dst = append(dst, 0)
|
||||||
|
}
|
||||||
|
dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
if rembits < 8 {
|
||||||
|
// special EOS symbol
|
||||||
|
code := uint32(0x3fffffff)
|
||||||
|
nbits := uint8(30)
|
||||||
|
|
||||||
|
t := uint8(code >> (nbits - rembits))
|
||||||
|
dst[len(dst)-1] |= t
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// HuffmanEncodeLength returns the number of bytes required to encode
|
||||||
|
// s in Huffman codes. The result is round up to byte boundary.
|
||||||
|
func HuffmanEncodeLength(s string) uint64 {
|
||||||
|
n := uint64(0)
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
n += uint64(huffmanCodeLen[s[i]])
|
||||||
|
}
|
||||||
|
return (n + 7) / 8
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendByteToHuffmanCode appends Huffman code for c to dst and
|
||||||
|
// returns the extended buffer and the remaining bits in the last
|
||||||
|
// element. The appending is not byte aligned and the remaining bits
|
||||||
|
// in the last element of dst is given in rembits.
|
||||||
|
func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
|
||||||
|
code := huffmanCodes[c]
|
||||||
|
nbits := huffmanCodeLen[c]
|
||||||
|
|
||||||
|
for {
|
||||||
|
if rembits > nbits {
|
||||||
|
t := uint8(code << (rembits - nbits))
|
||||||
|
dst[len(dst)-1] |= t
|
||||||
|
rembits -= nbits
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
t := uint8(code >> (nbits - rembits))
|
||||||
|
dst[len(dst)-1] |= t
|
||||||
|
|
||||||
|
nbits -= rembits
|
||||||
|
rembits = 8
|
||||||
|
|
||||||
|
if nbits == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = append(dst, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst, rembits
|
||||||
|
}
|
479
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
Normal file
479
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
Normal file
|
@ -0,0 +1,479 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// headerFieldTable implements a list of HeaderFields.
|
||||||
|
// This is used to implement the static and dynamic tables.
|
||||||
|
type headerFieldTable struct {
|
||||||
|
// For static tables, entries are never evicted.
|
||||||
|
//
|
||||||
|
// For dynamic tables, entries are evicted from ents[0] and added to the end.
|
||||||
|
// Each entry has a unique id that starts at one and increments for each
|
||||||
|
// entry that is added. This unique id is stable across evictions, meaning
|
||||||
|
// it can be used as a pointer to a specific entry. As in hpack, unique ids
|
||||||
|
// are 1-based. The unique id for ents[k] is k + evictCount + 1.
|
||||||
|
//
|
||||||
|
// Zero is not a valid unique id.
|
||||||
|
//
|
||||||
|
// evictCount should not overflow in any remotely practical situation. In
|
||||||
|
// practice, we will have one dynamic table per HTTP/2 connection. If we
|
||||||
|
// assume a very powerful server that handles 1M QPS per connection and each
|
||||||
|
// request adds (then evicts) 100 entries from the table, it would still take
|
||||||
|
// 2M years for evictCount to overflow.
|
||||||
|
ents []HeaderField
|
||||||
|
evictCount uint64
|
||||||
|
|
||||||
|
// byName maps a HeaderField name to the unique id of the newest entry with
|
||||||
|
// the same name. See above for a definition of "unique id".
|
||||||
|
byName map[string]uint64
|
||||||
|
|
||||||
|
// byNameValue maps a HeaderField name/value pair to the unique id of the newest
|
||||||
|
// entry with the same name and value. See above for a definition of "unique id".
|
||||||
|
byNameValue map[pairNameValue]uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type pairNameValue struct {
|
||||||
|
name, value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *headerFieldTable) init() {
|
||||||
|
t.byName = make(map[string]uint64)
|
||||||
|
t.byNameValue = make(map[pairNameValue]uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// len reports the number of entries in the table.
|
||||||
|
func (t *headerFieldTable) len() int {
|
||||||
|
return len(t.ents)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addEntry adds a new entry.
|
||||||
|
func (t *headerFieldTable) addEntry(f HeaderField) {
|
||||||
|
id := uint64(t.len()) + t.evictCount + 1
|
||||||
|
t.byName[f.Name] = id
|
||||||
|
t.byNameValue[pairNameValue{f.Name, f.Value}] = id
|
||||||
|
t.ents = append(t.ents, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// evictOldest evicts the n oldest entries in the table.
|
||||||
|
func (t *headerFieldTable) evictOldest(n int) {
|
||||||
|
if n > t.len() {
|
||||||
|
panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
|
||||||
|
}
|
||||||
|
for k := 0; k < n; k++ {
|
||||||
|
f := t.ents[k]
|
||||||
|
id := t.evictCount + uint64(k) + 1
|
||||||
|
if t.byName[f.Name] == id {
|
||||||
|
delete(t.byName, f.Name)
|
||||||
|
}
|
||||||
|
if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
|
||||||
|
delete(t.byNameValue, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(t.ents, t.ents[n:])
|
||||||
|
for k := t.len() - n; k < t.len(); k++ {
|
||||||
|
t.ents[k] = HeaderField{} // so strings can be garbage collected
|
||||||
|
}
|
||||||
|
t.ents = t.ents[:t.len()-n]
|
||||||
|
if t.evictCount+uint64(n) < t.evictCount {
|
||||||
|
panic("evictCount overflow")
|
||||||
|
}
|
||||||
|
t.evictCount += uint64(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// search finds f in the table. If there is no match, i is 0.
|
||||||
|
// If both name and value match, i is the matched index and nameValueMatch
|
||||||
|
// becomes true. If only name matches, i points to that index and
|
||||||
|
// nameValueMatch becomes false.
|
||||||
|
//
|
||||||
|
// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
|
||||||
|
// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
|
||||||
|
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
|
||||||
|
// table, the return value i actually refers to the entry t.ents[t.len()-i].
|
||||||
|
//
|
||||||
|
// All tables are assumed to be a dynamic tables except for the global
|
||||||
|
// staticTable pointer.
|
||||||
|
//
|
||||||
|
// See Section 2.3.3.
|
||||||
|
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
|
||||||
|
if !f.Sensitive {
|
||||||
|
if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
|
||||||
|
return t.idToIndex(id), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id := t.byName[f.Name]; id != 0 {
|
||||||
|
return t.idToIndex(id), false
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// idToIndex converts a unique id to an HPACK index.
|
||||||
|
// See Section 2.3.3.
|
||||||
|
func (t *headerFieldTable) idToIndex(id uint64) uint64 {
|
||||||
|
if id <= t.evictCount {
|
||||||
|
panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
|
||||||
|
}
|
||||||
|
k := id - t.evictCount - 1 // convert id to an index t.ents[k]
|
||||||
|
if t != staticTable {
|
||||||
|
return uint64(t.len()) - k // dynamic table
|
||||||
|
}
|
||||||
|
return k + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
||||||
|
var staticTable = newStaticTable()
|
||||||
|
var staticTableEntries = [...]HeaderField{
|
||||||
|
{Name: ":authority"},
|
||||||
|
{Name: ":method", Value: "GET"},
|
||||||
|
{Name: ":method", Value: "POST"},
|
||||||
|
{Name: ":path", Value: "/"},
|
||||||
|
{Name: ":path", Value: "/index.html"},
|
||||||
|
{Name: ":scheme", Value: "http"},
|
||||||
|
{Name: ":scheme", Value: "https"},
|
||||||
|
{Name: ":status", Value: "200"},
|
||||||
|
{Name: ":status", Value: "204"},
|
||||||
|
{Name: ":status", Value: "206"},
|
||||||
|
{Name: ":status", Value: "304"},
|
||||||
|
{Name: ":status", Value: "400"},
|
||||||
|
{Name: ":status", Value: "404"},
|
||||||
|
{Name: ":status", Value: "500"},
|
||||||
|
{Name: "accept-charset"},
|
||||||
|
{Name: "accept-encoding", Value: "gzip, deflate"},
|
||||||
|
{Name: "accept-language"},
|
||||||
|
{Name: "accept-ranges"},
|
||||||
|
{Name: "accept"},
|
||||||
|
{Name: "access-control-allow-origin"},
|
||||||
|
{Name: "age"},
|
||||||
|
{Name: "allow"},
|
||||||
|
{Name: "authorization"},
|
||||||
|
{Name: "cache-control"},
|
||||||
|
{Name: "content-disposition"},
|
||||||
|
{Name: "content-encoding"},
|
||||||
|
{Name: "content-language"},
|
||||||
|
{Name: "content-length"},
|
||||||
|
{Name: "content-location"},
|
||||||
|
{Name: "content-range"},
|
||||||
|
{Name: "content-type"},
|
||||||
|
{Name: "cookie"},
|
||||||
|
{Name: "date"},
|
||||||
|
{Name: "etag"},
|
||||||
|
{Name: "expect"},
|
||||||
|
{Name: "expires"},
|
||||||
|
{Name: "from"},
|
||||||
|
{Name: "host"},
|
||||||
|
{Name: "if-match"},
|
||||||
|
{Name: "if-modified-since"},
|
||||||
|
{Name: "if-none-match"},
|
||||||
|
{Name: "if-range"},
|
||||||
|
{Name: "if-unmodified-since"},
|
||||||
|
{Name: "last-modified"},
|
||||||
|
{Name: "link"},
|
||||||
|
{Name: "location"},
|
||||||
|
{Name: "max-forwards"},
|
||||||
|
{Name: "proxy-authenticate"},
|
||||||
|
{Name: "proxy-authorization"},
|
||||||
|
{Name: "range"},
|
||||||
|
{Name: "referer"},
|
||||||
|
{Name: "refresh"},
|
||||||
|
{Name: "retry-after"},
|
||||||
|
{Name: "server"},
|
||||||
|
{Name: "set-cookie"},
|
||||||
|
{Name: "strict-transport-security"},
|
||||||
|
{Name: "transfer-encoding"},
|
||||||
|
{Name: "user-agent"},
|
||||||
|
{Name: "vary"},
|
||||||
|
{Name: "via"},
|
||||||
|
{Name: "www-authenticate"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStaticTable() *headerFieldTable {
|
||||||
|
t := &headerFieldTable{}
|
||||||
|
t.init()
|
||||||
|
for _, e := range staticTableEntries[:] {
|
||||||
|
t.addEntry(e)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
var huffmanCodes = [256]uint32{
|
||||||
|
0x1ff8,
|
||||||
|
0x7fffd8,
|
||||||
|
0xfffffe2,
|
||||||
|
0xfffffe3,
|
||||||
|
0xfffffe4,
|
||||||
|
0xfffffe5,
|
||||||
|
0xfffffe6,
|
||||||
|
0xfffffe7,
|
||||||
|
0xfffffe8,
|
||||||
|
0xffffea,
|
||||||
|
0x3ffffffc,
|
||||||
|
0xfffffe9,
|
||||||
|
0xfffffea,
|
||||||
|
0x3ffffffd,
|
||||||
|
0xfffffeb,
|
||||||
|
0xfffffec,
|
||||||
|
0xfffffed,
|
||||||
|
0xfffffee,
|
||||||
|
0xfffffef,
|
||||||
|
0xffffff0,
|
||||||
|
0xffffff1,
|
||||||
|
0xffffff2,
|
||||||
|
0x3ffffffe,
|
||||||
|
0xffffff3,
|
||||||
|
0xffffff4,
|
||||||
|
0xffffff5,
|
||||||
|
0xffffff6,
|
||||||
|
0xffffff7,
|
||||||
|
0xffffff8,
|
||||||
|
0xffffff9,
|
||||||
|
0xffffffa,
|
||||||
|
0xffffffb,
|
||||||
|
0x14,
|
||||||
|
0x3f8,
|
||||||
|
0x3f9,
|
||||||
|
0xffa,
|
||||||
|
0x1ff9,
|
||||||
|
0x15,
|
||||||
|
0xf8,
|
||||||
|
0x7fa,
|
||||||
|
0x3fa,
|
||||||
|
0x3fb,
|
||||||
|
0xf9,
|
||||||
|
0x7fb,
|
||||||
|
0xfa,
|
||||||
|
0x16,
|
||||||
|
0x17,
|
||||||
|
0x18,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0x2,
|
||||||
|
0x19,
|
||||||
|
0x1a,
|
||||||
|
0x1b,
|
||||||
|
0x1c,
|
||||||
|
0x1d,
|
||||||
|
0x1e,
|
||||||
|
0x1f,
|
||||||
|
0x5c,
|
||||||
|
0xfb,
|
||||||
|
0x7ffc,
|
||||||
|
0x20,
|
||||||
|
0xffb,
|
||||||
|
0x3fc,
|
||||||
|
0x1ffa,
|
||||||
|
0x21,
|
||||||
|
0x5d,
|
||||||
|
0x5e,
|
||||||
|
0x5f,
|
||||||
|
0x60,
|
||||||
|
0x61,
|
||||||
|
0x62,
|
||||||
|
0x63,
|
||||||
|
0x64,
|
||||||
|
0x65,
|
||||||
|
0x66,
|
||||||
|
0x67,
|
||||||
|
0x68,
|
||||||
|
0x69,
|
||||||
|
0x6a,
|
||||||
|
0x6b,
|
||||||
|
0x6c,
|
||||||
|
0x6d,
|
||||||
|
0x6e,
|
||||||
|
0x6f,
|
||||||
|
0x70,
|
||||||
|
0x71,
|
||||||
|
0x72,
|
||||||
|
0xfc,
|
||||||
|
0x73,
|
||||||
|
0xfd,
|
||||||
|
0x1ffb,
|
||||||
|
0x7fff0,
|
||||||
|
0x1ffc,
|
||||||
|
0x3ffc,
|
||||||
|
0x22,
|
||||||
|
0x7ffd,
|
||||||
|
0x3,
|
||||||
|
0x23,
|
||||||
|
0x4,
|
||||||
|
0x24,
|
||||||
|
0x5,
|
||||||
|
0x25,
|
||||||
|
0x26,
|
||||||
|
0x27,
|
||||||
|
0x6,
|
||||||
|
0x74,
|
||||||
|
0x75,
|
||||||
|
0x28,
|
||||||
|
0x29,
|
||||||
|
0x2a,
|
||||||
|
0x7,
|
||||||
|
0x2b,
|
||||||
|
0x76,
|
||||||
|
0x2c,
|
||||||
|
0x8,
|
||||||
|
0x9,
|
||||||
|
0x2d,
|
||||||
|
0x77,
|
||||||
|
0x78,
|
||||||
|
0x79,
|
||||||
|
0x7a,
|
||||||
|
0x7b,
|
||||||
|
0x7ffe,
|
||||||
|
0x7fc,
|
||||||
|
0x3ffd,
|
||||||
|
0x1ffd,
|
||||||
|
0xffffffc,
|
||||||
|
0xfffe6,
|
||||||
|
0x3fffd2,
|
||||||
|
0xfffe7,
|
||||||
|
0xfffe8,
|
||||||
|
0x3fffd3,
|
||||||
|
0x3fffd4,
|
||||||
|
0x3fffd5,
|
||||||
|
0x7fffd9,
|
||||||
|
0x3fffd6,
|
||||||
|
0x7fffda,
|
||||||
|
0x7fffdb,
|
||||||
|
0x7fffdc,
|
||||||
|
0x7fffdd,
|
||||||
|
0x7fffde,
|
||||||
|
0xffffeb,
|
||||||
|
0x7fffdf,
|
||||||
|
0xffffec,
|
||||||
|
0xffffed,
|
||||||
|
0x3fffd7,
|
||||||
|
0x7fffe0,
|
||||||
|
0xffffee,
|
||||||
|
0x7fffe1,
|
||||||
|
0x7fffe2,
|
||||||
|
0x7fffe3,
|
||||||
|
0x7fffe4,
|
||||||
|
0x1fffdc,
|
||||||
|
0x3fffd8,
|
||||||
|
0x7fffe5,
|
||||||
|
0x3fffd9,
|
||||||
|
0x7fffe6,
|
||||||
|
0x7fffe7,
|
||||||
|
0xffffef,
|
||||||
|
0x3fffda,
|
||||||
|
0x1fffdd,
|
||||||
|
0xfffe9,
|
||||||
|
0x3fffdb,
|
||||||
|
0x3fffdc,
|
||||||
|
0x7fffe8,
|
||||||
|
0x7fffe9,
|
||||||
|
0x1fffde,
|
||||||
|
0x7fffea,
|
||||||
|
0x3fffdd,
|
||||||
|
0x3fffde,
|
||||||
|
0xfffff0,
|
||||||
|
0x1fffdf,
|
||||||
|
0x3fffdf,
|
||||||
|
0x7fffeb,
|
||||||
|
0x7fffec,
|
||||||
|
0x1fffe0,
|
||||||
|
0x1fffe1,
|
||||||
|
0x3fffe0,
|
||||||
|
0x1fffe2,
|
||||||
|
0x7fffed,
|
||||||
|
0x3fffe1,
|
||||||
|
0x7fffee,
|
||||||
|
0x7fffef,
|
||||||
|
0xfffea,
|
||||||
|
0x3fffe2,
|
||||||
|
0x3fffe3,
|
||||||
|
0x3fffe4,
|
||||||
|
0x7ffff0,
|
||||||
|
0x3fffe5,
|
||||||
|
0x3fffe6,
|
||||||
|
0x7ffff1,
|
||||||
|
0x3ffffe0,
|
||||||
|
0x3ffffe1,
|
||||||
|
0xfffeb,
|
||||||
|
0x7fff1,
|
||||||
|
0x3fffe7,
|
||||||
|
0x7ffff2,
|
||||||
|
0x3fffe8,
|
||||||
|
0x1ffffec,
|
||||||
|
0x3ffffe2,
|
||||||
|
0x3ffffe3,
|
||||||
|
0x3ffffe4,
|
||||||
|
0x7ffffde,
|
||||||
|
0x7ffffdf,
|
||||||
|
0x3ffffe5,
|
||||||
|
0xfffff1,
|
||||||
|
0x1ffffed,
|
||||||
|
0x7fff2,
|
||||||
|
0x1fffe3,
|
||||||
|
0x3ffffe6,
|
||||||
|
0x7ffffe0,
|
||||||
|
0x7ffffe1,
|
||||||
|
0x3ffffe7,
|
||||||
|
0x7ffffe2,
|
||||||
|
0xfffff2,
|
||||||
|
0x1fffe4,
|
||||||
|
0x1fffe5,
|
||||||
|
0x3ffffe8,
|
||||||
|
0x3ffffe9,
|
||||||
|
0xffffffd,
|
||||||
|
0x7ffffe3,
|
||||||
|
0x7ffffe4,
|
||||||
|
0x7ffffe5,
|
||||||
|
0xfffec,
|
||||||
|
0xfffff3,
|
||||||
|
0xfffed,
|
||||||
|
0x1fffe6,
|
||||||
|
0x3fffe9,
|
||||||
|
0x1fffe7,
|
||||||
|
0x1fffe8,
|
||||||
|
0x7ffff3,
|
||||||
|
0x3fffea,
|
||||||
|
0x3fffeb,
|
||||||
|
0x1ffffee,
|
||||||
|
0x1ffffef,
|
||||||
|
0xfffff4,
|
||||||
|
0xfffff5,
|
||||||
|
0x3ffffea,
|
||||||
|
0x7ffff4,
|
||||||
|
0x3ffffeb,
|
||||||
|
0x7ffffe6,
|
||||||
|
0x3ffffec,
|
||||||
|
0x3ffffed,
|
||||||
|
0x7ffffe7,
|
||||||
|
0x7ffffe8,
|
||||||
|
0x7ffffe9,
|
||||||
|
0x7ffffea,
|
||||||
|
0x7ffffeb,
|
||||||
|
0xffffffe,
|
||||||
|
0x7ffffec,
|
||||||
|
0x7ffffed,
|
||||||
|
0x7ffffee,
|
||||||
|
0x7ffffef,
|
||||||
|
0x7fffff0,
|
||||||
|
0x3ffffee,
|
||||||
|
}
|
||||||
|
|
||||||
|
var huffmanCodeLen = [256]uint8{
|
||||||
|
13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
|
||||||
|
28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||||
|
6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
|
||||||
|
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
|
||||||
|
13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
|
||||||
|
15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
|
||||||
|
6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
|
||||||
|
20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
|
||||||
|
24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
|
||||||
|
22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
|
||||||
|
21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
|
||||||
|
26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
|
||||||
|
19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
|
||||||
|
20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
|
||||||
|
26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
|
||||||
|
}
|
378
vendor/golang.org/x/net/http2/http2.go
generated
vendored
Normal file
378
vendor/golang.org/x/net/http2/http2.go
generated
vendored
Normal file
|
@ -0,0 +1,378 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package http2 implements the HTTP/2 protocol.
|
||||||
|
//
|
||||||
|
// This package is low-level and intended to be used directly by very
|
||||||
|
// few people. Most users will use it indirectly through the automatic
|
||||||
|
// use by the net/http package (from Go 1.6 and later).
|
||||||
|
// For use in earlier Go versions see ConfigureServer. (Transport support
|
||||||
|
// requires Go 1.6 or later)
|
||||||
|
//
|
||||||
|
// See https://http2.github.io/ for more information on HTTP/2.
|
||||||
|
//
|
||||||
|
// See https://http2.golang.org/ for a test server running this code.
|
||||||
|
//
|
||||||
|
package http2 // import "golang.org/x/net/http2"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
VerboseLogs bool
|
||||||
|
logFrameWrites bool
|
||||||
|
logFrameReads bool
|
||||||
|
inTests bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
e := os.Getenv("GODEBUG")
|
||||||
|
if strings.Contains(e, "http2debug=1") {
|
||||||
|
VerboseLogs = true
|
||||||
|
}
|
||||||
|
if strings.Contains(e, "http2debug=2") {
|
||||||
|
VerboseLogs = true
|
||||||
|
logFrameWrites = true
|
||||||
|
logFrameReads = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ClientPreface is the string that must be sent by new
|
||||||
|
// connections from clients.
|
||||||
|
ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
||||||
|
|
||||||
|
// SETTINGS_MAX_FRAME_SIZE default
|
||||||
|
// http://http2.github.io/http2-spec/#rfc.section.6.5.2
|
||||||
|
initialMaxFrameSize = 16384
|
||||||
|
|
||||||
|
// NextProtoTLS is the NPN/ALPN protocol negotiated during
|
||||||
|
// HTTP/2's TLS setup.
|
||||||
|
NextProtoTLS = "h2"
|
||||||
|
|
||||||
|
// http://http2.github.io/http2-spec/#SettingValues
|
||||||
|
initialHeaderTableSize = 4096
|
||||||
|
|
||||||
|
initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
|
||||||
|
|
||||||
|
defaultMaxReadFrameSize = 1 << 20
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
clientPreface = []byte(ClientPreface)
|
||||||
|
)
|
||||||
|
|
||||||
|
type streamState int
|
||||||
|
|
||||||
|
// HTTP/2 stream states.
|
||||||
|
//
|
||||||
|
// See http://tools.ietf.org/html/rfc7540#section-5.1.
|
||||||
|
//
|
||||||
|
// For simplicity, the server code merges "reserved (local)" into
|
||||||
|
// "half-closed (remote)". This is one less state transition to track.
|
||||||
|
// The only downside is that we send PUSH_PROMISEs slightly less
|
||||||
|
// liberally than allowable. More discussion here:
|
||||||
|
// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
|
||||||
|
//
|
||||||
|
// "reserved (remote)" is omitted since the client code does not
|
||||||
|
// support server push.
|
||||||
|
const (
|
||||||
|
stateIdle streamState = iota
|
||||||
|
stateOpen
|
||||||
|
stateHalfClosedLocal
|
||||||
|
stateHalfClosedRemote
|
||||||
|
stateClosed
|
||||||
|
)
|
||||||
|
|
||||||
|
var stateName = [...]string{
|
||||||
|
stateIdle: "Idle",
|
||||||
|
stateOpen: "Open",
|
||||||
|
stateHalfClosedLocal: "HalfClosedLocal",
|
||||||
|
stateHalfClosedRemote: "HalfClosedRemote",
|
||||||
|
stateClosed: "Closed",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st streamState) String() string {
|
||||||
|
return stateName[st]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setting is a setting parameter: which setting it is, and its value.
|
||||||
|
type Setting struct {
|
||||||
|
// ID is which setting is being set.
|
||||||
|
// See http://http2.github.io/http2-spec/#SettingValues
|
||||||
|
ID SettingID
|
||||||
|
|
||||||
|
// Val is the value.
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Setting) String() string {
|
||||||
|
return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid reports whether the setting is valid.
|
||||||
|
func (s Setting) Valid() error {
|
||||||
|
// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
|
||||||
|
switch s.ID {
|
||||||
|
case SettingEnablePush:
|
||||||
|
if s.Val != 1 && s.Val != 0 {
|
||||||
|
return ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
case SettingInitialWindowSize:
|
||||||
|
if s.Val > 1<<31-1 {
|
||||||
|
return ConnectionError(ErrCodeFlowControl)
|
||||||
|
}
|
||||||
|
case SettingMaxFrameSize:
|
||||||
|
if s.Val < 16384 || s.Val > 1<<24-1 {
|
||||||
|
return ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A SettingID is an HTTP/2 setting as defined in
|
||||||
|
// http://http2.github.io/http2-spec/#iana-settings
|
||||||
|
type SettingID uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
SettingHeaderTableSize SettingID = 0x1
|
||||||
|
SettingEnablePush SettingID = 0x2
|
||||||
|
SettingMaxConcurrentStreams SettingID = 0x3
|
||||||
|
SettingInitialWindowSize SettingID = 0x4
|
||||||
|
SettingMaxFrameSize SettingID = 0x5
|
||||||
|
SettingMaxHeaderListSize SettingID = 0x6
|
||||||
|
)
|
||||||
|
|
||||||
|
var settingName = map[SettingID]string{
|
||||||
|
SettingHeaderTableSize: "HEADER_TABLE_SIZE",
|
||||||
|
SettingEnablePush: "ENABLE_PUSH",
|
||||||
|
SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
|
||||||
|
SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
|
||||||
|
SettingMaxFrameSize: "MAX_FRAME_SIZE",
|
||||||
|
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SettingID) String() string {
|
||||||
|
if v, ok := settingName[s]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// validWireHeaderFieldName reports whether v is a valid header field
|
||||||
|
// name (key). See httpguts.ValidHeaderName for the base rules.
|
||||||
|
//
|
||||||
|
// Further, http2 says:
|
||||||
|
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
||||||
|
// characters that are compared in a case-insensitive
|
||||||
|
// fashion. However, header field names MUST be converted to
|
||||||
|
// lowercase prior to their encoding in HTTP/2. "
|
||||||
|
func validWireHeaderFieldName(v string) bool {
|
||||||
|
if len(v) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, r := range v {
|
||||||
|
if !httpguts.IsTokenRune(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if 'A' <= r && r <= 'Z' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func httpCodeString(code int) string {
|
||||||
|
switch code {
|
||||||
|
case 200:
|
||||||
|
return "200"
|
||||||
|
case 404:
|
||||||
|
return "404"
|
||||||
|
}
|
||||||
|
return strconv.Itoa(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// from pkg io
|
||||||
|
type stringWriter interface {
|
||||||
|
WriteString(s string) (n int, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A gate lets two goroutines coordinate their activities.
|
||||||
|
type gate chan struct{}
|
||||||
|
|
||||||
|
func (g gate) Done() { g <- struct{}{} }
|
||||||
|
func (g gate) Wait() { <-g }
|
||||||
|
|
||||||
|
// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
|
||||||
|
type closeWaiter chan struct{}
|
||||||
|
|
||||||
|
// Init makes a closeWaiter usable.
|
||||||
|
// It exists because so a closeWaiter value can be placed inside a
|
||||||
|
// larger struct and have the Mutex and Cond's memory in the same
|
||||||
|
// allocation.
|
||||||
|
func (cw *closeWaiter) Init() {
|
||||||
|
*cw = make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close marks the closeWaiter as closed and unblocks any waiters.
|
||||||
|
func (cw closeWaiter) Close() {
|
||||||
|
close(cw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait waits for the closeWaiter to become closed.
|
||||||
|
func (cw closeWaiter) Wait() {
|
||||||
|
<-cw
|
||||||
|
}
|
||||||
|
|
||||||
|
// bufferedWriter is a buffered writer that writes to w.
|
||||||
|
// Its buffered writer is lazily allocated as needed, to minimize
|
||||||
|
// idle memory usage with many connections.
|
||||||
|
type bufferedWriter struct {
|
||||||
|
w io.Writer // immutable
|
||||||
|
bw *bufio.Writer // non-nil when data is buffered
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBufferedWriter(w io.Writer) *bufferedWriter {
|
||||||
|
return &bufferedWriter{w: w}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bufWriterPoolBufferSize is the size of bufio.Writer's
|
||||||
|
// buffers created using bufWriterPool.
|
||||||
|
//
|
||||||
|
// TODO: pick a less arbitrary value? this is a bit under
|
||||||
|
// (3 x typical 1500 byte MTU) at least. Other than that,
|
||||||
|
// not much thought went into it.
|
||||||
|
const bufWriterPoolBufferSize = 4 << 10
|
||||||
|
|
||||||
|
var bufWriterPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *bufferedWriter) Available() int {
|
||||||
|
if w.bw == nil {
|
||||||
|
return bufWriterPoolBufferSize
|
||||||
|
}
|
||||||
|
return w.bw.Available()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *bufferedWriter) Write(p []byte) (n int, err error) {
|
||||||
|
if w.bw == nil {
|
||||||
|
bw := bufWriterPool.Get().(*bufio.Writer)
|
||||||
|
bw.Reset(w.w)
|
||||||
|
w.bw = bw
|
||||||
|
}
|
||||||
|
return w.bw.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *bufferedWriter) Flush() error {
|
||||||
|
bw := w.bw
|
||||||
|
if bw == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := bw.Flush()
|
||||||
|
bw.Reset(nil)
|
||||||
|
bufWriterPool.Put(bw)
|
||||||
|
w.bw = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustUint31(v int32) uint32 {
|
||||||
|
if v < 0 || v > 2147483647 {
|
||||||
|
panic("out of range")
|
||||||
|
}
|
||||||
|
return uint32(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bodyAllowedForStatus reports whether a given response status code
|
||||||
|
// permits a body. See RFC 7230, section 3.3.
|
||||||
|
func bodyAllowedForStatus(status int) bool {
|
||||||
|
switch {
|
||||||
|
case status >= 100 && status <= 199:
|
||||||
|
return false
|
||||||
|
case status == 204:
|
||||||
|
return false
|
||||||
|
case status == 304:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpError struct {
|
||||||
|
msg string
|
||||||
|
timeout bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *httpError) Error() string { return e.msg }
|
||||||
|
func (e *httpError) Timeout() bool { return e.timeout }
|
||||||
|
func (e *httpError) Temporary() bool { return true }
|
||||||
|
|
||||||
|
var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
|
||||||
|
|
||||||
|
type connectionStater interface {
|
||||||
|
ConnectionState() tls.ConnectionState
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
|
||||||
|
|
||||||
|
type sorter struct {
|
||||||
|
v []string // owned by sorter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sorter) Len() int { return len(s.v) }
|
||||||
|
func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
|
||||||
|
func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
|
||||||
|
|
||||||
|
// Keys returns the sorted keys of h.
|
||||||
|
//
|
||||||
|
// The returned slice is only valid until s used again or returned to
|
||||||
|
// its pool.
|
||||||
|
func (s *sorter) Keys(h http.Header) []string {
|
||||||
|
keys := s.v[:0]
|
||||||
|
for k := range h {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
s.v = keys
|
||||||
|
sort.Sort(s)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sorter) SortStrings(ss []string) {
|
||||||
|
// Our sorter works on s.v, which sorter owns, so
|
||||||
|
// stash it away while we sort the user's buffer.
|
||||||
|
save := s.v
|
||||||
|
s.v = ss
|
||||||
|
sort.Sort(s)
|
||||||
|
s.v = save
|
||||||
|
}
|
||||||
|
|
||||||
|
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||||
|
// value. It must be either:
|
||||||
|
//
|
||||||
|
// *) a non-empty string starting with '/'
|
||||||
|
// *) the string '*', for OPTIONS requests.
|
||||||
|
//
|
||||||
|
// For now this is only used a quick check for deciding when to clean
|
||||||
|
// up Opaque URLs before sending requests from the Transport.
|
||||||
|
// See golang.org/issue/16847
|
||||||
|
//
|
||||||
|
// We used to enforce that the path also didn't start with "//", but
|
||||||
|
// Google's GFE accepts such paths and Chrome sends them, so ignore
|
||||||
|
// that part of the spec. See golang.org/issue/19103.
|
||||||
|
func validPseudoPath(v string) bool {
|
||||||
|
return (len(v) > 0 && v[0] == '/') || v == "*"
|
||||||
|
}
|
20
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
20
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.11
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptrace"
|
||||||
|
"net/textproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
return nil
|
||||||
|
}
|
168
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
Normal file
168
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
|
||||||
|
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
|
||||||
|
// underlying buffer is an interface. (io.Pipe is always unbuffered)
|
||||||
|
type pipe struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
c sync.Cond // c.L lazily initialized to &p.mu
|
||||||
|
b pipeBuffer // nil when done reading
|
||||||
|
unread int // bytes unread when done
|
||||||
|
err error // read error once empty. non-nil means closed.
|
||||||
|
breakErr error // immediate read error (caller doesn't see rest of b)
|
||||||
|
donec chan struct{} // closed on error
|
||||||
|
readFn func() // optional code to run in Read before error
|
||||||
|
}
|
||||||
|
|
||||||
|
type pipeBuffer interface {
|
||||||
|
Len() int
|
||||||
|
io.Writer
|
||||||
|
io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) Len() int {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.b == nil {
|
||||||
|
return p.unread
|
||||||
|
}
|
||||||
|
return p.b.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read waits until data is available and copies bytes
|
||||||
|
// from the buffer into p.
|
||||||
|
func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.c.L == nil {
|
||||||
|
p.c.L = &p.mu
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
if p.breakErr != nil {
|
||||||
|
return 0, p.breakErr
|
||||||
|
}
|
||||||
|
if p.b != nil && p.b.Len() > 0 {
|
||||||
|
return p.b.Read(d)
|
||||||
|
}
|
||||||
|
if p.err != nil {
|
||||||
|
if p.readFn != nil {
|
||||||
|
p.readFn() // e.g. copy trailers
|
||||||
|
p.readFn = nil // not sticky like p.err
|
||||||
|
}
|
||||||
|
p.b = nil
|
||||||
|
return 0, p.err
|
||||||
|
}
|
||||||
|
p.c.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errClosedPipeWrite = errors.New("write on closed buffer")
|
||||||
|
|
||||||
|
// Write copies bytes from p into the buffer and wakes a reader.
|
||||||
|
// It is an error to write more data than the buffer can hold.
|
||||||
|
func (p *pipe) Write(d []byte) (n int, err error) {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.c.L == nil {
|
||||||
|
p.c.L = &p.mu
|
||||||
|
}
|
||||||
|
defer p.c.Signal()
|
||||||
|
if p.err != nil {
|
||||||
|
return 0, errClosedPipeWrite
|
||||||
|
}
|
||||||
|
if p.breakErr != nil {
|
||||||
|
p.unread += len(d)
|
||||||
|
return len(d), nil // discard when there is no reader
|
||||||
|
}
|
||||||
|
return p.b.Write(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseWithError causes the next Read (waking up a current blocked
|
||||||
|
// Read if needed) to return the provided err after all data has been
|
||||||
|
// read.
|
||||||
|
//
|
||||||
|
// The error must be non-nil.
|
||||||
|
func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
|
||||||
|
|
||||||
|
// BreakWithError causes the next Read (waking up a current blocked
|
||||||
|
// Read if needed) to return the provided err immediately, without
|
||||||
|
// waiting for unread data.
|
||||||
|
func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
|
||||||
|
|
||||||
|
// closeWithErrorAndCode is like CloseWithError but also sets some code to run
|
||||||
|
// in the caller's goroutine before returning the error.
|
||||||
|
func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
|
||||||
|
|
||||||
|
func (p *pipe) closeWithError(dst *error, err error, fn func()) {
|
||||||
|
if err == nil {
|
||||||
|
panic("err must be non-nil")
|
||||||
|
}
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.c.L == nil {
|
||||||
|
p.c.L = &p.mu
|
||||||
|
}
|
||||||
|
defer p.c.Signal()
|
||||||
|
if *dst != nil {
|
||||||
|
// Already been done.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.readFn = fn
|
||||||
|
if dst == &p.breakErr {
|
||||||
|
if p.b != nil {
|
||||||
|
p.unread += p.b.Len()
|
||||||
|
}
|
||||||
|
p.b = nil
|
||||||
|
}
|
||||||
|
*dst = err
|
||||||
|
p.closeDoneLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
// requires p.mu be held.
|
||||||
|
func (p *pipe) closeDoneLocked() {
|
||||||
|
if p.donec == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Close if unclosed. This isn't racy since we always
|
||||||
|
// hold p.mu while closing.
|
||||||
|
select {
|
||||||
|
case <-p.donec:
|
||||||
|
default:
|
||||||
|
close(p.donec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err returns the error (if any) first set by BreakWithError or CloseWithError.
|
||||||
|
func (p *pipe) Err() error {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.breakErr != nil {
|
||||||
|
return p.breakErr
|
||||||
|
}
|
||||||
|
return p.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done returns a channel which is closed if and when this pipe is closed
|
||||||
|
// with CloseWithError.
|
||||||
|
func (p *pipe) Done() <-chan struct{} {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.donec == nil {
|
||||||
|
p.donec = make(chan struct{})
|
||||||
|
if p.err != nil || p.breakErr != nil {
|
||||||
|
// Already hit an error.
|
||||||
|
p.closeDoneLocked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.donec
|
||||||
|
}
|
2962
vendor/golang.org/x/net/http2/server.go
generated
vendored
Normal file
2962
vendor/golang.org/x/net/http2/server.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2667
vendor/golang.org/x/net/http2/transport.go
generated
vendored
Normal file
2667
vendor/golang.org/x/net/http2/transport.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
365
vendor/golang.org/x/net/http2/write.go
generated
vendored
Normal file
365
vendor/golang.org/x/net/http2/write.go
generated
vendored
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"golang.org/x/net/http/httpguts"
|
||||||
|
"golang.org/x/net/http2/hpack"
|
||||||
|
)
|
||||||
|
|
||||||
|
// writeFramer is implemented by any type that is used to write frames.
|
||||||
|
type writeFramer interface {
|
||||||
|
writeFrame(writeContext) error
|
||||||
|
|
||||||
|
// staysWithinBuffer reports whether this writer promises that
|
||||||
|
// it will only write less than or equal to size bytes, and it
|
||||||
|
// won't Flush the write context.
|
||||||
|
staysWithinBuffer(size int) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeContext is the interface needed by the various frame writer
|
||||||
|
// types below. All the writeFrame methods below are scheduled via the
|
||||||
|
// frame writing scheduler (see writeScheduler in writesched.go).
|
||||||
|
//
|
||||||
|
// This interface is implemented by *serverConn.
|
||||||
|
//
|
||||||
|
// TODO: decide whether to a) use this in the client code (which didn't
|
||||||
|
// end up using this yet, because it has a simpler design, not
|
||||||
|
// currently implementing priorities), or b) delete this and
|
||||||
|
// make the server code a bit more concrete.
|
||||||
|
type writeContext interface {
|
||||||
|
Framer() *Framer
|
||||||
|
Flush() error
|
||||||
|
CloseConn() error
|
||||||
|
// HeaderEncoder returns an HPACK encoder that writes to the
|
||||||
|
// returned buffer.
|
||||||
|
HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeEndsStream reports whether w writes a frame that will transition
|
||||||
|
// the stream to a half-closed local state. This returns false for RST_STREAM,
|
||||||
|
// which closes the entire stream (not just the local half).
|
||||||
|
func writeEndsStream(w writeFramer) bool {
|
||||||
|
switch v := w.(type) {
|
||||||
|
case *writeData:
|
||||||
|
return v.endStream
|
||||||
|
case *writeResHeaders:
|
||||||
|
return v.endStream
|
||||||
|
case nil:
|
||||||
|
// This can only happen if the caller reuses w after it's
|
||||||
|
// been intentionally nil'ed out to prevent use. Keep this
|
||||||
|
// here to catch future refactoring breaking it.
|
||||||
|
panic("writeEndsStream called on nil writeFramer")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type flushFrameWriter struct{}
|
||||||
|
|
||||||
|
func (flushFrameWriter) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (flushFrameWriter) staysWithinBuffer(max int) bool { return false }
|
||||||
|
|
||||||
|
type writeSettings []Setting
|
||||||
|
|
||||||
|
func (s writeSettings) staysWithinBuffer(max int) bool {
|
||||||
|
const settingSize = 6 // uint16 + uint32
|
||||||
|
return frameHeaderLen+settingSize*len(s) <= max
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s writeSettings) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteSettings([]Setting(s)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeGoAway struct {
|
||||||
|
maxStreamID uint32
|
||||||
|
code ErrCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *writeGoAway) writeFrame(ctx writeContext) error {
|
||||||
|
err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
|
||||||
|
ctx.Flush() // ignore error: we're hanging up on them anyway
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*writeGoAway) staysWithinBuffer(max int) bool { return false } // flushes
|
||||||
|
|
||||||
|
type writeData struct {
|
||||||
|
streamID uint32
|
||||||
|
p []byte
|
||||||
|
endStream bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeData) String() string {
|
||||||
|
return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", w.streamID, len(w.p), w.endStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeData) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteData(w.streamID, w.endStream, w.p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeData) staysWithinBuffer(max int) bool {
|
||||||
|
return frameHeaderLen+len(w.p) <= max
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlerPanicRST is the message sent from handler goroutines when
|
||||||
|
// the handler panics.
|
||||||
|
type handlerPanicRST struct {
|
||||||
|
StreamID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp handlerPanicRST) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteRSTStream(hp.StreamID, ErrCodeInternal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp handlerPanicRST) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
|
||||||
|
|
||||||
|
func (se StreamError) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteRSTStream(se.StreamID, se.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
|
||||||
|
|
||||||
|
type writePingAck struct{ pf *PingFrame }
|
||||||
|
|
||||||
|
func (w writePingAck) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WritePing(true, w.pf.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w writePingAck) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.pf.Data) <= max }
|
||||||
|
|
||||||
|
type writeSettingsAck struct{}
|
||||||
|
|
||||||
|
func (writeSettingsAck) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteSettingsAck()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (writeSettingsAck) staysWithinBuffer(max int) bool { return frameHeaderLen <= max }
|
||||||
|
|
||||||
|
// splitHeaderBlock splits headerBlock into fragments so that each fragment fits
|
||||||
|
// in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
|
||||||
|
// for the first/last fragment, respectively.
|
||||||
|
func splitHeaderBlock(ctx writeContext, headerBlock []byte, fn func(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error) error {
|
||||||
|
// For now we're lazy and just pick the minimum MAX_FRAME_SIZE
|
||||||
|
// that all peers must support (16KB). Later we could care
|
||||||
|
// more and send larger frames if the peer advertised it, but
|
||||||
|
// there's little point. Most headers are small anyway (so we
|
||||||
|
// generally won't have CONTINUATION frames), and extra frames
|
||||||
|
// only waste 9 bytes anyway.
|
||||||
|
const maxFrameSize = 16384
|
||||||
|
|
||||||
|
first := true
|
||||||
|
for len(headerBlock) > 0 {
|
||||||
|
frag := headerBlock
|
||||||
|
if len(frag) > maxFrameSize {
|
||||||
|
frag = frag[:maxFrameSize]
|
||||||
|
}
|
||||||
|
headerBlock = headerBlock[len(frag):]
|
||||||
|
if err := fn(ctx, frag, first, len(headerBlock) == 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
|
||||||
|
// for HTTP response headers or trailers from a server handler.
|
||||||
|
type writeResHeaders struct {
|
||||||
|
streamID uint32
|
||||||
|
httpResCode int // 0 means no ":status" line
|
||||||
|
h http.Header // may be nil
|
||||||
|
trailers []string // if non-nil, which keys of h to write. nil means all.
|
||||||
|
endStream bool
|
||||||
|
|
||||||
|
date string
|
||||||
|
contentType string
|
||||||
|
contentLength string
|
||||||
|
}
|
||||||
|
|
||||||
|
func encKV(enc *hpack.Encoder, k, v string) {
|
||||||
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: server encoding header %q = %q", k, v)
|
||||||
|
}
|
||||||
|
enc.WriteField(hpack.HeaderField{Name: k, Value: v})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeResHeaders) staysWithinBuffer(max int) bool {
|
||||||
|
// TODO: this is a common one. It'd be nice to return true
|
||||||
|
// here and get into the fast path if we could be clever and
|
||||||
|
// calculate the size fast enough, or at least a conservative
|
||||||
|
// upper bound that usually fires. (Maybe if w.h and
|
||||||
|
// w.trailers are nil, so we don't need to enumerate it.)
|
||||||
|
// Otherwise I'm afraid that just calculating the length to
|
||||||
|
// answer this question would be slower than the ~2µs benefit.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeResHeaders) writeFrame(ctx writeContext) error {
|
||||||
|
enc, buf := ctx.HeaderEncoder()
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
if w.httpResCode != 0 {
|
||||||
|
encKV(enc, ":status", httpCodeString(w.httpResCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeHeaders(enc, w.h, w.trailers)
|
||||||
|
|
||||||
|
if w.contentType != "" {
|
||||||
|
encKV(enc, "content-type", w.contentType)
|
||||||
|
}
|
||||||
|
if w.contentLength != "" {
|
||||||
|
encKV(enc, "content-length", w.contentLength)
|
||||||
|
}
|
||||||
|
if w.date != "" {
|
||||||
|
encKV(enc, "date", w.date)
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBlock := buf.Bytes()
|
||||||
|
if len(headerBlock) == 0 && w.trailers == nil {
|
||||||
|
panic("unexpected empty hpack")
|
||||||
|
}
|
||||||
|
|
||||||
|
return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writeResHeaders) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
|
||||||
|
if firstFrag {
|
||||||
|
return ctx.Framer().WriteHeaders(HeadersFrameParam{
|
||||||
|
StreamID: w.streamID,
|
||||||
|
BlockFragment: frag,
|
||||||
|
EndStream: w.endStream,
|
||||||
|
EndHeaders: lastFrag,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames.
|
||||||
|
type writePushPromise struct {
|
||||||
|
streamID uint32 // pusher stream
|
||||||
|
method string // for :method
|
||||||
|
url *url.URL // for :scheme, :authority, :path
|
||||||
|
h http.Header
|
||||||
|
|
||||||
|
// Creates an ID for a pushed stream. This runs on serveG just before
|
||||||
|
// the frame is written. The returned ID is copied to promisedID.
|
||||||
|
allocatePromisedID func() (uint32, error)
|
||||||
|
promisedID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writePushPromise) staysWithinBuffer(max int) bool {
|
||||||
|
// TODO: see writeResHeaders.staysWithinBuffer
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writePushPromise) writeFrame(ctx writeContext) error {
|
||||||
|
enc, buf := ctx.HeaderEncoder()
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
encKV(enc, ":method", w.method)
|
||||||
|
encKV(enc, ":scheme", w.url.Scheme)
|
||||||
|
encKV(enc, ":authority", w.url.Host)
|
||||||
|
encKV(enc, ":path", w.url.RequestURI())
|
||||||
|
encodeHeaders(enc, w.h, nil)
|
||||||
|
|
||||||
|
headerBlock := buf.Bytes()
|
||||||
|
if len(headerBlock) == 0 {
|
||||||
|
panic("unexpected empty hpack")
|
||||||
|
}
|
||||||
|
|
||||||
|
return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writePushPromise) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
|
||||||
|
if firstFrag {
|
||||||
|
return ctx.Framer().WritePushPromise(PushPromiseParam{
|
||||||
|
StreamID: w.streamID,
|
||||||
|
PromiseID: w.promisedID,
|
||||||
|
BlockFragment: frag,
|
||||||
|
EndHeaders: lastFrag,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type write100ContinueHeadersFrame struct {
|
||||||
|
streamID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w write100ContinueHeadersFrame) writeFrame(ctx writeContext) error {
|
||||||
|
enc, buf := ctx.HeaderEncoder()
|
||||||
|
buf.Reset()
|
||||||
|
encKV(enc, ":status", "100")
|
||||||
|
return ctx.Framer().WriteHeaders(HeadersFrameParam{
|
||||||
|
StreamID: w.streamID,
|
||||||
|
BlockFragment: buf.Bytes(),
|
||||||
|
EndStream: false,
|
||||||
|
EndHeaders: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w write100ContinueHeadersFrame) staysWithinBuffer(max int) bool {
|
||||||
|
// Sloppy but conservative:
|
||||||
|
return 9+2*(len(":status")+len("100")) <= max
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeWindowUpdate struct {
|
||||||
|
streamID uint32 // or 0 for conn-level
|
||||||
|
n uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wu writeWindowUpdate) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
|
||||||
|
|
||||||
|
func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
|
||||||
|
return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
|
||||||
|
// is encoded only if k is in keys.
|
||||||
|
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
||||||
|
if keys == nil {
|
||||||
|
sorter := sorterPool.Get().(*sorter)
|
||||||
|
// Using defer here, since the returned keys from the
|
||||||
|
// sorter.Keys method is only valid until the sorter
|
||||||
|
// is returned:
|
||||||
|
defer sorterPool.Put(sorter)
|
||||||
|
keys = sorter.Keys(h)
|
||||||
|
}
|
||||||
|
for _, k := range keys {
|
||||||
|
vv := h[k]
|
||||||
|
k = lowerHeader(k)
|
||||||
|
if !validWireHeaderFieldName(k) {
|
||||||
|
// Skip it as backup paranoia. Per
|
||||||
|
// golang.org/issue/14048, these should
|
||||||
|
// already be rejected at a higher level.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
isTE := k == "transfer-encoding"
|
||||||
|
for _, v := range vv {
|
||||||
|
if !httpguts.ValidHeaderFieldValue(v) {
|
||||||
|
// TODO: return an error? golang.org/issue/14048
|
||||||
|
// For now just omit it.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// TODO: more of "8.1.2.2 Connection-Specific Header Fields"
|
||||||
|
if isTE && v != "trailers" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
encKV(enc, k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
248
vendor/golang.org/x/net/http2/writesched.go
generated
vendored
Normal file
248
vendor/golang.org/x/net/http2/writesched.go
generated
vendored
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// WriteScheduler is the interface implemented by HTTP/2 write schedulers.
|
||||||
|
// Methods are never called concurrently.
|
||||||
|
type WriteScheduler interface {
|
||||||
|
// OpenStream opens a new stream in the write scheduler.
|
||||||
|
// It is illegal to call this with streamID=0 or with a streamID that is
|
||||||
|
// already open -- the call may panic.
|
||||||
|
OpenStream(streamID uint32, options OpenStreamOptions)
|
||||||
|
|
||||||
|
// CloseStream closes a stream in the write scheduler. Any frames queued on
|
||||||
|
// this stream should be discarded. It is illegal to call this on a stream
|
||||||
|
// that is not open -- the call may panic.
|
||||||
|
CloseStream(streamID uint32)
|
||||||
|
|
||||||
|
// AdjustStream adjusts the priority of the given stream. This may be called
|
||||||
|
// on a stream that has not yet been opened or has been closed. Note that
|
||||||
|
// RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
|
||||||
|
// https://tools.ietf.org/html/rfc7540#section-5.1
|
||||||
|
AdjustStream(streamID uint32, priority PriorityParam)
|
||||||
|
|
||||||
|
// Push queues a frame in the scheduler. In most cases, this will not be
|
||||||
|
// called with wr.StreamID()!=0 unless that stream is currently open. The one
|
||||||
|
// exception is RST_STREAM frames, which may be sent on idle or closed streams.
|
||||||
|
Push(wr FrameWriteRequest)
|
||||||
|
|
||||||
|
// Pop dequeues the next frame to write. Returns false if no frames can
|
||||||
|
// be written. Frames with a given wr.StreamID() are Pop'd in the same
|
||||||
|
// order they are Push'd. No frames should be discarded except by CloseStream.
|
||||||
|
Pop() (wr FrameWriteRequest, ok bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
|
||||||
|
type OpenStreamOptions struct {
|
||||||
|
// PusherID is zero if the stream was initiated by the client. Otherwise,
|
||||||
|
// PusherID names the stream that pushed the newly opened stream.
|
||||||
|
PusherID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrameWriteRequest is a request to write a frame.
|
||||||
|
type FrameWriteRequest struct {
|
||||||
|
// write is the interface value that does the writing, once the
|
||||||
|
// WriteScheduler has selected this frame to write. The write
|
||||||
|
// functions are all defined in write.go.
|
||||||
|
write writeFramer
|
||||||
|
|
||||||
|
// stream is the stream on which this frame will be written.
|
||||||
|
// nil for non-stream frames like PING and SETTINGS.
|
||||||
|
stream *stream
|
||||||
|
|
||||||
|
// done, if non-nil, must be a buffered channel with space for
|
||||||
|
// 1 message and is sent the return value from write (or an
|
||||||
|
// earlier error) when the frame has been written.
|
||||||
|
done chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
// StreamID returns the id of the stream this frame will be written to.
|
||||||
|
// 0 is used for non-stream frames such as PING and SETTINGS.
|
||||||
|
func (wr FrameWriteRequest) StreamID() uint32 {
|
||||||
|
if wr.stream == nil {
|
||||||
|
if se, ok := wr.write.(StreamError); ok {
|
||||||
|
// (*serverConn).resetStream doesn't set
|
||||||
|
// stream because it doesn't necessarily have
|
||||||
|
// one. So special case this type of write
|
||||||
|
// message.
|
||||||
|
return se.StreamID
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return wr.stream.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// isControl reports whether wr is a control frame for MaxQueuedControlFrames
|
||||||
|
// purposes. That includes non-stream frames and RST_STREAM frames.
|
||||||
|
func (wr FrameWriteRequest) isControl() bool {
|
||||||
|
return wr.stream == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataSize returns the number of flow control bytes that must be consumed
|
||||||
|
// to write this entire frame. This is 0 for non-DATA frames.
|
||||||
|
func (wr FrameWriteRequest) DataSize() int {
|
||||||
|
if wd, ok := wr.write.(*writeData); ok {
|
||||||
|
return len(wd.p)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume consumes min(n, available) bytes from this frame, where available
|
||||||
|
// is the number of flow control bytes available on the stream. Consume returns
|
||||||
|
// 0, 1, or 2 frames, where the integer return value gives the number of frames
|
||||||
|
// returned.
|
||||||
|
//
|
||||||
|
// If flow control prevents consuming any bytes, this returns (_, _, 0). If
|
||||||
|
// the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
|
||||||
|
// returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
|
||||||
|
// 'rest' contains the remaining bytes. The consumed bytes are deducted from the
|
||||||
|
// underlying stream's flow control budget.
|
||||||
|
func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) {
|
||||||
|
var empty FrameWriteRequest
|
||||||
|
|
||||||
|
// Non-DATA frames are always consumed whole.
|
||||||
|
wd, ok := wr.write.(*writeData)
|
||||||
|
if !ok || len(wd.p) == 0 {
|
||||||
|
return wr, empty, 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might need to split after applying limits.
|
||||||
|
allowed := wr.stream.flow.available()
|
||||||
|
if n < allowed {
|
||||||
|
allowed = n
|
||||||
|
}
|
||||||
|
if wr.stream.sc.maxFrameSize < allowed {
|
||||||
|
allowed = wr.stream.sc.maxFrameSize
|
||||||
|
}
|
||||||
|
if allowed <= 0 {
|
||||||
|
return empty, empty, 0
|
||||||
|
}
|
||||||
|
if len(wd.p) > int(allowed) {
|
||||||
|
wr.stream.flow.take(allowed)
|
||||||
|
consumed := FrameWriteRequest{
|
||||||
|
stream: wr.stream,
|
||||||
|
write: &writeData{
|
||||||
|
streamID: wd.streamID,
|
||||||
|
p: wd.p[:allowed],
|
||||||
|
// Even if the original had endStream set, there
|
||||||
|
// are bytes remaining because len(wd.p) > allowed,
|
||||||
|
// so we know endStream is false.
|
||||||
|
endStream: false,
|
||||||
|
},
|
||||||
|
// Our caller is blocking on the final DATA frame, not
|
||||||
|
// this intermediate frame, so no need to wait.
|
||||||
|
done: nil,
|
||||||
|
}
|
||||||
|
rest := FrameWriteRequest{
|
||||||
|
stream: wr.stream,
|
||||||
|
write: &writeData{
|
||||||
|
streamID: wd.streamID,
|
||||||
|
p: wd.p[allowed:],
|
||||||
|
endStream: wd.endStream,
|
||||||
|
},
|
||||||
|
done: wr.done,
|
||||||
|
}
|
||||||
|
return consumed, rest, 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// The frame is consumed whole.
|
||||||
|
// NB: This cast cannot overflow because allowed is <= math.MaxInt32.
|
||||||
|
wr.stream.flow.take(int32(len(wd.p)))
|
||||||
|
return wr, empty, 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is for debugging only.
|
||||||
|
func (wr FrameWriteRequest) String() string {
|
||||||
|
var des string
|
||||||
|
if s, ok := wr.write.(fmt.Stringer); ok {
|
||||||
|
des = s.String()
|
||||||
|
} else {
|
||||||
|
des = fmt.Sprintf("%T", wr.write)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
|
||||||
|
}
|
||||||
|
|
||||||
|
// replyToWriter sends err to wr.done and panics if the send must block
|
||||||
|
// This does nothing if wr.done is nil.
|
||||||
|
func (wr *FrameWriteRequest) replyToWriter(err error) {
|
||||||
|
if wr.done == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case wr.done <- err:
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
|
||||||
|
}
|
||||||
|
wr.write = nil // prevent use (assume it's tainted after wr.done send)
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeQueue is used by implementations of WriteScheduler.
|
||||||
|
type writeQueue struct {
|
||||||
|
s []FrameWriteRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *writeQueue) empty() bool { return len(q.s) == 0 }
|
||||||
|
|
||||||
|
func (q *writeQueue) push(wr FrameWriteRequest) {
|
||||||
|
q.s = append(q.s, wr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *writeQueue) shift() FrameWriteRequest {
|
||||||
|
if len(q.s) == 0 {
|
||||||
|
panic("invalid use of queue")
|
||||||
|
}
|
||||||
|
wr := q.s[0]
|
||||||
|
// TODO: less copy-happy queue.
|
||||||
|
copy(q.s, q.s[1:])
|
||||||
|
q.s[len(q.s)-1] = FrameWriteRequest{}
|
||||||
|
q.s = q.s[:len(q.s)-1]
|
||||||
|
return wr
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume consumes up to n bytes from q.s[0]. If the frame is
|
||||||
|
// entirely consumed, it is removed from the queue. If the frame
|
||||||
|
// is partially consumed, the frame is kept with the consumed
|
||||||
|
// bytes removed. Returns true iff any bytes were consumed.
|
||||||
|
func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
|
||||||
|
if len(q.s) == 0 {
|
||||||
|
return FrameWriteRequest{}, false
|
||||||
|
}
|
||||||
|
consumed, rest, numresult := q.s[0].Consume(n)
|
||||||
|
switch numresult {
|
||||||
|
case 0:
|
||||||
|
return FrameWriteRequest{}, false
|
||||||
|
case 1:
|
||||||
|
q.shift()
|
||||||
|
case 2:
|
||||||
|
q.s[0] = rest
|
||||||
|
}
|
||||||
|
return consumed, true
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeQueuePool []*writeQueue
|
||||||
|
|
||||||
|
// put inserts an unused writeQueue into the pool.
|
||||||
|
func (p *writeQueuePool) put(q *writeQueue) {
|
||||||
|
for i := range q.s {
|
||||||
|
q.s[i] = FrameWriteRequest{}
|
||||||
|
}
|
||||||
|
q.s = q.s[:0]
|
||||||
|
*p = append(*p, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get returns an empty writeQueue.
|
||||||
|
func (p *writeQueuePool) get() *writeQueue {
|
||||||
|
ln := len(*p)
|
||||||
|
if ln == 0 {
|
||||||
|
return new(writeQueue)
|
||||||
|
}
|
||||||
|
x := ln - 1
|
||||||
|
q := (*p)[x]
|
||||||
|
(*p)[x] = nil
|
||||||
|
*p = (*p)[:x]
|
||||||
|
return q
|
||||||
|
}
|
452
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
Normal file
452
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
Normal file
|
@ -0,0 +1,452 @@
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RFC 7540, Section 5.3.5: the default weight is 16.
|
||||||
|
const priorityDefaultWeight = 15 // 16 = 15 + 1
|
||||||
|
|
||||||
|
// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
|
||||||
|
type PriorityWriteSchedulerConfig struct {
|
||||||
|
// MaxClosedNodesInTree controls the maximum number of closed streams to
|
||||||
|
// retain in the priority tree. Setting this to zero saves a small amount
|
||||||
|
// of memory at the cost of performance.
|
||||||
|
//
|
||||||
|
// See RFC 7540, Section 5.3.4:
|
||||||
|
// "It is possible for a stream to become closed while prioritization
|
||||||
|
// information ... is in transit. ... This potentially creates suboptimal
|
||||||
|
// prioritization, since the stream could be given a priority that is
|
||||||
|
// different from what is intended. To avoid these problems, an endpoint
|
||||||
|
// SHOULD retain stream prioritization state for a period after streams
|
||||||
|
// become closed. The longer state is retained, the lower the chance that
|
||||||
|
// streams are assigned incorrect or default priority values."
|
||||||
|
MaxClosedNodesInTree int
|
||||||
|
|
||||||
|
// MaxIdleNodesInTree controls the maximum number of idle streams to
|
||||||
|
// retain in the priority tree. Setting this to zero saves a small amount
|
||||||
|
// of memory at the cost of performance.
|
||||||
|
//
|
||||||
|
// See RFC 7540, Section 5.3.4:
|
||||||
|
// Similarly, streams that are in the "idle" state can be assigned
|
||||||
|
// priority or become a parent of other streams. This allows for the
|
||||||
|
// creation of a grouping node in the dependency tree, which enables
|
||||||
|
// more flexible expressions of priority. Idle streams begin with a
|
||||||
|
// default priority (Section 5.3.5).
|
||||||
|
MaxIdleNodesInTree int
|
||||||
|
|
||||||
|
// ThrottleOutOfOrderWrites enables write throttling to help ensure that
|
||||||
|
// data is delivered in priority order. This works around a race where
|
||||||
|
// stream B depends on stream A and both streams are about to call Write
|
||||||
|
// to queue DATA frames. If B wins the race, a naive scheduler would eagerly
|
||||||
|
// write as much data from B as possible, but this is suboptimal because A
|
||||||
|
// is a higher-priority stream. With throttling enabled, we write a small
|
||||||
|
// amount of data from B to minimize the amount of bandwidth that B can
|
||||||
|
// steal from A.
|
||||||
|
ThrottleOutOfOrderWrites bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
||||||
|
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
|
||||||
|
// If cfg is nil, default options are used.
|
||||||
|
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
||||||
|
if cfg == nil {
|
||||||
|
// For justification of these defaults, see:
|
||||||
|
// https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY
|
||||||
|
cfg = &PriorityWriteSchedulerConfig{
|
||||||
|
MaxClosedNodesInTree: 10,
|
||||||
|
MaxIdleNodesInTree: 10,
|
||||||
|
ThrottleOutOfOrderWrites: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws := &priorityWriteScheduler{
|
||||||
|
nodes: make(map[uint32]*priorityNode),
|
||||||
|
maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
|
||||||
|
maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
|
||||||
|
enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
|
||||||
|
}
|
||||||
|
ws.nodes[0] = &ws.root
|
||||||
|
if cfg.ThrottleOutOfOrderWrites {
|
||||||
|
ws.writeThrottleLimit = 1024
|
||||||
|
} else {
|
||||||
|
ws.writeThrottleLimit = math.MaxInt32
|
||||||
|
}
|
||||||
|
return ws
|
||||||
|
}
|
||||||
|
|
||||||
|
type priorityNodeState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
priorityNodeOpen priorityNodeState = iota
|
||||||
|
priorityNodeClosed
|
||||||
|
priorityNodeIdle
|
||||||
|
)
|
||||||
|
|
||||||
|
// priorityNode is a node in an HTTP/2 priority tree.
|
||||||
|
// Each node is associated with a single stream ID.
|
||||||
|
// See RFC 7540, Section 5.3.
|
||||||
|
type priorityNode struct {
|
||||||
|
q writeQueue // queue of pending frames to write
|
||||||
|
id uint32 // id of the stream, or 0 for the root of the tree
|
||||||
|
weight uint8 // the actual weight is weight+1, so the value is in [1,256]
|
||||||
|
state priorityNodeState // open | closed | idle
|
||||||
|
bytes int64 // number of bytes written by this node, or 0 if closed
|
||||||
|
subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
|
||||||
|
|
||||||
|
// These links form the priority tree.
|
||||||
|
parent *priorityNode
|
||||||
|
kids *priorityNode // start of the kids list
|
||||||
|
prev, next *priorityNode // doubly-linked list of siblings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *priorityNode) setParent(parent *priorityNode) {
|
||||||
|
if n == parent {
|
||||||
|
panic("setParent to self")
|
||||||
|
}
|
||||||
|
if n.parent == parent {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Unlink from current parent.
|
||||||
|
if parent := n.parent; parent != nil {
|
||||||
|
if n.prev == nil {
|
||||||
|
parent.kids = n.next
|
||||||
|
} else {
|
||||||
|
n.prev.next = n.next
|
||||||
|
}
|
||||||
|
if n.next != nil {
|
||||||
|
n.next.prev = n.prev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Link to new parent.
|
||||||
|
// If parent=nil, remove n from the tree.
|
||||||
|
// Always insert at the head of parent.kids (this is assumed by walkReadyInOrder).
|
||||||
|
n.parent = parent
|
||||||
|
if parent == nil {
|
||||||
|
n.next = nil
|
||||||
|
n.prev = nil
|
||||||
|
} else {
|
||||||
|
n.next = parent.kids
|
||||||
|
n.prev = nil
|
||||||
|
if n.next != nil {
|
||||||
|
n.next.prev = n
|
||||||
|
}
|
||||||
|
parent.kids = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *priorityNode) addBytes(b int64) {
|
||||||
|
n.bytes += b
|
||||||
|
for ; n != nil; n = n.parent {
|
||||||
|
n.subtreeBytes += b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// walkReadyInOrder iterates over the tree in priority order, calling f for each node
|
||||||
|
// with a non-empty write queue. When f returns true, this function returns true and the
|
||||||
|
// walk halts. tmp is used as scratch space for sorting.
|
||||||
|
//
|
||||||
|
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
|
||||||
|
// if any ancestor p of n is still open (ignoring the root node).
|
||||||
|
func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool {
|
||||||
|
if !n.q.empty() && f(n, openParent) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if n.kids == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't consider the root "open" when updating openParent since
|
||||||
|
// we can't send data frames on the root stream (only control frames).
|
||||||
|
if n.id != 0 {
|
||||||
|
openParent = openParent || (n.state == priorityNodeOpen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common case: only one kid or all kids have the same weight.
|
||||||
|
// Some clients don't use weights; other clients (like web browsers)
|
||||||
|
// use mostly-linear priority trees.
|
||||||
|
w := n.kids.weight
|
||||||
|
needSort := false
|
||||||
|
for k := n.kids.next; k != nil; k = k.next {
|
||||||
|
if k.weight != w {
|
||||||
|
needSort = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !needSort {
|
||||||
|
for k := n.kids; k != nil; k = k.next {
|
||||||
|
if k.walkReadyInOrder(openParent, tmp, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncommon case: sort the child nodes. We remove the kids from the parent,
|
||||||
|
// then re-insert after sorting so we can reuse tmp for future sort calls.
|
||||||
|
*tmp = (*tmp)[:0]
|
||||||
|
for n.kids != nil {
|
||||||
|
*tmp = append(*tmp, n.kids)
|
||||||
|
n.kids.setParent(nil)
|
||||||
|
}
|
||||||
|
sort.Sort(sortPriorityNodeSiblings(*tmp))
|
||||||
|
for i := len(*tmp) - 1; i >= 0; i-- {
|
||||||
|
(*tmp)[i].setParent(n) // setParent inserts at the head of n.kids
|
||||||
|
}
|
||||||
|
for k := n.kids; k != nil; k = k.next {
|
||||||
|
if k.walkReadyInOrder(openParent, tmp, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortPriorityNodeSiblings []*priorityNode
|
||||||
|
|
||||||
|
func (z sortPriorityNodeSiblings) Len() int { return len(z) }
|
||||||
|
func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
|
||||||
|
func (z sortPriorityNodeSiblings) Less(i, k int) bool {
|
||||||
|
// Prefer the subtree that has sent fewer bytes relative to its weight.
|
||||||
|
// See sections 5.3.2 and 5.3.4.
|
||||||
|
wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
|
||||||
|
wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
|
||||||
|
if bi == 0 && bk == 0 {
|
||||||
|
return wi >= wk
|
||||||
|
}
|
||||||
|
if bk == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return bi/bk <= wi/wk
|
||||||
|
}
|
||||||
|
|
||||||
|
type priorityWriteScheduler struct {
|
||||||
|
// root is the root of the priority tree, where root.id = 0.
|
||||||
|
// The root queues control frames that are not associated with any stream.
|
||||||
|
root priorityNode
|
||||||
|
|
||||||
|
// nodes maps stream ids to priority tree nodes.
|
||||||
|
nodes map[uint32]*priorityNode
|
||||||
|
|
||||||
|
// maxID is the maximum stream id in nodes.
|
||||||
|
maxID uint32
|
||||||
|
|
||||||
|
// lists of nodes that have been closed or are idle, but are kept in
|
||||||
|
// the tree for improved prioritization. When the lengths exceed either
|
||||||
|
// maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
|
||||||
|
closedNodes, idleNodes []*priorityNode
|
||||||
|
|
||||||
|
// From the config.
|
||||||
|
maxClosedNodesInTree int
|
||||||
|
maxIdleNodesInTree int
|
||||||
|
writeThrottleLimit int32
|
||||||
|
enableWriteThrottle bool
|
||||||
|
|
||||||
|
// tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
|
||||||
|
tmp []*priorityNode
|
||||||
|
|
||||||
|
// pool of empty queues for reuse.
|
||||||
|
queuePool writeQueuePool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
|
||||||
|
// The stream may be currently idle but cannot be opened or closed.
|
||||||
|
if curr := ws.nodes[streamID]; curr != nil {
|
||||||
|
if curr.state != priorityNodeIdle {
|
||||||
|
panic(fmt.Sprintf("stream %d already opened", streamID))
|
||||||
|
}
|
||||||
|
curr.state = priorityNodeOpen
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 7540, Section 5.3.5:
|
||||||
|
// "All streams are initially assigned a non-exclusive dependency on stream 0x0.
|
||||||
|
// Pushed streams initially depend on their associated stream. In both cases,
|
||||||
|
// streams are assigned a default weight of 16."
|
||||||
|
parent := ws.nodes[options.PusherID]
|
||||||
|
if parent == nil {
|
||||||
|
parent = &ws.root
|
||||||
|
}
|
||||||
|
n := &priorityNode{
|
||||||
|
q: *ws.queuePool.get(),
|
||||||
|
id: streamID,
|
||||||
|
weight: priorityDefaultWeight,
|
||||||
|
state: priorityNodeOpen,
|
||||||
|
}
|
||||||
|
n.setParent(parent)
|
||||||
|
ws.nodes[streamID] = n
|
||||||
|
if streamID > ws.maxID {
|
||||||
|
ws.maxID = streamID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
|
||||||
|
if streamID == 0 {
|
||||||
|
panic("violation of WriteScheduler interface: cannot close stream 0")
|
||||||
|
}
|
||||||
|
if ws.nodes[streamID] == nil {
|
||||||
|
panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
|
||||||
|
}
|
||||||
|
if ws.nodes[streamID].state != priorityNodeOpen {
|
||||||
|
panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
|
||||||
|
}
|
||||||
|
|
||||||
|
n := ws.nodes[streamID]
|
||||||
|
n.state = priorityNodeClosed
|
||||||
|
n.addBytes(-n.bytes)
|
||||||
|
|
||||||
|
q := n.q
|
||||||
|
ws.queuePool.put(&q)
|
||||||
|
n.q.s = nil
|
||||||
|
if ws.maxClosedNodesInTree > 0 {
|
||||||
|
ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
|
||||||
|
} else {
|
||||||
|
ws.removeNode(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
|
||||||
|
if streamID == 0 {
|
||||||
|
panic("adjustPriority on root")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If streamID does not exist, there are two cases:
|
||||||
|
// - A closed stream that has been removed (this will have ID <= maxID)
|
||||||
|
// - An idle stream that is being used for "grouping" (this will have ID > maxID)
|
||||||
|
n := ws.nodes[streamID]
|
||||||
|
if n == nil {
|
||||||
|
if streamID <= ws.maxID || ws.maxIdleNodesInTree == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ws.maxID = streamID
|
||||||
|
n = &priorityNode{
|
||||||
|
q: *ws.queuePool.get(),
|
||||||
|
id: streamID,
|
||||||
|
weight: priorityDefaultWeight,
|
||||||
|
state: priorityNodeIdle,
|
||||||
|
}
|
||||||
|
n.setParent(&ws.root)
|
||||||
|
ws.nodes[streamID] = n
|
||||||
|
ws.addClosedOrIdleNode(&ws.idleNodes, ws.maxIdleNodesInTree, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section 5.3.1: A dependency on a stream that is not currently in the tree
|
||||||
|
// results in that stream being given a default priority (Section 5.3.5).
|
||||||
|
parent := ws.nodes[priority.StreamDep]
|
||||||
|
if parent == nil {
|
||||||
|
n.setParent(&ws.root)
|
||||||
|
n.weight = priorityDefaultWeight
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore if the client tries to make a node its own parent.
|
||||||
|
if n == parent {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section 5.3.3:
|
||||||
|
// "If a stream is made dependent on one of its own dependencies, the
|
||||||
|
// formerly dependent stream is first moved to be dependent on the
|
||||||
|
// reprioritized stream's previous parent. The moved dependency retains
|
||||||
|
// its weight."
|
||||||
|
//
|
||||||
|
// That is: if parent depends on n, move parent to depend on n.parent.
|
||||||
|
for x := parent.parent; x != nil; x = x.parent {
|
||||||
|
if x == n {
|
||||||
|
parent.setParent(n.parent)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section 5.3.3: The exclusive flag causes the stream to become the sole
|
||||||
|
// dependency of its parent stream, causing other dependencies to become
|
||||||
|
// dependent on the exclusive stream.
|
||||||
|
if priority.Exclusive {
|
||||||
|
k := parent.kids
|
||||||
|
for k != nil {
|
||||||
|
next := k.next
|
||||||
|
if k != n {
|
||||||
|
k.setParent(n)
|
||||||
|
}
|
||||||
|
k = next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n.setParent(parent)
|
||||||
|
n.weight = priority.Weight
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
|
||||||
|
var n *priorityNode
|
||||||
|
if id := wr.StreamID(); id == 0 {
|
||||||
|
n = &ws.root
|
||||||
|
} else {
|
||||||
|
n = ws.nodes[id]
|
||||||
|
if n == nil {
|
||||||
|
// id is an idle or closed stream. wr should not be a HEADERS or
|
||||||
|
// DATA frame. However, wr can be a RST_STREAM. In this case, we
|
||||||
|
// push wr onto the root, rather than creating a new priorityNode,
|
||||||
|
// since RST_STREAM is tiny and the stream's priority is unknown
|
||||||
|
// anyway. See issue #17919.
|
||||||
|
if wr.DataSize() > 0 {
|
||||||
|
panic("add DATA on non-open stream")
|
||||||
|
}
|
||||||
|
n = &ws.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n.q.push(wr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
|
||||||
|
ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool {
|
||||||
|
limit := int32(math.MaxInt32)
|
||||||
|
if openParent {
|
||||||
|
limit = ws.writeThrottleLimit
|
||||||
|
}
|
||||||
|
wr, ok = n.q.consume(limit)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
n.addBytes(int64(wr.DataSize()))
|
||||||
|
// If B depends on A and B continuously has data available but A
|
||||||
|
// does not, gradually increase the throttling limit to allow B to
|
||||||
|
// steal more and more bandwidth from A.
|
||||||
|
if openParent {
|
||||||
|
ws.writeThrottleLimit += 1024
|
||||||
|
if ws.writeThrottleLimit < 0 {
|
||||||
|
ws.writeThrottleLimit = math.MaxInt32
|
||||||
|
}
|
||||||
|
} else if ws.enableWriteThrottle {
|
||||||
|
ws.writeThrottleLimit = 1024
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return wr, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) {
|
||||||
|
if maxSize == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(*list) == maxSize {
|
||||||
|
// Remove the oldest node, then shift left.
|
||||||
|
ws.removeNode((*list)[0])
|
||||||
|
x := (*list)[1:]
|
||||||
|
copy(*list, x)
|
||||||
|
*list = (*list)[:len(x)]
|
||||||
|
}
|
||||||
|
*list = append(*list, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
|
||||||
|
for k := n.kids; k != nil; k = k.next {
|
||||||
|
k.setParent(n.parent)
|
||||||
|
}
|
||||||
|
n.setParent(nil)
|
||||||
|
delete(ws.nodes, n.id)
|
||||||
|
}
|
77
vendor/golang.org/x/net/http2/writesched_random.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/http2/writesched_random.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2
|
||||||
|
// priorities. Control frames like SETTINGS and PING are written before DATA
|
||||||
|
// frames, but if no control frames are queued and multiple streams have queued
|
||||||
|
// HEADERS or DATA frames, Pop selects a ready stream arbitrarily.
|
||||||
|
func NewRandomWriteScheduler() WriteScheduler {
|
||||||
|
return &randomWriteScheduler{sq: make(map[uint32]*writeQueue)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type randomWriteScheduler struct {
|
||||||
|
// zero are frames not associated with a specific stream.
|
||||||
|
zero writeQueue
|
||||||
|
|
||||||
|
// sq contains the stream-specific queues, keyed by stream ID.
|
||||||
|
// When a stream is idle, closed, or emptied, it's deleted
|
||||||
|
// from the map.
|
||||||
|
sq map[uint32]*writeQueue
|
||||||
|
|
||||||
|
// pool of empty queues for reuse.
|
||||||
|
queuePool writeQueuePool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *randomWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
|
||||||
|
// no-op: idle streams are not tracked
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *randomWriteScheduler) CloseStream(streamID uint32) {
|
||||||
|
q, ok := ws.sq[streamID]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(ws.sq, streamID)
|
||||||
|
ws.queuePool.put(q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
|
||||||
|
// no-op: priorities are ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
|
||||||
|
id := wr.StreamID()
|
||||||
|
if id == 0 {
|
||||||
|
ws.zero.push(wr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
q, ok := ws.sq[id]
|
||||||
|
if !ok {
|
||||||
|
q = ws.queuePool.get()
|
||||||
|
ws.sq[id] = q
|
||||||
|
}
|
||||||
|
q.push(wr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
|
||||||
|
// Control frames first.
|
||||||
|
if !ws.zero.empty() {
|
||||||
|
return ws.zero.shift(), true
|
||||||
|
}
|
||||||
|
// Iterate over all non-idle streams until finding one that can be consumed.
|
||||||
|
for streamID, q := range ws.sq {
|
||||||
|
if wr, ok := q.consume(math.MaxInt32); ok {
|
||||||
|
if q.empty() {
|
||||||
|
delete(ws.sq, streamID)
|
||||||
|
ws.queuePool.put(q)
|
||||||
|
}
|
||||||
|
return wr, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FrameWriteRequest{}, false
|
||||||
|
}
|
2
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
2
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
|
@ -486,7 +486,7 @@ ccflags="$@"
|
||||||
$2 ~ /^TCSET/ ||
|
$2 ~ /^TCSET/ ||
|
||||||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
|
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
|
||||||
$2 !~ "RTF_BITS" &&
|
$2 !~ "RTF_BITS" &&
|
||||||
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
|
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
|
||||||
$2 ~ /^BIOC/ ||
|
$2 ~ /^BIOC/ ||
|
||||||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
|
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
|
||||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
4
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
|
@ -1555,8 +1555,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
//sys Acct(path string) (err error)
|
//sys Acct(path string) (err error)
|
||||||
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
|
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
|
||||||
//sys Adjtimex(buf *Timex) (state int, err error)
|
//sys Adjtimex(buf *Timex) (state int, err error)
|
||||||
//sys Capget(hdr *CapUserHeader, data *CapUserData) (err error)
|
//sysnb Capget(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||||
//sys Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||||
//sys Chdir(path string) (err error)
|
//sys Chdir(path string) (err error)
|
||||||
//sys Chroot(path string) (err error)
|
//sys Chroot(path string) (err error)
|
||||||
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
generated
vendored
4
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
generated
vendored
|
@ -216,6 +216,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
||||||
cmsg.Len = uint64(length)
|
cmsg.Len = uint64(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InotifyInit() (fd int, err error) {
|
||||||
|
return InotifyInit1(0)
|
||||||
|
}
|
||||||
|
|
||||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||||
|
|
||||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
|
@ -1938,6 +1938,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
|
@ -1939,6 +1939,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
|
@ -1945,6 +1945,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
|
@ -1931,6 +1931,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
|
@ -1938,6 +1938,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
|
@ -1938,6 +1938,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
|
@ -1938,6 +1938,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
|
@ -1938,6 +1938,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
|
@ -1997,6 +1997,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
|
@ -1997,6 +1997,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
|
@ -1926,6 +1926,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
|
@ -1999,6 +1999,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
15
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
15
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
|
@ -1992,6 +1992,21 @@ const (
|
||||||
RTF_UP = 0x1
|
RTF_UP = 0x1
|
||||||
RTF_WINDOW = 0x80
|
RTF_WINDOW = 0x80
|
||||||
RTF_XRESOLVE = 0x800
|
RTF_XRESOLVE = 0x800
|
||||||
|
RTMGRP_DECnet_IFADDR = 0x1000
|
||||||
|
RTMGRP_DECnet_ROUTE = 0x4000
|
||||||
|
RTMGRP_IPV4_IFADDR = 0x10
|
||||||
|
RTMGRP_IPV4_MROUTE = 0x20
|
||||||
|
RTMGRP_IPV4_ROUTE = 0x40
|
||||||
|
RTMGRP_IPV4_RULE = 0x80
|
||||||
|
RTMGRP_IPV6_IFADDR = 0x100
|
||||||
|
RTMGRP_IPV6_IFINFO = 0x800
|
||||||
|
RTMGRP_IPV6_MROUTE = 0x200
|
||||||
|
RTMGRP_IPV6_PREFIX = 0x20000
|
||||||
|
RTMGRP_IPV6_ROUTE = 0x400
|
||||||
|
RTMGRP_LINK = 0x1
|
||||||
|
RTMGRP_NEIGH = 0x4
|
||||||
|
RTMGRP_NOTIFY = 0x2
|
||||||
|
RTMGRP_TC = 0x8
|
||||||
RTM_BASE = 0x10
|
RTM_BASE = 0x10
|
||||||
RTM_DELACTION = 0x31
|
RTM_DELACTION = 0x31
|
||||||
RTM_DELADDR = 0x15
|
RTM_DELADDR = 0x15
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
4
vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go
generated
vendored
|
@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
|
||||||
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
}
|
}
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int32
|
type Time_t int32
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int32
|
type Time_t int32
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int32
|
type Time_t int32
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int32
|
type Time_t int32
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
|
@ -55,6 +55,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
10
vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
generated
vendored
|
@ -56,6 +56,16 @@ type Timex struct {
|
||||||
_ [44]byte
|
_ [44]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIME_OK = 0x0
|
||||||
|
TIME_INS = 0x1
|
||||||
|
TIME_DEL = 0x2
|
||||||
|
TIME_OOP = 0x3
|
||||||
|
TIME_WAIT = 0x4
|
||||||
|
TIME_ERROR = 0x5
|
||||||
|
TIME_BAD = 0x5
|
||||||
|
)
|
||||||
|
|
||||||
type Time_t int64
|
type Time_t int64
|
||||||
|
|
||||||
type Tms struct {
|
type Tms struct {
|
||||||
|
|
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
|
@ -94,7 +94,7 @@ github.com/inconshreveable/mousetrap
|
||||||
# github.com/jgautheron/goconst v0.0.0-20200227150835-cda7ea3bf591
|
# github.com/jgautheron/goconst v0.0.0-20200227150835-cda7ea3bf591
|
||||||
github.com/jgautheron/goconst
|
github.com/jgautheron/goconst
|
||||||
github.com/jgautheron/goconst/cmd/goconst
|
github.com/jgautheron/goconst/cmd/goconst
|
||||||
# github.com/labstack/echo/v4 v4.1.14
|
# github.com/labstack/echo/v4 v4.1.16
|
||||||
github.com/labstack/echo/v4
|
github.com/labstack/echo/v4
|
||||||
github.com/labstack/echo/v4/middleware
|
github.com/labstack/echo/v4/middleware
|
||||||
# github.com/labstack/gommon v0.3.0
|
# github.com/labstack/gommon v0.3.0
|
||||||
|
@ -114,7 +114,7 @@ github.com/magiconair/properties
|
||||||
github.com/mailru/easyjson/buffer
|
github.com/mailru/easyjson/buffer
|
||||||
github.com/mailru/easyjson/jlexer
|
github.com/mailru/easyjson/jlexer
|
||||||
github.com/mailru/easyjson/jwriter
|
github.com/mailru/easyjson/jwriter
|
||||||
# github.com/mattn/go-colorable v0.1.4
|
# github.com/mattn/go-colorable v0.1.6
|
||||||
github.com/mattn/go-colorable
|
github.com/mattn/go-colorable
|
||||||
# github.com/mattn/go-isatty v0.0.12
|
# github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mattn/go-isatty
|
github.com/mattn/go-isatty
|
||||||
|
@ -211,9 +211,13 @@ golang.org/x/crypto/blowfish
|
||||||
# golang.org/x/lint v0.0.0-20200302205851-738671d3881b
|
# golang.org/x/lint v0.0.0-20200302205851-738671d3881b
|
||||||
golang.org/x/lint
|
golang.org/x/lint
|
||||||
golang.org/x/lint/golint
|
golang.org/x/lint/golint
|
||||||
# golang.org/x/net v0.0.0-20200202094626-16171245cfb2
|
# golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
||||||
|
golang.org/x/net/http/httpguts
|
||||||
|
golang.org/x/net/http2
|
||||||
|
golang.org/x/net/http2/h2c
|
||||||
|
golang.org/x/net/http2/hpack
|
||||||
golang.org/x/net/idna
|
golang.org/x/net/idna
|
||||||
# golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5
|
# golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
# golang.org/x/text v0.3.2
|
# golang.org/x/text v0.3.2
|
||||||
golang.org/x/text/secure/bidirule
|
golang.org/x/text/secure/bidirule
|
||||||
|
|
Loading…
Reference in a new issue