Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
songlinfeng
k8s-device-plugin
Commits
8a683270
Commit
8a683270
authored
Nov 25, 2025
by
songlinfeng
💬
Browse files
add k8s-device-plugin
parent
f5f6fd20
Changes
165
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
4180 additions
and
0 deletions
+4180
-0
vendor/golang.org/x/net/context/context.go
vendor/golang.org/x/net/context/context.go
+56
-0
vendor/golang.org/x/net/context/go17.go
vendor/golang.org/x/net/context/go17.go
+72
-0
vendor/golang.org/x/net/context/go19.go
vendor/golang.org/x/net/context/go19.go
+20
-0
vendor/golang.org/x/net/context/pre_go17.go
vendor/golang.org/x/net/context/pre_go17.go
+300
-0
vendor/golang.org/x/net/context/pre_go19.go
vendor/golang.org/x/net/context/pre_go19.go
+109
-0
vendor/golang.org/x/net/http/httpguts/guts.go
vendor/golang.org/x/net/http/httpguts/guts.go
+50
-0
vendor/golang.org/x/net/http/httpguts/httplex.go
vendor/golang.org/x/net/http/httpguts/httplex.go
+346
-0
vendor/golang.org/x/net/http2/.gitignore
vendor/golang.org/x/net/http2/.gitignore
+2
-0
vendor/golang.org/x/net/http2/Dockerfile
vendor/golang.org/x/net/http2/Dockerfile
+51
-0
vendor/golang.org/x/net/http2/Makefile
vendor/golang.org/x/net/http2/Makefile
+3
-0
vendor/golang.org/x/net/http2/README
vendor/golang.org/x/net/http2/README
+20
-0
vendor/golang.org/x/net/http2/ciphers.go
vendor/golang.org/x/net/http2/ciphers.go
+641
-0
vendor/golang.org/x/net/http2/client_conn_pool.go
vendor/golang.org/x/net/http2/client_conn_pool.go
+278
-0
vendor/golang.org/x/net/http2/databuffer.go
vendor/golang.org/x/net/http2/databuffer.go
+146
-0
vendor/golang.org/x/net/http2/errors.go
vendor/golang.org/x/net/http2/errors.go
+133
-0
vendor/golang.org/x/net/http2/flow.go
vendor/golang.org/x/net/http2/flow.go
+52
-0
vendor/golang.org/x/net/http2/frame.go
vendor/golang.org/x/net/http2/frame.go
+1614
-0
vendor/golang.org/x/net/http2/go111.go
vendor/golang.org/x/net/http2/go111.go
+29
-0
vendor/golang.org/x/net/http2/gotrack.go
vendor/golang.org/x/net/http2/gotrack.go
+170
-0
vendor/golang.org/x/net/http2/headermap.go
vendor/golang.org/x/net/http2/headermap.go
+88
-0
No files found.
Too many changes to show.
To preserve performance only
165 of 165+
files are displayed.
Plain diff
Email patch
vendor/golang.org/x/net/context/context.go
0 → 100644
View file @
8a683270
// 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 context defines the Context type, which carries deadlines,
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
// As of Go 1.7 this package is available in the standard library under the
// name context. https://golang.org/pkg/context.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context. The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
//
// func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ...
// }
//
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The same Context may be passed to functions running in different goroutines;
// Contexts are safe for simultaneous use by multiple goroutines.
//
// See http://blog.golang.org/context for example code for a server that uses
// Contexts.
package
context
// import "golang.org/x/net/context"
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func
Background
()
Context
{
return
background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func
TODO
()
Context
{
return
todo
}
vendor/golang.org/x/net/context/go17.go
0 → 100644
View file @
8a683270
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7
package
context
import
(
"context"
// standard library's context, as of Go 1.7
"time"
)
var
(
todo
=
context
.
TODO
()
background
=
context
.
Background
()
)
// Canceled is the error returned by Context.Err when the context is canceled.
var
Canceled
=
context
.
Canceled
// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var
DeadlineExceeded
=
context
.
DeadlineExceeded
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func
WithCancel
(
parent
Context
)
(
ctx
Context
,
cancel
CancelFunc
)
{
ctx
,
f
:=
context
.
WithCancel
(
parent
)
return
ctx
,
CancelFunc
(
f
)
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func
WithDeadline
(
parent
Context
,
deadline
time
.
Time
)
(
Context
,
CancelFunc
)
{
ctx
,
f
:=
context
.
WithDeadline
(
parent
,
deadline
)
return
ctx
,
CancelFunc
(
f
)
}
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete:
//
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
func
WithTimeout
(
parent
Context
,
timeout
time
.
Duration
)
(
Context
,
CancelFunc
)
{
return
WithDeadline
(
parent
,
time
.
Now
()
.
Add
(
timeout
))
}
// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func
WithValue
(
parent
Context
,
key
interface
{},
val
interface
{})
Context
{
return
context
.
WithValue
(
parent
,
key
,
val
)
}
vendor/golang.org/x/net/context/go19.go
0 → 100644
View file @
8a683270
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package
context
import
"context"
// standard library's context, as of Go 1.7
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type
Context
=
context
.
Context
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type
CancelFunc
=
context
.
CancelFunc
vendor/golang.org/x/net/context/pre_go17.go
0 → 100644
View file @
8a683270
// 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.
// +build !go1.7
package
context
import
(
"errors"
"fmt"
"sync"
"time"
)
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type
emptyCtx
int
func
(
*
emptyCtx
)
Deadline
()
(
deadline
time
.
Time
,
ok
bool
)
{
return
}
func
(
*
emptyCtx
)
Done
()
<-
chan
struct
{}
{
return
nil
}
func
(
*
emptyCtx
)
Err
()
error
{
return
nil
}
func
(
*
emptyCtx
)
Value
(
key
interface
{})
interface
{}
{
return
nil
}
func
(
e
*
emptyCtx
)
String
()
string
{
switch
e
{
case
background
:
return
"context.Background"
case
todo
:
return
"context.TODO"
}
return
"unknown empty Context"
}
var
(
background
=
new
(
emptyCtx
)
todo
=
new
(
emptyCtx
)
)
// Canceled is the error returned by Context.Err when the context is canceled.
var
Canceled
=
errors
.
New
(
"context canceled"
)
// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var
DeadlineExceeded
=
errors
.
New
(
"context deadline exceeded"
)
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func
WithCancel
(
parent
Context
)
(
ctx
Context
,
cancel
CancelFunc
)
{
c
:=
newCancelCtx
(
parent
)
propagateCancel
(
parent
,
c
)
return
c
,
func
()
{
c
.
cancel
(
true
,
Canceled
)
}
}
// newCancelCtx returns an initialized cancelCtx.
func
newCancelCtx
(
parent
Context
)
*
cancelCtx
{
return
&
cancelCtx
{
Context
:
parent
,
done
:
make
(
chan
struct
{}),
}
}
// propagateCancel arranges for child to be canceled when parent is.
func
propagateCancel
(
parent
Context
,
child
canceler
)
{
if
parent
.
Done
()
==
nil
{
return
// parent is never canceled
}
if
p
,
ok
:=
parentCancelCtx
(
parent
);
ok
{
p
.
mu
.
Lock
()
if
p
.
err
!=
nil
{
// parent has already been canceled
child
.
cancel
(
false
,
p
.
err
)
}
else
{
if
p
.
children
==
nil
{
p
.
children
=
make
(
map
[
canceler
]
bool
)
}
p
.
children
[
child
]
=
true
}
p
.
mu
.
Unlock
()
}
else
{
go
func
()
{
select
{
case
<-
parent
.
Done
()
:
child
.
cancel
(
false
,
parent
.
Err
())
case
<-
child
.
Done
()
:
}
}()
}
}
// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx. This function understands how each of the concrete types in this
// package represents its parent.
func
parentCancelCtx
(
parent
Context
)
(
*
cancelCtx
,
bool
)
{
for
{
switch
c
:=
parent
.
(
type
)
{
case
*
cancelCtx
:
return
c
,
true
case
*
timerCtx
:
return
c
.
cancelCtx
,
true
case
*
valueCtx
:
parent
=
c
.
Context
default
:
return
nil
,
false
}
}
}
// removeChild removes a context from its parent.
func
removeChild
(
parent
Context
,
child
canceler
)
{
p
,
ok
:=
parentCancelCtx
(
parent
)
if
!
ok
{
return
}
p
.
mu
.
Lock
()
if
p
.
children
!=
nil
{
delete
(
p
.
children
,
child
)
}
p
.
mu
.
Unlock
()
}
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type
canceler
interface
{
cancel
(
removeFromParent
bool
,
err
error
)
Done
()
<-
chan
struct
{}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type
cancelCtx
struct
{
Context
done
chan
struct
{}
// closed by the first cancel call.
mu
sync
.
Mutex
children
map
[
canceler
]
bool
// set to nil by the first cancel call
err
error
// set to non-nil by the first cancel call
}
func
(
c
*
cancelCtx
)
Done
()
<-
chan
struct
{}
{
return
c
.
done
}
func
(
c
*
cancelCtx
)
Err
()
error
{
c
.
mu
.
Lock
()
defer
c
.
mu
.
Unlock
()
return
c
.
err
}
func
(
c
*
cancelCtx
)
String
()
string
{
return
fmt
.
Sprintf
(
"%v.WithCancel"
,
c
.
Context
)
}
// cancel closes c.done, cancels each of c's children, and, if
// removeFromParent is true, removes c from its parent's children.
func
(
c
*
cancelCtx
)
cancel
(
removeFromParent
bool
,
err
error
)
{
if
err
==
nil
{
panic
(
"context: internal error: missing cancel error"
)
}
c
.
mu
.
Lock
()
if
c
.
err
!=
nil
{
c
.
mu
.
Unlock
()
return
// already canceled
}
c
.
err
=
err
close
(
c
.
done
)
for
child
:=
range
c
.
children
{
// NOTE: acquiring the child's lock while holding parent's lock.
child
.
cancel
(
false
,
err
)
}
c
.
children
=
nil
c
.
mu
.
Unlock
()
if
removeFromParent
{
removeChild
(
c
.
Context
,
c
)
}
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func
WithDeadline
(
parent
Context
,
deadline
time
.
Time
)
(
Context
,
CancelFunc
)
{
if
cur
,
ok
:=
parent
.
Deadline
();
ok
&&
cur
.
Before
(
deadline
)
{
// The current deadline is already sooner than the new one.
return
WithCancel
(
parent
)
}
c
:=
&
timerCtx
{
cancelCtx
:
newCancelCtx
(
parent
),
deadline
:
deadline
,
}
propagateCancel
(
parent
,
c
)
d
:=
deadline
.
Sub
(
time
.
Now
())
if
d
<=
0
{
c
.
cancel
(
true
,
DeadlineExceeded
)
// deadline has already passed
return
c
,
func
()
{
c
.
cancel
(
true
,
Canceled
)
}
}
c
.
mu
.
Lock
()
defer
c
.
mu
.
Unlock
()
if
c
.
err
==
nil
{
c
.
timer
=
time
.
AfterFunc
(
d
,
func
()
{
c
.
cancel
(
true
,
DeadlineExceeded
)
})
}
return
c
,
func
()
{
c
.
cancel
(
true
,
Canceled
)
}
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type
timerCtx
struct
{
*
cancelCtx
timer
*
time
.
Timer
// Under cancelCtx.mu.
deadline
time
.
Time
}
func
(
c
*
timerCtx
)
Deadline
()
(
deadline
time
.
Time
,
ok
bool
)
{
return
c
.
deadline
,
true
}
func
(
c
*
timerCtx
)
String
()
string
{
return
fmt
.
Sprintf
(
"%v.WithDeadline(%s [%s])"
,
c
.
cancelCtx
.
Context
,
c
.
deadline
,
c
.
deadline
.
Sub
(
time
.
Now
()))
}
func
(
c
*
timerCtx
)
cancel
(
removeFromParent
bool
,
err
error
)
{
c
.
cancelCtx
.
cancel
(
false
,
err
)
if
removeFromParent
{
// Remove this timerCtx from its parent cancelCtx's children.
removeChild
(
c
.
cancelCtx
.
Context
,
c
)
}
c
.
mu
.
Lock
()
if
c
.
timer
!=
nil
{
c
.
timer
.
Stop
()
c
.
timer
=
nil
}
c
.
mu
.
Unlock
()
}
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete:
//
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
func
WithTimeout
(
parent
Context
,
timeout
time
.
Duration
)
(
Context
,
CancelFunc
)
{
return
WithDeadline
(
parent
,
time
.
Now
()
.
Add
(
timeout
))
}
// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func
WithValue
(
parent
Context
,
key
interface
{},
val
interface
{})
Context
{
return
&
valueCtx
{
parent
,
key
,
val
}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type
valueCtx
struct
{
Context
key
,
val
interface
{}
}
func
(
c
*
valueCtx
)
String
()
string
{
return
fmt
.
Sprintf
(
"%v.WithValue(%#v, %#v)"
,
c
.
Context
,
c
.
key
,
c
.
val
)
}
func
(
c
*
valueCtx
)
Value
(
key
interface
{})
interface
{}
{
if
c
.
key
==
key
{
return
c
.
val
}
return
c
.
Context
.
Value
(
key
)
}
vendor/golang.org/x/net/context/pre_go19.go
0 → 100644
View file @
8a683270
// 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.
// +build !go1.9
package
context
import
"time"
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type
Context
interface
{
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline
()
(
deadline
time
.
Time
,
ok
bool
)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See http://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done
()
<-
chan
struct
{}
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err
()
error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "golang.org/x/net/context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value
(
key
interface
{})
interface
{}
}
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type
CancelFunc
func
()
vendor/golang.org/x/net/http/httpguts/guts.go
0 → 100644
View file @
8a683270
// 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
,
}
vendor/golang.org/x/net/http/httpguts/httplex.go
0 → 100644
View file @
8a683270
// 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
}
vendor/golang.org/x/net/http2/.gitignore
0 → 100644
View file @
8a683270
*~
h2i/h2i
vendor/golang.org/x/net/http2/Dockerfile
0 → 100644
View file @
8a683270
#
# 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"]
vendor/golang.org/x/net/http2/Makefile
0 → 100644
View file @
8a683270
curlimage
:
docker build
-t
gohttp2/curl .
vendor/golang.org/x/net/http2/README
0 → 100644
View file @
8a683270
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:+
vendor/golang.org/x/net/http2/ciphers.go
0 → 100644
View file @
8a683270
// 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
}
}
vendor/golang.org/x/net/http2/client_conn_pool.go
0 → 100644
View file @
8a683270
// 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
{
_
incomparable
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
{
_
incomparable
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
)
}
// 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
)
}
vendor/golang.org/x/net/http2/databuffer.go
0 → 100644
View file @
8a683270
// 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
}
vendor/golang.org/x/net/http2/errors.go
0 → 100644
View file @
8a683270
// 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"
)
)
vendor/golang.org/x/net/http2/flow.go
0 → 100644
View file @
8a683270
// 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
{
_
incomparable
// 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
}
vendor/golang.org/x/net/http2/frame.go
0 → 100644
View file @
8a683270
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
http2
import
(
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"log"
"strings"
"sync"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack"
)
const
frameHeaderLen
=
9
var
padZeros
=
make
([]
byte
,
255
)
// zeros for padding
// A FrameType is a registered frame type as defined in
// http://http2.github.io/http2-spec/#rfc.section.11.2
type
FrameType
uint8
const
(
FrameData
FrameType
=
0x0
FrameHeaders
FrameType
=
0x1
FramePriority
FrameType
=
0x2
FrameRSTStream
FrameType
=
0x3
FrameSettings
FrameType
=
0x4
FramePushPromise
FrameType
=
0x5
FramePing
FrameType
=
0x6
FrameGoAway
FrameType
=
0x7
FrameWindowUpdate
FrameType
=
0x8
FrameContinuation
FrameType
=
0x9
)
var
frameName
=
map
[
FrameType
]
string
{
FrameData
:
"DATA"
,
FrameHeaders
:
"HEADERS"
,
FramePriority
:
"PRIORITY"
,
FrameRSTStream
:
"RST_STREAM"
,
FrameSettings
:
"SETTINGS"
,
FramePushPromise
:
"PUSH_PROMISE"
,
FramePing
:
"PING"
,
FrameGoAway
:
"GOAWAY"
,
FrameWindowUpdate
:
"WINDOW_UPDATE"
,
FrameContinuation
:
"CONTINUATION"
,
}
func
(
t
FrameType
)
String
()
string
{
if
s
,
ok
:=
frameName
[
t
];
ok
{
return
s
}
return
fmt
.
Sprintf
(
"UNKNOWN_FRAME_TYPE_%d"
,
uint8
(
t
))
}
// Flags is a bitmask of HTTP/2 flags.
// The meaning of flags varies depending on the frame type.
type
Flags
uint8
// Has reports whether f contains all (0 or more) flags in v.
func
(
f
Flags
)
Has
(
v
Flags
)
bool
{
return
(
f
&
v
)
==
v
}
// Frame-specific FrameHeader flag bits.
const
(
// Data Frame
FlagDataEndStream
Flags
=
0x1
FlagDataPadded
Flags
=
0x8
// Headers Frame
FlagHeadersEndStream
Flags
=
0x1
FlagHeadersEndHeaders
Flags
=
0x4
FlagHeadersPadded
Flags
=
0x8
FlagHeadersPriority
Flags
=
0x20
// Settings Frame
FlagSettingsAck
Flags
=
0x1
// Ping Frame
FlagPingAck
Flags
=
0x1
// Continuation Frame
FlagContinuationEndHeaders
Flags
=
0x4
FlagPushPromiseEndHeaders
Flags
=
0x4
FlagPushPromisePadded
Flags
=
0x8
)
var
flagName
=
map
[
FrameType
]
map
[
Flags
]
string
{
FrameData
:
{
FlagDataEndStream
:
"END_STREAM"
,
FlagDataPadded
:
"PADDED"
,
},
FrameHeaders
:
{
FlagHeadersEndStream
:
"END_STREAM"
,
FlagHeadersEndHeaders
:
"END_HEADERS"
,
FlagHeadersPadded
:
"PADDED"
,
FlagHeadersPriority
:
"PRIORITY"
,
},
FrameSettings
:
{
FlagSettingsAck
:
"ACK"
,
},
FramePing
:
{
FlagPingAck
:
"ACK"
,
},
FrameContinuation
:
{
FlagContinuationEndHeaders
:
"END_HEADERS"
,
},
FramePushPromise
:
{
FlagPushPromiseEndHeaders
:
"END_HEADERS"
,
FlagPushPromisePadded
:
"PADDED"
,
},
}
// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
type
frameParser
func
(
fc
*
frameCache
,
fh
FrameHeader
,
payload
[]
byte
)
(
Frame
,
error
)
var
frameParsers
=
map
[
FrameType
]
frameParser
{
FrameData
:
parseDataFrame
,
FrameHeaders
:
parseHeadersFrame
,
FramePriority
:
parsePriorityFrame
,
FrameRSTStream
:
parseRSTStreamFrame
,
FrameSettings
:
parseSettingsFrame
,
FramePushPromise
:
parsePushPromise
,
FramePing
:
parsePingFrame
,
FrameGoAway
:
parseGoAwayFrame
,
FrameWindowUpdate
:
parseWindowUpdateFrame
,
FrameContinuation
:
parseContinuationFrame
,
}
func
typeFrameParser
(
t
FrameType
)
frameParser
{
if
f
:=
frameParsers
[
t
];
f
!=
nil
{
return
f
}
return
parseUnknownFrame
}
// A FrameHeader is the 9 byte header of all HTTP/2 frames.
//
// See http://http2.github.io/http2-spec/#FrameHeader
type
FrameHeader
struct
{
valid
bool
// caller can access []byte fields in the Frame
// Type is the 1 byte frame type. There are ten standard frame
// types, but extension frame types may be written by WriteRawFrame
// and will be returned by ReadFrame (as UnknownFrame).
Type
FrameType
// Flags are the 1 byte of 8 potential bit flags per frame.
// They are specific to the frame type.
Flags
Flags
// Length is the length of the frame, not including the 9 byte header.
// The maximum size is one byte less than 16MB (uint24), but only
// frames up to 16KB are allowed without peer agreement.
Length
uint32
// StreamID is which stream this frame is for. Certain frames
// are not stream-specific, in which case this field is 0.
StreamID
uint32
}
// Header returns h. It exists so FrameHeaders can be embedded in other
// specific frame types and implement the Frame interface.
func
(
h
FrameHeader
)
Header
()
FrameHeader
{
return
h
}
func
(
h
FrameHeader
)
String
()
string
{
var
buf
bytes
.
Buffer
buf
.
WriteString
(
"[FrameHeader "
)
h
.
writeDebug
(
&
buf
)
buf
.
WriteByte
(
']'
)
return
buf
.
String
()
}
func
(
h
FrameHeader
)
writeDebug
(
buf
*
bytes
.
Buffer
)
{
buf
.
WriteString
(
h
.
Type
.
String
())
if
h
.
Flags
!=
0
{
buf
.
WriteString
(
" flags="
)
set
:=
0
for
i
:=
uint8
(
0
);
i
<
8
;
i
++
{
if
h
.
Flags
&
(
1
<<
i
)
==
0
{
continue
}
set
++
if
set
>
1
{
buf
.
WriteByte
(
'|'
)
}
name
:=
flagName
[
h
.
Type
][
Flags
(
1
<<
i
)]
if
name
!=
""
{
buf
.
WriteString
(
name
)
}
else
{
fmt
.
Fprintf
(
buf
,
"0x%x"
,
1
<<
i
)
}
}
}
if
h
.
StreamID
!=
0
{
fmt
.
Fprintf
(
buf
,
" stream=%d"
,
h
.
StreamID
)
}
fmt
.
Fprintf
(
buf
,
" len=%d"
,
h
.
Length
)
}
func
(
h
*
FrameHeader
)
checkValid
()
{
if
!
h
.
valid
{
panic
(
"Frame accessor called on non-owned Frame"
)
}
}
func
(
h
*
FrameHeader
)
invalidate
()
{
h
.
valid
=
false
}
// frame header bytes.
// Used only by ReadFrameHeader.
var
fhBytes
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
buf
:=
make
([]
byte
,
frameHeaderLen
)
return
&
buf
},
}
// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
// Most users should use Framer.ReadFrame instead.
func
ReadFrameHeader
(
r
io
.
Reader
)
(
FrameHeader
,
error
)
{
bufp
:=
fhBytes
.
Get
()
.
(
*
[]
byte
)
defer
fhBytes
.
Put
(
bufp
)
return
readFrameHeader
(
*
bufp
,
r
)
}
func
readFrameHeader
(
buf
[]
byte
,
r
io
.
Reader
)
(
FrameHeader
,
error
)
{
_
,
err
:=
io
.
ReadFull
(
r
,
buf
[
:
frameHeaderLen
])
if
err
!=
nil
{
return
FrameHeader
{},
err
}
return
FrameHeader
{
Length
:
(
uint32
(
buf
[
0
])
<<
16
|
uint32
(
buf
[
1
])
<<
8
|
uint32
(
buf
[
2
])),
Type
:
FrameType
(
buf
[
3
]),
Flags
:
Flags
(
buf
[
4
]),
StreamID
:
binary
.
BigEndian
.
Uint32
(
buf
[
5
:
])
&
(
1
<<
31
-
1
),
valid
:
true
,
},
nil
}
// A Frame is the base interface implemented by all frame types.
// Callers will generally type-assert the specific frame type:
// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
//
// Frames are only valid until the next call to Framer.ReadFrame.
type
Frame
interface
{
Header
()
FrameHeader
// invalidate is called by Framer.ReadFrame to make this
// frame's buffers as being invalid, since the subsequent
// frame will reuse them.
invalidate
()
}
// A Framer reads and writes Frames.
type
Framer
struct
{
r
io
.
Reader
lastFrame
Frame
errDetail
error
// lastHeaderStream is non-zero if the last frame was an
// unfinished HEADERS/CONTINUATION.
lastHeaderStream
uint32
maxReadSize
uint32
headerBuf
[
frameHeaderLen
]
byte
// TODO: let getReadBuf be configurable, and use a less memory-pinning
// allocator in server.go to minimize memory pinned for many idle conns.
// Will probably also need to make frame invalidation have a hook too.
getReadBuf
func
(
size
uint32
)
[]
byte
readBuf
[]
byte
// cache for default getReadBuf
maxWriteSize
uint32
// zero means unlimited; TODO: implement
w
io
.
Writer
wbuf
[]
byte
// AllowIllegalWrites permits the Framer's Write methods to
// write frames that do not conform to the HTTP/2 spec. This
// permits using the Framer to test other HTTP/2
// implementations' conformance to the spec.
// If false, the Write methods will prefer to return an error
// rather than comply.
AllowIllegalWrites
bool
// AllowIllegalReads permits the Framer's ReadFrame method
// to return non-compliant frames or frame orders.
// This is for testing and permits using the Framer to test
// other HTTP/2 implementations' conformance to the spec.
// It is not compatible with ReadMetaHeaders.
AllowIllegalReads
bool
// ReadMetaHeaders if non-nil causes ReadFrame to merge
// HEADERS and CONTINUATION frames together and return
// MetaHeadersFrame instead.
ReadMetaHeaders
*
hpack
.
Decoder
// MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
// It's used only if ReadMetaHeaders is set; 0 means a sane default
// (currently 16MB)
// If the limit is hit, MetaHeadersFrame.Truncated is set true.
MaxHeaderListSize
uint32
// TODO: track which type of frame & with which flags was sent
// last. Then return an error (unless AllowIllegalWrites) if
// we're in the middle of a header block and a
// non-Continuation or Continuation on a different stream is
// attempted to be written.
logReads
,
logWrites
bool
debugFramer
*
Framer
// only use for logging written writes
debugFramerBuf
*
bytes
.
Buffer
debugReadLoggerf
func
(
string
,
...
interface
{})
debugWriteLoggerf
func
(
string
,
...
interface
{})
frameCache
*
frameCache
// nil if frames aren't reused (default)
}
func
(
fr
*
Framer
)
maxHeaderListSize
()
uint32
{
if
fr
.
MaxHeaderListSize
==
0
{
return
16
<<
20
// sane default, per docs
}
return
fr
.
MaxHeaderListSize
}
func
(
f
*
Framer
)
startWrite
(
ftype
FrameType
,
flags
Flags
,
streamID
uint32
)
{
// Write the FrameHeader.
f
.
wbuf
=
append
(
f
.
wbuf
[
:
0
],
0
,
// 3 bytes of length, filled in in endWrite
0
,
0
,
byte
(
ftype
),
byte
(
flags
),
byte
(
streamID
>>
24
),
byte
(
streamID
>>
16
),
byte
(
streamID
>>
8
),
byte
(
streamID
))
}
func
(
f
*
Framer
)
endWrite
()
error
{
// Now that we know the final size, fill in the FrameHeader in
// the space previously reserved for it. Abuse append.
length
:=
len
(
f
.
wbuf
)
-
frameHeaderLen
if
length
>=
(
1
<<
24
)
{
return
ErrFrameTooLarge
}
_
=
append
(
f
.
wbuf
[
:
0
],
byte
(
length
>>
16
),
byte
(
length
>>
8
),
byte
(
length
))
if
f
.
logWrites
{
f
.
logWrite
()
}
n
,
err
:=
f
.
w
.
Write
(
f
.
wbuf
)
if
err
==
nil
&&
n
!=
len
(
f
.
wbuf
)
{
err
=
io
.
ErrShortWrite
}
return
err
}
func
(
f
*
Framer
)
logWrite
()
{
if
f
.
debugFramer
==
nil
{
f
.
debugFramerBuf
=
new
(
bytes
.
Buffer
)
f
.
debugFramer
=
NewFramer
(
nil
,
f
.
debugFramerBuf
)
f
.
debugFramer
.
logReads
=
false
// we log it ourselves, saying "wrote" below
// Let us read anything, even if we accidentally wrote it
// in the wrong order:
f
.
debugFramer
.
AllowIllegalReads
=
true
}
f
.
debugFramerBuf
.
Write
(
f
.
wbuf
)
fr
,
err
:=
f
.
debugFramer
.
ReadFrame
()
if
err
!=
nil
{
f
.
debugWriteLoggerf
(
"http2: Framer %p: failed to decode just-written frame"
,
f
)
return
}
f
.
debugWriteLoggerf
(
"http2: Framer %p: wrote %v"
,
f
,
summarizeFrame
(
fr
))
}
func
(
f
*
Framer
)
writeByte
(
v
byte
)
{
f
.
wbuf
=
append
(
f
.
wbuf
,
v
)
}
func
(
f
*
Framer
)
writeBytes
(
v
[]
byte
)
{
f
.
wbuf
=
append
(
f
.
wbuf
,
v
...
)
}
func
(
f
*
Framer
)
writeUint16
(
v
uint16
)
{
f
.
wbuf
=
append
(
f
.
wbuf
,
byte
(
v
>>
8
),
byte
(
v
))
}
func
(
f
*
Framer
)
writeUint32
(
v
uint32
)
{
f
.
wbuf
=
append
(
f
.
wbuf
,
byte
(
v
>>
24
),
byte
(
v
>>
16
),
byte
(
v
>>
8
),
byte
(
v
))
}
const
(
minMaxFrameSize
=
1
<<
14
maxFrameSize
=
1
<<
24
-
1
)
// SetReuseFrames allows the Framer to reuse Frames.
// If called on a Framer, Frames returned by calls to ReadFrame are only
// valid until the next call to ReadFrame.
func
(
fr
*
Framer
)
SetReuseFrames
()
{
if
fr
.
frameCache
!=
nil
{
return
}
fr
.
frameCache
=
&
frameCache
{}
}
type
frameCache
struct
{
dataFrame
DataFrame
}
func
(
fc
*
frameCache
)
getDataFrame
()
*
DataFrame
{
if
fc
==
nil
{
return
&
DataFrame
{}
}
return
&
fc
.
dataFrame
}
// NewFramer returns a Framer that writes frames to w and reads them from r.
func
NewFramer
(
w
io
.
Writer
,
r
io
.
Reader
)
*
Framer
{
fr
:=
&
Framer
{
w
:
w
,
r
:
r
,
logReads
:
logFrameReads
,
logWrites
:
logFrameWrites
,
debugReadLoggerf
:
log
.
Printf
,
debugWriteLoggerf
:
log
.
Printf
,
}
fr
.
getReadBuf
=
func
(
size
uint32
)
[]
byte
{
if
cap
(
fr
.
readBuf
)
>=
int
(
size
)
{
return
fr
.
readBuf
[
:
size
]
}
fr
.
readBuf
=
make
([]
byte
,
size
)
return
fr
.
readBuf
}
fr
.
SetMaxReadFrameSize
(
maxFrameSize
)
return
fr
}
// SetMaxReadFrameSize sets the maximum size of a frame
// that will be read by a subsequent call to ReadFrame.
// It is the caller's responsibility to advertise this
// limit with a SETTINGS frame.
func
(
fr
*
Framer
)
SetMaxReadFrameSize
(
v
uint32
)
{
if
v
>
maxFrameSize
{
v
=
maxFrameSize
}
fr
.
maxReadSize
=
v
}
// ErrorDetail returns a more detailed error of the last error
// returned by Framer.ReadFrame. For instance, if ReadFrame
// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
// will say exactly what was invalid. ErrorDetail is not guaranteed
// to return a non-nil value and like the rest of the http2 package,
// its return value is not protected by an API compatibility promise.
// ErrorDetail is reset after the next call to ReadFrame.
func
(
fr
*
Framer
)
ErrorDetail
()
error
{
return
fr
.
errDetail
}
// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
// sends a frame that is larger than declared with SetMaxReadFrameSize.
var
ErrFrameTooLarge
=
errors
.
New
(
"http2: frame too large"
)
// terminalReadFrameError reports whether err is an unrecoverable
// error from ReadFrame and no other frames should be read.
func
terminalReadFrameError
(
err
error
)
bool
{
if
_
,
ok
:=
err
.
(
StreamError
);
ok
{
return
false
}
return
err
!=
nil
}
// ReadFrame reads a single frame. The returned Frame is only valid
// until the next call to ReadFrame.
//
// If the frame is larger than previously set with SetMaxReadFrameSize, the
// returned error is ErrFrameTooLarge. Other errors may be of type
// ConnectionError, StreamError, or anything else from the underlying
// reader.
func
(
fr
*
Framer
)
ReadFrame
()
(
Frame
,
error
)
{
fr
.
errDetail
=
nil
if
fr
.
lastFrame
!=
nil
{
fr
.
lastFrame
.
invalidate
()
}
fh
,
err
:=
readFrameHeader
(
fr
.
headerBuf
[
:
],
fr
.
r
)
if
err
!=
nil
{
return
nil
,
err
}
if
fh
.
Length
>
fr
.
maxReadSize
{
return
nil
,
ErrFrameTooLarge
}
payload
:=
fr
.
getReadBuf
(
fh
.
Length
)
if
_
,
err
:=
io
.
ReadFull
(
fr
.
r
,
payload
);
err
!=
nil
{
return
nil
,
err
}
f
,
err
:=
typeFrameParser
(
fh
.
Type
)(
fr
.
frameCache
,
fh
,
payload
)
if
err
!=
nil
{
if
ce
,
ok
:=
err
.
(
connError
);
ok
{
return
nil
,
fr
.
connError
(
ce
.
Code
,
ce
.
Reason
)
}
return
nil
,
err
}
if
err
:=
fr
.
checkFrameOrder
(
f
);
err
!=
nil
{
return
nil
,
err
}
if
fr
.
logReads
{
fr
.
debugReadLoggerf
(
"http2: Framer %p: read %v"
,
fr
,
summarizeFrame
(
f
))
}
if
fh
.
Type
==
FrameHeaders
&&
fr
.
ReadMetaHeaders
!=
nil
{
return
fr
.
readMetaFrame
(
f
.
(
*
HeadersFrame
))
}
return
f
,
nil
}
// connError returns ConnectionError(code) but first
// stashes away a public reason to the caller can optionally relay it
// to the peer before hanging up on them. This might help others debug
// their implementations.
func
(
fr
*
Framer
)
connError
(
code
ErrCode
,
reason
string
)
error
{
fr
.
errDetail
=
errors
.
New
(
reason
)
return
ConnectionError
(
code
)
}
// checkFrameOrder reports an error if f is an invalid frame to return
// next from ReadFrame. Mostly it checks whether HEADERS and
// CONTINUATION frames are contiguous.
func
(
fr
*
Framer
)
checkFrameOrder
(
f
Frame
)
error
{
last
:=
fr
.
lastFrame
fr
.
lastFrame
=
f
if
fr
.
AllowIllegalReads
{
return
nil
}
fh
:=
f
.
Header
()
if
fr
.
lastHeaderStream
!=
0
{
if
fh
.
Type
!=
FrameContinuation
{
return
fr
.
connError
(
ErrCodeProtocol
,
fmt
.
Sprintf
(
"got %s for stream %d; expected CONTINUATION following %s for stream %d"
,
fh
.
Type
,
fh
.
StreamID
,
last
.
Header
()
.
Type
,
fr
.
lastHeaderStream
))
}
if
fh
.
StreamID
!=
fr
.
lastHeaderStream
{
return
fr
.
connError
(
ErrCodeProtocol
,
fmt
.
Sprintf
(
"got CONTINUATION for stream %d; expected stream %d"
,
fh
.
StreamID
,
fr
.
lastHeaderStream
))
}
}
else
if
fh
.
Type
==
FrameContinuation
{
return
fr
.
connError
(
ErrCodeProtocol
,
fmt
.
Sprintf
(
"unexpected CONTINUATION for stream %d"
,
fh
.
StreamID
))
}
switch
fh
.
Type
{
case
FrameHeaders
,
FrameContinuation
:
if
fh
.
Flags
.
Has
(
FlagHeadersEndHeaders
)
{
fr
.
lastHeaderStream
=
0
}
else
{
fr
.
lastHeaderStream
=
fh
.
StreamID
}
}
return
nil
}
// A DataFrame conveys arbitrary, variable-length sequences of octets
// associated with a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.1
type
DataFrame
struct
{
FrameHeader
data
[]
byte
}
func
(
f
*
DataFrame
)
StreamEnded
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagDataEndStream
)
}
// Data returns the frame's data octets, not including any padding
// size byte or padding suffix bytes.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func
(
f
*
DataFrame
)
Data
()
[]
byte
{
f
.
checkValid
()
return
f
.
data
}
func
parseDataFrame
(
fc
*
frameCache
,
fh
FrameHeader
,
payload
[]
byte
)
(
Frame
,
error
)
{
if
fh
.
StreamID
==
0
{
// DATA frames MUST be associated with a stream. If a
// DATA frame is received whose stream identifier
// field is 0x0, the recipient MUST respond with a
// connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
return
nil
,
connError
{
ErrCodeProtocol
,
"DATA frame with stream ID 0"
}
}
f
:=
fc
.
getDataFrame
()
f
.
FrameHeader
=
fh
var
padSize
byte
if
fh
.
Flags
.
Has
(
FlagDataPadded
)
{
var
err
error
payload
,
padSize
,
err
=
readByte
(
payload
)
if
err
!=
nil
{
return
nil
,
err
}
}
if
int
(
padSize
)
>
len
(
payload
)
{
// If the length of the padding is greater than the
// length of the frame payload, the recipient MUST
// treat this as a connection error.
// Filed: https://github.com/http2/http2-spec/issues/610
return
nil
,
connError
{
ErrCodeProtocol
,
"pad size larger than data payload"
}
}
f
.
data
=
payload
[
:
len
(
payload
)
-
int
(
padSize
)]
return
f
,
nil
}
var
(
errStreamID
=
errors
.
New
(
"invalid stream ID"
)
errDepStreamID
=
errors
.
New
(
"invalid dependent stream ID"
)
errPadLength
=
errors
.
New
(
"pad length too large"
)
errPadBytes
=
errors
.
New
(
"padding bytes must all be zeros unless AllowIllegalWrites is enabled"
)
)
func
validStreamIDOrZero
(
streamID
uint32
)
bool
{
return
streamID
&
(
1
<<
31
)
==
0
}
func
validStreamID
(
streamID
uint32
)
bool
{
return
streamID
!=
0
&&
streamID
&
(
1
<<
31
)
==
0
}
// WriteData writes a DATA frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
// and to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteData
(
streamID
uint32
,
endStream
bool
,
data
[]
byte
)
error
{
return
f
.
WriteDataPadded
(
streamID
,
endStream
,
data
,
nil
)
}
// WriteDataPadded writes a DATA frame with optional padding.
//
// If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes.
// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
// and to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteDataPadded
(
streamID
uint32
,
endStream
bool
,
data
,
pad
[]
byte
)
error
{
if
!
validStreamID
(
streamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
if
len
(
pad
)
>
0
{
if
len
(
pad
)
>
255
{
return
errPadLength
}
if
!
f
.
AllowIllegalWrites
{
for
_
,
b
:=
range
pad
{
if
b
!=
0
{
// "Padding octets MUST be set to zero when sending."
return
errPadBytes
}
}
}
}
var
flags
Flags
if
endStream
{
flags
|=
FlagDataEndStream
}
if
pad
!=
nil
{
flags
|=
FlagDataPadded
}
f
.
startWrite
(
FrameData
,
flags
,
streamID
)
if
pad
!=
nil
{
f
.
wbuf
=
append
(
f
.
wbuf
,
byte
(
len
(
pad
)))
}
f
.
wbuf
=
append
(
f
.
wbuf
,
data
...
)
f
.
wbuf
=
append
(
f
.
wbuf
,
pad
...
)
return
f
.
endWrite
()
}
// A SettingsFrame conveys configuration parameters that affect how
// endpoints communicate, such as preferences and constraints on peer
// behavior.
//
// See http://http2.github.io/http2-spec/#SETTINGS
type
SettingsFrame
struct
{
FrameHeader
p
[]
byte
}
func
parseSettingsFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
if
fh
.
Flags
.
Has
(
FlagSettingsAck
)
&&
fh
.
Length
>
0
{
// When this (ACK 0x1) bit is set, the payload of the
// SETTINGS frame MUST be empty. Receipt of a
// SETTINGS frame with the ACK flag set and a length
// field value other than 0 MUST be treated as a
// connection error (Section 5.4.1) of type
// FRAME_SIZE_ERROR.
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
if
fh
.
StreamID
!=
0
{
// SETTINGS frames always apply to a connection,
// never a single stream. The stream identifier for a
// SETTINGS frame MUST be zero (0x0). If an endpoint
// receives a SETTINGS frame whose stream identifier
// field is anything other than 0x0, the endpoint MUST
// respond with a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR.
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
if
len
(
p
)
%
6
!=
0
{
// Expecting even number of 6 byte settings.
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
f
:=
&
SettingsFrame
{
FrameHeader
:
fh
,
p
:
p
}
if
v
,
ok
:=
f
.
Value
(
SettingInitialWindowSize
);
ok
&&
v
>
(
1
<<
31
)
-
1
{
// Values above the maximum flow control window size of 2^31 - 1 MUST
// be treated as a connection error (Section 5.4.1) of type
// FLOW_CONTROL_ERROR.
return
nil
,
ConnectionError
(
ErrCodeFlowControl
)
}
return
f
,
nil
}
func
(
f
*
SettingsFrame
)
IsAck
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagSettingsAck
)
}
func
(
f
*
SettingsFrame
)
Value
(
id
SettingID
)
(
v
uint32
,
ok
bool
)
{
f
.
checkValid
()
for
i
:=
0
;
i
<
f
.
NumSettings
();
i
++
{
if
s
:=
f
.
Setting
(
i
);
s
.
ID
==
id
{
return
s
.
Val
,
true
}
}
return
0
,
false
}
// Setting returns the setting from the frame at the given 0-based index.
// The index must be >= 0 and less than f.NumSettings().
func
(
f
*
SettingsFrame
)
Setting
(
i
int
)
Setting
{
buf
:=
f
.
p
return
Setting
{
ID
:
SettingID
(
binary
.
BigEndian
.
Uint16
(
buf
[
i
*
6
:
i
*
6
+
2
])),
Val
:
binary
.
BigEndian
.
Uint32
(
buf
[
i
*
6
+
2
:
i
*
6
+
6
]),
}
}
func
(
f
*
SettingsFrame
)
NumSettings
()
int
{
return
len
(
f
.
p
)
/
6
}
// HasDuplicates reports whether f contains any duplicate setting IDs.
func
(
f
*
SettingsFrame
)
HasDuplicates
()
bool
{
num
:=
f
.
NumSettings
()
if
num
==
0
{
return
false
}
// If it's small enough (the common case), just do the n^2
// thing and avoid a map allocation.
if
num
<
10
{
for
i
:=
0
;
i
<
num
;
i
++
{
idi
:=
f
.
Setting
(
i
)
.
ID
for
j
:=
i
+
1
;
j
<
num
;
j
++
{
idj
:=
f
.
Setting
(
j
)
.
ID
if
idi
==
idj
{
return
true
}
}
}
return
false
}
seen
:=
map
[
SettingID
]
bool
{}
for
i
:=
0
;
i
<
num
;
i
++
{
id
:=
f
.
Setting
(
i
)
.
ID
if
seen
[
id
]
{
return
true
}
seen
[
id
]
=
true
}
return
false
}
// ForeachSetting runs fn for each setting.
// It stops and returns the first error.
func
(
f
*
SettingsFrame
)
ForeachSetting
(
fn
func
(
Setting
)
error
)
error
{
f
.
checkValid
()
for
i
:=
0
;
i
<
f
.
NumSettings
();
i
++
{
if
err
:=
fn
(
f
.
Setting
(
i
));
err
!=
nil
{
return
err
}
}
return
nil
}
// WriteSettings writes a SETTINGS frame with zero or more settings
// specified and the ACK bit not set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteSettings
(
settings
...
Setting
)
error
{
f
.
startWrite
(
FrameSettings
,
0
,
0
)
for
_
,
s
:=
range
settings
{
f
.
writeUint16
(
uint16
(
s
.
ID
))
f
.
writeUint32
(
s
.
Val
)
}
return
f
.
endWrite
()
}
// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteSettingsAck
()
error
{
f
.
startWrite
(
FrameSettings
,
FlagSettingsAck
,
0
)
return
f
.
endWrite
()
}
// A PingFrame is a mechanism for measuring a minimal round trip time
// from the sender, as well as determining whether an idle connection
// is still functional.
// See http://http2.github.io/http2-spec/#rfc.section.6.7
type
PingFrame
struct
{
FrameHeader
Data
[
8
]
byte
}
func
(
f
*
PingFrame
)
IsAck
()
bool
{
return
f
.
Flags
.
Has
(
FlagPingAck
)
}
func
parsePingFrame
(
_
*
frameCache
,
fh
FrameHeader
,
payload
[]
byte
)
(
Frame
,
error
)
{
if
len
(
payload
)
!=
8
{
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
if
fh
.
StreamID
!=
0
{
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
f
:=
&
PingFrame
{
FrameHeader
:
fh
}
copy
(
f
.
Data
[
:
],
payload
)
return
f
,
nil
}
func
(
f
*
Framer
)
WritePing
(
ack
bool
,
data
[
8
]
byte
)
error
{
var
flags
Flags
if
ack
{
flags
=
FlagPingAck
}
f
.
startWrite
(
FramePing
,
flags
,
0
)
f
.
writeBytes
(
data
[
:
])
return
f
.
endWrite
()
}
// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
// See http://http2.github.io/http2-spec/#rfc.section.6.8
type
GoAwayFrame
struct
{
FrameHeader
LastStreamID
uint32
ErrCode
ErrCode
debugData
[]
byte
}
// DebugData returns any debug data in the GOAWAY frame. Its contents
// are not defined.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func
(
f
*
GoAwayFrame
)
DebugData
()
[]
byte
{
f
.
checkValid
()
return
f
.
debugData
}
func
parseGoAwayFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
if
fh
.
StreamID
!=
0
{
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
if
len
(
p
)
<
8
{
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
return
&
GoAwayFrame
{
FrameHeader
:
fh
,
LastStreamID
:
binary
.
BigEndian
.
Uint32
(
p
[
:
4
])
&
(
1
<<
31
-
1
),
ErrCode
:
ErrCode
(
binary
.
BigEndian
.
Uint32
(
p
[
4
:
8
])),
debugData
:
p
[
8
:
],
},
nil
}
func
(
f
*
Framer
)
WriteGoAway
(
maxStreamID
uint32
,
code
ErrCode
,
debugData
[]
byte
)
error
{
f
.
startWrite
(
FrameGoAway
,
0
,
0
)
f
.
writeUint32
(
maxStreamID
&
(
1
<<
31
-
1
))
f
.
writeUint32
(
uint32
(
code
))
f
.
writeBytes
(
debugData
)
return
f
.
endWrite
()
}
// An UnknownFrame is the frame type returned when the frame type is unknown
// or no specific frame type parser exists.
type
UnknownFrame
struct
{
FrameHeader
p
[]
byte
}
// Payload returns the frame's payload (after the header). It is not
// valid to call this method after a subsequent call to
// Framer.ReadFrame, nor is it valid to retain the returned slice.
// The memory is owned by the Framer and is invalidated when the next
// frame is read.
func
(
f
*
UnknownFrame
)
Payload
()
[]
byte
{
f
.
checkValid
()
return
f
.
p
}
func
parseUnknownFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
return
&
UnknownFrame
{
fh
,
p
},
nil
}
// A WindowUpdateFrame is used to implement flow control.
// See http://http2.github.io/http2-spec/#rfc.section.6.9
type
WindowUpdateFrame
struct
{
FrameHeader
Increment
uint32
// never read with high bit set
}
func
parseWindowUpdateFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
if
len
(
p
)
!=
4
{
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
inc
:=
binary
.
BigEndian
.
Uint32
(
p
[
:
4
])
&
0x7fffffff
// mask off high reserved bit
if
inc
==
0
{
// A receiver MUST treat the receipt of a
// WINDOW_UPDATE frame with an flow control window
// increment of 0 as a stream error (Section 5.4.2) of
// type PROTOCOL_ERROR; errors on the connection flow
// control window MUST be treated as a connection
// error (Section 5.4.1).
if
fh
.
StreamID
==
0
{
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
return
nil
,
streamError
(
fh
.
StreamID
,
ErrCodeProtocol
)
}
return
&
WindowUpdateFrame
{
FrameHeader
:
fh
,
Increment
:
inc
,
},
nil
}
// WriteWindowUpdate writes a WINDOW_UPDATE frame.
// The increment value must be between 1 and 2,147,483,647, inclusive.
// If the Stream ID is zero, the window update applies to the
// connection as a whole.
func
(
f
*
Framer
)
WriteWindowUpdate
(
streamID
,
incr
uint32
)
error
{
// "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
if
(
incr
<
1
||
incr
>
2147483647
)
&&
!
f
.
AllowIllegalWrites
{
return
errors
.
New
(
"illegal window increment value"
)
}
f
.
startWrite
(
FrameWindowUpdate
,
0
,
streamID
)
f
.
writeUint32
(
incr
)
return
f
.
endWrite
()
}
// A HeadersFrame is used to open a stream and additionally carries a
// header block fragment.
type
HeadersFrame
struct
{
FrameHeader
// Priority is set if FlagHeadersPriority is set in the FrameHeader.
Priority
PriorityParam
headerFragBuf
[]
byte
// not owned
}
func
(
f
*
HeadersFrame
)
HeaderBlockFragment
()
[]
byte
{
f
.
checkValid
()
return
f
.
headerFragBuf
}
func
(
f
*
HeadersFrame
)
HeadersEnded
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagHeadersEndHeaders
)
}
func
(
f
*
HeadersFrame
)
StreamEnded
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagHeadersEndStream
)
}
func
(
f
*
HeadersFrame
)
HasPriority
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagHeadersPriority
)
}
func
parseHeadersFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
_
Frame
,
err
error
)
{
hf
:=
&
HeadersFrame
{
FrameHeader
:
fh
,
}
if
fh
.
StreamID
==
0
{
// HEADERS frames MUST be associated with a stream. If a HEADERS frame
// is received whose stream identifier field is 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
return
nil
,
connError
{
ErrCodeProtocol
,
"HEADERS frame with stream ID 0"
}
}
var
padLength
uint8
if
fh
.
Flags
.
Has
(
FlagHeadersPadded
)
{
if
p
,
padLength
,
err
=
readByte
(
p
);
err
!=
nil
{
return
}
}
if
fh
.
Flags
.
Has
(
FlagHeadersPriority
)
{
var
v
uint32
p
,
v
,
err
=
readUint32
(
p
)
if
err
!=
nil
{
return
nil
,
err
}
hf
.
Priority
.
StreamDep
=
v
&
0x7fffffff
hf
.
Priority
.
Exclusive
=
(
v
!=
hf
.
Priority
.
StreamDep
)
// high bit was set
p
,
hf
.
Priority
.
Weight
,
err
=
readByte
(
p
)
if
err
!=
nil
{
return
nil
,
err
}
}
if
len
(
p
)
-
int
(
padLength
)
<=
0
{
return
nil
,
streamError
(
fh
.
StreamID
,
ErrCodeProtocol
)
}
hf
.
headerFragBuf
=
p
[
:
len
(
p
)
-
int
(
padLength
)]
return
hf
,
nil
}
// HeadersFrameParam are the parameters for writing a HEADERS frame.
type
HeadersFrameParam
struct
{
// StreamID is the required Stream ID to initiate.
StreamID
uint32
// BlockFragment is part (or all) of a Header Block.
BlockFragment
[]
byte
// EndStream indicates that the header block is the last that
// the endpoint will send for the identified stream. Setting
// this flag causes the stream to enter one of "half closed"
// states.
EndStream
bool
// EndHeaders indicates that this frame contains an entire
// header block and is not followed by any
// CONTINUATION frames.
EndHeaders
bool
// PadLength is the optional number of bytes of zeros to add
// to this frame.
PadLength
uint8
// Priority, if non-zero, includes stream priority information
// in the HEADER frame.
Priority
PriorityParam
}
// WriteHeaders writes a single HEADERS frame.
//
// This is a low-level header writing method. Encoding headers and
// splitting them into any necessary CONTINUATION frames is handled
// elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteHeaders
(
p
HeadersFrameParam
)
error
{
if
!
validStreamID
(
p
.
StreamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
var
flags
Flags
if
p
.
PadLength
!=
0
{
flags
|=
FlagHeadersPadded
}
if
p
.
EndStream
{
flags
|=
FlagHeadersEndStream
}
if
p
.
EndHeaders
{
flags
|=
FlagHeadersEndHeaders
}
if
!
p
.
Priority
.
IsZero
()
{
flags
|=
FlagHeadersPriority
}
f
.
startWrite
(
FrameHeaders
,
flags
,
p
.
StreamID
)
if
p
.
PadLength
!=
0
{
f
.
writeByte
(
p
.
PadLength
)
}
if
!
p
.
Priority
.
IsZero
()
{
v
:=
p
.
Priority
.
StreamDep
if
!
validStreamIDOrZero
(
v
)
&&
!
f
.
AllowIllegalWrites
{
return
errDepStreamID
}
if
p
.
Priority
.
Exclusive
{
v
|=
1
<<
31
}
f
.
writeUint32
(
v
)
f
.
writeByte
(
p
.
Priority
.
Weight
)
}
f
.
wbuf
=
append
(
f
.
wbuf
,
p
.
BlockFragment
...
)
f
.
wbuf
=
append
(
f
.
wbuf
,
padZeros
[
:
p
.
PadLength
]
...
)
return
f
.
endWrite
()
}
// A PriorityFrame specifies the sender-advised priority of a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.3
type
PriorityFrame
struct
{
FrameHeader
PriorityParam
}
// PriorityParam are the stream prioritzation parameters.
type
PriorityParam
struct
{
// StreamDep is a 31-bit stream identifier for the
// stream that this stream depends on. Zero means no
// dependency.
StreamDep
uint32
// Exclusive is whether the dependency is exclusive.
Exclusive
bool
// Weight is the stream's zero-indexed weight. It should be
// set together with StreamDep, or neither should be set. Per
// the spec, "Add one to the value to obtain a weight between
// 1 and 256."
Weight
uint8
}
func
(
p
PriorityParam
)
IsZero
()
bool
{
return
p
==
PriorityParam
{}
}
func
parsePriorityFrame
(
_
*
frameCache
,
fh
FrameHeader
,
payload
[]
byte
)
(
Frame
,
error
)
{
if
fh
.
StreamID
==
0
{
return
nil
,
connError
{
ErrCodeProtocol
,
"PRIORITY frame with stream ID 0"
}
}
if
len
(
payload
)
!=
5
{
return
nil
,
connError
{
ErrCodeFrameSize
,
fmt
.
Sprintf
(
"PRIORITY frame payload size was %d; want 5"
,
len
(
payload
))}
}
v
:=
binary
.
BigEndian
.
Uint32
(
payload
[
:
4
])
streamID
:=
v
&
0x7fffffff
// mask off high bit
return
&
PriorityFrame
{
FrameHeader
:
fh
,
PriorityParam
:
PriorityParam
{
Weight
:
payload
[
4
],
StreamDep
:
streamID
,
Exclusive
:
streamID
!=
v
,
// was high bit set?
},
},
nil
}
// WritePriority writes a PRIORITY frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WritePriority
(
streamID
uint32
,
p
PriorityParam
)
error
{
if
!
validStreamID
(
streamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
if
!
validStreamIDOrZero
(
p
.
StreamDep
)
{
return
errDepStreamID
}
f
.
startWrite
(
FramePriority
,
0
,
streamID
)
v
:=
p
.
StreamDep
if
p
.
Exclusive
{
v
|=
1
<<
31
}
f
.
writeUint32
(
v
)
f
.
writeByte
(
p
.
Weight
)
return
f
.
endWrite
()
}
// A RSTStreamFrame allows for abnormal termination of a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.4
type
RSTStreamFrame
struct
{
FrameHeader
ErrCode
ErrCode
}
func
parseRSTStreamFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
if
len
(
p
)
!=
4
{
return
nil
,
ConnectionError
(
ErrCodeFrameSize
)
}
if
fh
.
StreamID
==
0
{
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
return
&
RSTStreamFrame
{
fh
,
ErrCode
(
binary
.
BigEndian
.
Uint32
(
p
[
:
4
]))},
nil
}
// WriteRSTStream writes a RST_STREAM frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteRSTStream
(
streamID
uint32
,
code
ErrCode
)
error
{
if
!
validStreamID
(
streamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
f
.
startWrite
(
FrameRSTStream
,
0
,
streamID
)
f
.
writeUint32
(
uint32
(
code
))
return
f
.
endWrite
()
}
// A ContinuationFrame is used to continue a sequence of header block fragments.
// See http://http2.github.io/http2-spec/#rfc.section.6.10
type
ContinuationFrame
struct
{
FrameHeader
headerFragBuf
[]
byte
}
func
parseContinuationFrame
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
Frame
,
error
)
{
if
fh
.
StreamID
==
0
{
return
nil
,
connError
{
ErrCodeProtocol
,
"CONTINUATION frame with stream ID 0"
}
}
return
&
ContinuationFrame
{
fh
,
p
},
nil
}
func
(
f
*
ContinuationFrame
)
HeaderBlockFragment
()
[]
byte
{
f
.
checkValid
()
return
f
.
headerFragBuf
}
func
(
f
*
ContinuationFrame
)
HeadersEnded
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagContinuationEndHeaders
)
}
// WriteContinuation writes a CONTINUATION frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WriteContinuation
(
streamID
uint32
,
endHeaders
bool
,
headerBlockFragment
[]
byte
)
error
{
if
!
validStreamID
(
streamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
var
flags
Flags
if
endHeaders
{
flags
|=
FlagContinuationEndHeaders
}
f
.
startWrite
(
FrameContinuation
,
flags
,
streamID
)
f
.
wbuf
=
append
(
f
.
wbuf
,
headerBlockFragment
...
)
return
f
.
endWrite
()
}
// A PushPromiseFrame is used to initiate a server stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.6
type
PushPromiseFrame
struct
{
FrameHeader
PromiseID
uint32
headerFragBuf
[]
byte
// not owned
}
func
(
f
*
PushPromiseFrame
)
HeaderBlockFragment
()
[]
byte
{
f
.
checkValid
()
return
f
.
headerFragBuf
}
func
(
f
*
PushPromiseFrame
)
HeadersEnded
()
bool
{
return
f
.
FrameHeader
.
Flags
.
Has
(
FlagPushPromiseEndHeaders
)
}
func
parsePushPromise
(
_
*
frameCache
,
fh
FrameHeader
,
p
[]
byte
)
(
_
Frame
,
err
error
)
{
pp
:=
&
PushPromiseFrame
{
FrameHeader
:
fh
,
}
if
pp
.
StreamID
==
0
{
// PUSH_PROMISE frames MUST be associated with an existing,
// peer-initiated stream. The stream identifier of a
// PUSH_PROMISE frame indicates the stream it is associated
// with. If the stream identifier field specifies the value
// 0x0, a recipient MUST respond with a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR.
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
// The PUSH_PROMISE frame includes optional padding.
// Padding fields and flags are identical to those defined for DATA frames
var
padLength
uint8
if
fh
.
Flags
.
Has
(
FlagPushPromisePadded
)
{
if
p
,
padLength
,
err
=
readByte
(
p
);
err
!=
nil
{
return
}
}
p
,
pp
.
PromiseID
,
err
=
readUint32
(
p
)
if
err
!=
nil
{
return
}
pp
.
PromiseID
=
pp
.
PromiseID
&
(
1
<<
31
-
1
)
if
int
(
padLength
)
>
len
(
p
)
{
// like the DATA frame, error out if padding is longer than the body.
return
nil
,
ConnectionError
(
ErrCodeProtocol
)
}
pp
.
headerFragBuf
=
p
[
:
len
(
p
)
-
int
(
padLength
)]
return
pp
,
nil
}
// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
type
PushPromiseParam
struct
{
// StreamID is the required Stream ID to initiate.
StreamID
uint32
// PromiseID is the required Stream ID which this
// Push Promises
PromiseID
uint32
// BlockFragment is part (or all) of a Header Block.
BlockFragment
[]
byte
// EndHeaders indicates that this frame contains an entire
// header block and is not followed by any
// CONTINUATION frames.
EndHeaders
bool
// PadLength is the optional number of bytes of zeros to add
// to this frame.
PadLength
uint8
}
// WritePushPromise writes a single PushPromise Frame.
//
// As with Header Frames, This is the low level call for writing
// individual frames. Continuation frames are handled elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func
(
f
*
Framer
)
WritePushPromise
(
p
PushPromiseParam
)
error
{
if
!
validStreamID
(
p
.
StreamID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
var
flags
Flags
if
p
.
PadLength
!=
0
{
flags
|=
FlagPushPromisePadded
}
if
p
.
EndHeaders
{
flags
|=
FlagPushPromiseEndHeaders
}
f
.
startWrite
(
FramePushPromise
,
flags
,
p
.
StreamID
)
if
p
.
PadLength
!=
0
{
f
.
writeByte
(
p
.
PadLength
)
}
if
!
validStreamID
(
p
.
PromiseID
)
&&
!
f
.
AllowIllegalWrites
{
return
errStreamID
}
f
.
writeUint32
(
p
.
PromiseID
)
f
.
wbuf
=
append
(
f
.
wbuf
,
p
.
BlockFragment
...
)
f
.
wbuf
=
append
(
f
.
wbuf
,
padZeros
[
:
p
.
PadLength
]
...
)
return
f
.
endWrite
()
}
// WriteRawFrame writes a raw frame. This can be used to write
// extension frames unknown to this package.
func
(
f
*
Framer
)
WriteRawFrame
(
t
FrameType
,
flags
Flags
,
streamID
uint32
,
payload
[]
byte
)
error
{
f
.
startWrite
(
t
,
flags
,
streamID
)
f
.
writeBytes
(
payload
)
return
f
.
endWrite
()
}
func
readByte
(
p
[]
byte
)
(
remain
[]
byte
,
b
byte
,
err
error
)
{
if
len
(
p
)
==
0
{
return
nil
,
0
,
io
.
ErrUnexpectedEOF
}
return
p
[
1
:
],
p
[
0
],
nil
}
func
readUint32
(
p
[]
byte
)
(
remain
[]
byte
,
v
uint32
,
err
error
)
{
if
len
(
p
)
<
4
{
return
nil
,
0
,
io
.
ErrUnexpectedEOF
}
return
p
[
4
:
],
binary
.
BigEndian
.
Uint32
(
p
[
:
4
]),
nil
}
type
streamEnder
interface
{
StreamEnded
()
bool
}
type
headersEnder
interface
{
HeadersEnded
()
bool
}
type
headersOrContinuation
interface
{
headersEnder
HeaderBlockFragment
()
[]
byte
}
// A MetaHeadersFrame is the representation of one HEADERS frame and
// zero or more contiguous CONTINUATION frames and the decoding of
// their HPACK-encoded contents.
//
// This type of frame does not appear on the wire and is only returned
// by the Framer when Framer.ReadMetaHeaders is set.
type
MetaHeadersFrame
struct
{
*
HeadersFrame
// Fields are the fields contained in the HEADERS and
// CONTINUATION frames. The underlying slice is owned by the
// Framer and must not be retained after the next call to
// ReadFrame.
//
// Fields are guaranteed to be in the correct http2 order and
// not have unknown pseudo header fields or invalid header
// field names or values. Required pseudo header fields may be
// missing, however. Use the MetaHeadersFrame.Pseudo accessor
// method access pseudo headers.
Fields
[]
hpack
.
HeaderField
// Truncated is whether the max header list size limit was hit
// and Fields is incomplete. The hpack decoder state is still
// valid, however.
Truncated
bool
}
// PseudoValue returns the given pseudo header field's value.
// The provided pseudo field should not contain the leading colon.
func
(
mh
*
MetaHeadersFrame
)
PseudoValue
(
pseudo
string
)
string
{
for
_
,
hf
:=
range
mh
.
Fields
{
if
!
hf
.
IsPseudo
()
{
return
""
}
if
hf
.
Name
[
1
:
]
==
pseudo
{
return
hf
.
Value
}
}
return
""
}
// RegularFields returns the regular (non-pseudo) header fields of mh.
// The caller does not own the returned slice.
func
(
mh
*
MetaHeadersFrame
)
RegularFields
()
[]
hpack
.
HeaderField
{
for
i
,
hf
:=
range
mh
.
Fields
{
if
!
hf
.
IsPseudo
()
{
return
mh
.
Fields
[
i
:
]
}
}
return
nil
}
// PseudoFields returns the pseudo header fields of mh.
// The caller does not own the returned slice.
func
(
mh
*
MetaHeadersFrame
)
PseudoFields
()
[]
hpack
.
HeaderField
{
for
i
,
hf
:=
range
mh
.
Fields
{
if
!
hf
.
IsPseudo
()
{
return
mh
.
Fields
[
:
i
]
}
}
return
mh
.
Fields
}
func
(
mh
*
MetaHeadersFrame
)
checkPseudos
()
error
{
var
isRequest
,
isResponse
bool
pf
:=
mh
.
PseudoFields
()
for
i
,
hf
:=
range
pf
{
switch
hf
.
Name
{
case
":method"
,
":path"
,
":scheme"
,
":authority"
:
isRequest
=
true
case
":status"
:
isResponse
=
true
default
:
return
pseudoHeaderError
(
hf
.
Name
)
}
// Check for duplicates.
// This would be a bad algorithm, but N is 4.
// And this doesn't allocate.
for
_
,
hf2
:=
range
pf
[
:
i
]
{
if
hf
.
Name
==
hf2
.
Name
{
return
duplicatePseudoHeaderError
(
hf
.
Name
)
}
}
}
if
isRequest
&&
isResponse
{
return
errMixPseudoHeaderTypes
}
return
nil
}
func
(
fr
*
Framer
)
maxHeaderStringLen
()
int
{
v
:=
fr
.
maxHeaderListSize
()
if
uint32
(
int
(
v
))
==
v
{
return
int
(
v
)
}
// They had a crazy big number for MaxHeaderBytes anyway,
// so give them unlimited header lengths:
return
0
}
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
// merge them into the provided hf and returns a MetaHeadersFrame
// with the decoded hpack values.
func
(
fr
*
Framer
)
readMetaFrame
(
hf
*
HeadersFrame
)
(
*
MetaHeadersFrame
,
error
)
{
if
fr
.
AllowIllegalReads
{
return
nil
,
errors
.
New
(
"illegal use of AllowIllegalReads with ReadMetaHeaders"
)
}
mh
:=
&
MetaHeadersFrame
{
HeadersFrame
:
hf
,
}
var
remainSize
=
fr
.
maxHeaderListSize
()
var
sawRegular
bool
var
invalid
error
// pseudo header field errors
hdec
:=
fr
.
ReadMetaHeaders
hdec
.
SetEmitEnabled
(
true
)
hdec
.
SetMaxStringLength
(
fr
.
maxHeaderStringLen
())
hdec
.
SetEmitFunc
(
func
(
hf
hpack
.
HeaderField
)
{
if
VerboseLogs
&&
fr
.
logReads
{
fr
.
debugReadLoggerf
(
"http2: decoded hpack field %+v"
,
hf
)
}
if
!
httpguts
.
ValidHeaderFieldValue
(
hf
.
Value
)
{
invalid
=
headerFieldValueError
(
hf
.
Value
)
}
isPseudo
:=
strings
.
HasPrefix
(
hf
.
Name
,
":"
)
if
isPseudo
{
if
sawRegular
{
invalid
=
errPseudoAfterRegular
}
}
else
{
sawRegular
=
true
if
!
validWireHeaderFieldName
(
hf
.
Name
)
{
invalid
=
headerFieldNameError
(
hf
.
Name
)
}
}
if
invalid
!=
nil
{
hdec
.
SetEmitEnabled
(
false
)
return
}
size
:=
hf
.
Size
()
if
size
>
remainSize
{
hdec
.
SetEmitEnabled
(
false
)
mh
.
Truncated
=
true
return
}
remainSize
-=
size
mh
.
Fields
=
append
(
mh
.
Fields
,
hf
)
})
// Lose reference to MetaHeadersFrame:
defer
hdec
.
SetEmitFunc
(
func
(
hf
hpack
.
HeaderField
)
{})
var
hc
headersOrContinuation
=
hf
for
{
frag
:=
hc
.
HeaderBlockFragment
()
if
_
,
err
:=
hdec
.
Write
(
frag
);
err
!=
nil
{
return
nil
,
ConnectionError
(
ErrCodeCompression
)
}
if
hc
.
HeadersEnded
()
{
break
}
if
f
,
err
:=
fr
.
ReadFrame
();
err
!=
nil
{
return
nil
,
err
}
else
{
hc
=
f
.
(
*
ContinuationFrame
)
// guaranteed by checkFrameOrder
}
}
mh
.
HeadersFrame
.
headerFragBuf
=
nil
mh
.
HeadersFrame
.
invalidate
()
if
err
:=
hdec
.
Close
();
err
!=
nil
{
return
nil
,
ConnectionError
(
ErrCodeCompression
)
}
if
invalid
!=
nil
{
fr
.
errDetail
=
invalid
if
VerboseLogs
{
log
.
Printf
(
"http2: invalid header: %v"
,
invalid
)
}
return
nil
,
StreamError
{
mh
.
StreamID
,
ErrCodeProtocol
,
invalid
}
}
if
err
:=
mh
.
checkPseudos
();
err
!=
nil
{
fr
.
errDetail
=
err
if
VerboseLogs
{
log
.
Printf
(
"http2: invalid pseudo headers: %v"
,
err
)
}
return
nil
,
StreamError
{
mh
.
StreamID
,
ErrCodeProtocol
,
err
}
}
return
mh
,
nil
}
func
summarizeFrame
(
f
Frame
)
string
{
var
buf
bytes
.
Buffer
f
.
Header
()
.
writeDebug
(
&
buf
)
switch
f
:=
f
.
(
type
)
{
case
*
SettingsFrame
:
n
:=
0
f
.
ForeachSetting
(
func
(
s
Setting
)
error
{
n
++
if
n
==
1
{
buf
.
WriteString
(
", settings:"
)
}
fmt
.
Fprintf
(
&
buf
,
" %v=%v,"
,
s
.
ID
,
s
.
Val
)
return
nil
})
if
n
>
0
{
buf
.
Truncate
(
buf
.
Len
()
-
1
)
// remove trailing comma
}
case
*
DataFrame
:
data
:=
f
.
Data
()
const
max
=
256
if
len
(
data
)
>
max
{
data
=
data
[
:
max
]
}
fmt
.
Fprintf
(
&
buf
,
" data=%q"
,
data
)
if
len
(
f
.
Data
())
>
max
{
fmt
.
Fprintf
(
&
buf
,
" (%d bytes omitted)"
,
len
(
f
.
Data
())
-
max
)
}
case
*
WindowUpdateFrame
:
if
f
.
StreamID
==
0
{
buf
.
WriteString
(
" (conn)"
)
}
fmt
.
Fprintf
(
&
buf
,
" incr=%v"
,
f
.
Increment
)
case
*
PingFrame
:
fmt
.
Fprintf
(
&
buf
,
" ping=%q"
,
f
.
Data
[
:
])
case
*
GoAwayFrame
:
fmt
.
Fprintf
(
&
buf
,
" LastStreamID=%v ErrCode=%v Debug=%q"
,
f
.
LastStreamID
,
f
.
ErrCode
,
f
.
debugData
)
case
*
RSTStreamFrame
:
fmt
.
Fprintf
(
&
buf
,
" ErrCode=%v"
,
f
.
ErrCode
)
}
return
buf
.
String
()
}
vendor/golang.org/x/net/http2/go111.go
0 → 100644
View file @
8a683270
// 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
}
vendor/golang.org/x/net/http2/gotrack.go
0 → 100644
View file @
8a683270
// 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
}
vendor/golang.org/x/net/http2/headermap.go
0 → 100644
View file @
8a683270
// 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
)
}
Prev
1
…
3
4
5
6
7
8
9
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment