mirror of
https://github.com/restic/rest-server.git
synced 2025-10-20 08:03:21 +00:00
Update dependencies
This commit is contained in:
parent
5401014105
commit
907801c8b9
331 changed files with 30381 additions and 12843 deletions
14
glide.lock
generated
14
glide.lock
generated
|
@ -1,14 +1,22 @@
|
||||||
hash: 2a84da35c7f6887fc08d80cd20da4e38731a81ea9845e1f137f1ba9913d0268d
|
hash: fa6b47593c912fd3ce7a0a9bb3f2893f61e3e4b6f7a5772c5e602e1038d74015
|
||||||
updated: 2017-05-31T23:28:23.41107346+02:00
|
updated: 2017-06-02T10:26:06.121356863+02:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/gorilla/handlers
|
- name: github.com/gorilla/handlers
|
||||||
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3
|
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3
|
||||||
|
repo: https://github.com/gorilla/handlers
|
||||||
|
vcs: git
|
||||||
- name: github.com/inconshreveable/mousetrap
|
- name: github.com/inconshreveable/mousetrap
|
||||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||||
|
repo: https://github.com/inconshreveable/mousetrap
|
||||||
|
vcs: git
|
||||||
- name: github.com/spf13/cobra
|
- name: github.com/spf13/cobra
|
||||||
version: 8d4ce3549a0bf0e3569df3aae7423b7743cd05a9
|
version: 8d4ce3549a0bf0e3569df3aae7423b7743cd05a9
|
||||||
|
repo: https://github.com/spf13/cobra
|
||||||
|
vcs: git
|
||||||
- name: github.com/spf13/pflag
|
- name: github.com/spf13/pflag
|
||||||
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
|
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
|
||||||
|
repo: https://github.com/spf13/pflag
|
||||||
|
vcs: git
|
||||||
- name: goji.io
|
- name: goji.io
|
||||||
version: 0d89ff54b2c18c9c4ba530e32496aef902d3c6cd
|
version: 0d89ff54b2c18c9c4ba530e32496aef902d3c6cd
|
||||||
repo: https://github.com/goji/goji
|
repo: https://github.com/goji/goji
|
||||||
|
@ -19,7 +27,7 @@ imports:
|
||||||
- pat
|
- pat
|
||||||
- pattern
|
- pattern
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: 45e771701b814666a7eb299e6c7a57d0b1799e91
|
version: 3da985ce5951d99de868be4385f21ea6c2b22f24
|
||||||
repo: https://github.com/golang/net
|
repo: https://github.com/golang/net
|
||||||
vcs: git
|
vcs: git
|
||||||
testImports: []
|
testImports: []
|
||||||
|
|
11
glide.yaml
11
glide.yaml
|
@ -5,8 +5,17 @@ import:
|
||||||
repo: https://github.com/goji/goji
|
repo: https://github.com/goji/goji
|
||||||
vcs: git
|
vcs: git
|
||||||
- package: golang.org/x/net
|
- package: golang.org/x/net
|
||||||
version: 45e771701b814666a7eb299e6c7a57d0b1799e91
|
|
||||||
repo: https://github.com/golang/net
|
repo: https://github.com/golang/net
|
||||||
vcs: git
|
vcs: git
|
||||||
- package: github.com/spf13/cobra
|
- package: github.com/spf13/cobra
|
||||||
|
repo: https://github.com/spf13/cobra
|
||||||
|
vcs: git
|
||||||
- package: github.com/spf13/pflag
|
- package: github.com/spf13/pflag
|
||||||
|
repo: https://github.com/spf13/pflag
|
||||||
|
vcs: git
|
||||||
|
- package: github.com/gorilla/handlers
|
||||||
|
repo: https://github.com/gorilla/handlers
|
||||||
|
vcs: git
|
||||||
|
- package: github.com/inconshreveable/mousetrap
|
||||||
|
repo: https://github.com/inconshreveable/mousetrap
|
||||||
|
vcs: git
|
||||||
|
|
3
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
3
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
|
@ -70,6 +70,9 @@ type Extension int
|
||||||
|
|
||||||
// Extension functions available in the Linux kernel.
|
// Extension functions available in the Linux kernel.
|
||||||
const (
|
const (
|
||||||
|
// extOffset is the negative maximum number of instructions used
|
||||||
|
// to load instructions by overloading the K argument.
|
||||||
|
extOffset = -0x1000
|
||||||
// ExtLen returns the length of the packet.
|
// ExtLen returns the length of the packet.
|
||||||
ExtLen Extension = 1
|
ExtLen Extension = 1
|
||||||
// ExtProto returns the packet's L3 protocol type.
|
// ExtProto returns the packet's L3 protocol type.
|
||||||
|
|
272
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
272
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
|
@ -57,6 +57,9 @@ func (ri RawInstruction) Disassemble() Instruction {
|
||||||
}
|
}
|
||||||
return LoadScratch{Dst: reg, N: int(ri.K)}
|
return LoadScratch{Dst: reg, N: int(ri.K)}
|
||||||
case opAddrModeAbsolute:
|
case opAddrModeAbsolute:
|
||||||
|
if ri.K > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(-extOffset + ri.K)}
|
||||||
|
}
|
||||||
return LoadAbsolute{Size: sz, Off: ri.K}
|
return LoadAbsolute{Size: sz, Off: ri.K}
|
||||||
case opAddrModeIndirect:
|
case opAddrModeIndirect:
|
||||||
return LoadIndirect{Size: sz, Off: ri.K}
|
return LoadIndirect{Size: sz, Off: ri.K}
|
||||||
|
@ -104,6 +107,14 @@ func (ri RawInstruction) Disassemble() Instruction {
|
||||||
case opJumpAlways:
|
case opJumpAlways:
|
||||||
return Jump{Skip: ri.K}
|
return Jump{Skip: ri.K}
|
||||||
case opJumpEqual:
|
case opJumpEqual:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpNotEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
return JumpIf{
|
return JumpIf{
|
||||||
Cond: JumpEqual,
|
Cond: JumpEqual,
|
||||||
Val: ri.K,
|
Val: ri.K,
|
||||||
|
@ -111,6 +122,14 @@ func (ri RawInstruction) Disassemble() Instruction {
|
||||||
SkipFalse: ri.Jf,
|
SkipFalse: ri.Jf,
|
||||||
}
|
}
|
||||||
case opJumpGT:
|
case opJumpGT:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpLessOrEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
return JumpIf{
|
return JumpIf{
|
||||||
Cond: JumpGreaterThan,
|
Cond: JumpGreaterThan,
|
||||||
Val: ri.K,
|
Val: ri.K,
|
||||||
|
@ -118,6 +137,14 @@ func (ri RawInstruction) Disassemble() Instruction {
|
||||||
SkipFalse: ri.Jf,
|
SkipFalse: ri.Jf,
|
||||||
}
|
}
|
||||||
case opJumpGE:
|
case opJumpGE:
|
||||||
|
if ri.Jt == 0 {
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpLessThan,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jf,
|
||||||
|
SkipFalse: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
return JumpIf{
|
return JumpIf{
|
||||||
Cond: JumpGreaterOrEqual,
|
Cond: JumpGreaterOrEqual,
|
||||||
Val: ri.K,
|
Val: ri.K,
|
||||||
|
@ -171,6 +198,18 @@ func (a LoadConstant) Assemble() (RawInstruction, error) {
|
||||||
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadConstant) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld #%d", a.Val)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadScratch loads scratch[N] into register Dst.
|
// LoadScratch loads scratch[N] into register Dst.
|
||||||
type LoadScratch struct {
|
type LoadScratch struct {
|
||||||
Dst Register
|
Dst Register
|
||||||
|
@ -185,6 +224,18 @@ func (a LoadScratch) Assemble() (RawInstruction, error) {
|
||||||
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadScratch) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
||||||
// register A.
|
// register A.
|
||||||
type LoadAbsolute struct {
|
type LoadAbsolute struct {
|
||||||
|
@ -197,6 +248,23 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) {
|
||||||
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadAbsolute) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [%d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [%d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
if a.Off > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ld [%d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
||||||
// into register A.
|
// into register A.
|
||||||
type LoadIndirect struct {
|
type LoadIndirect struct {
|
||||||
|
@ -209,6 +277,20 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) {
|
||||||
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadIndirect) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [x + %d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [x + %d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
return fmt.Sprintf("ld [x + %d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
||||||
// by 4 and stores the result in register X.
|
// by 4 and stores the result in register X.
|
||||||
//
|
//
|
||||||
|
@ -224,6 +306,11 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) {
|
||||||
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadMemShift) String() string {
|
||||||
|
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
// LoadExtension invokes a linux-specific extension and stores the
|
// LoadExtension invokes a linux-specific extension and stores the
|
||||||
// result in register A.
|
// result in register A.
|
||||||
type LoadExtension struct {
|
type LoadExtension struct {
|
||||||
|
@ -235,7 +322,47 @@ func (a LoadExtension) Assemble() (RawInstruction, error) {
|
||||||
if a.Num == ExtLen {
|
if a.Num == ExtLen {
|
||||||
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
||||||
}
|
}
|
||||||
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
|
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a LoadExtension) String() string {
|
||||||
|
switch a.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return "ld #len"
|
||||||
|
case ExtProto:
|
||||||
|
return "ld #proto"
|
||||||
|
case ExtType:
|
||||||
|
return "ld #type"
|
||||||
|
case ExtPayloadOffset:
|
||||||
|
return "ld #poff"
|
||||||
|
case ExtInterfaceIndex:
|
||||||
|
return "ld #ifidx"
|
||||||
|
case ExtNetlinkAttr:
|
||||||
|
return "ld #nla"
|
||||||
|
case ExtNetlinkAttrNested:
|
||||||
|
return "ld #nlan"
|
||||||
|
case ExtMark:
|
||||||
|
return "ld #mark"
|
||||||
|
case ExtQueue:
|
||||||
|
return "ld #queue"
|
||||||
|
case ExtLinkLayerType:
|
||||||
|
return "ld #hatype"
|
||||||
|
case ExtRXHash:
|
||||||
|
return "ld #rxhash"
|
||||||
|
case ExtCPUID:
|
||||||
|
return "ld #cpu"
|
||||||
|
case ExtVLANTag:
|
||||||
|
return "ld #vlan_tci"
|
||||||
|
case ExtVLANTagPresent:
|
||||||
|
return "ld #vlan_avail"
|
||||||
|
case ExtVLANProto:
|
||||||
|
return "ld #vlan_tpid"
|
||||||
|
case ExtRand:
|
||||||
|
return "ld #rand"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreScratch stores register Src into scratch[N].
|
// StoreScratch stores register Src into scratch[N].
|
||||||
|
@ -265,6 +392,18 @@ func (a StoreScratch) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a StoreScratch) String() string {
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("st M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("stx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ALUOpConstant executes A = A <Op> Val.
|
// ALUOpConstant executes A = A <Op> Val.
|
||||||
type ALUOpConstant struct {
|
type ALUOpConstant struct {
|
||||||
Op ALUOp
|
Op ALUOp
|
||||||
|
@ -279,6 +418,34 @@ func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a ALUOpConstant) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return fmt.Sprintf("add #%d", a.Val)
|
||||||
|
case ALUOpSub:
|
||||||
|
return fmt.Sprintf("sub #%d", a.Val)
|
||||||
|
case ALUOpMul:
|
||||||
|
return fmt.Sprintf("mul #%d", a.Val)
|
||||||
|
case ALUOpDiv:
|
||||||
|
return fmt.Sprintf("div #%d", a.Val)
|
||||||
|
case ALUOpMod:
|
||||||
|
return fmt.Sprintf("mod #%d", a.Val)
|
||||||
|
case ALUOpAnd:
|
||||||
|
return fmt.Sprintf("and #%d", a.Val)
|
||||||
|
case ALUOpOr:
|
||||||
|
return fmt.Sprintf("or #%d", a.Val)
|
||||||
|
case ALUOpXor:
|
||||||
|
return fmt.Sprintf("xor #%d", a.Val)
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return fmt.Sprintf("lsh #%d", a.Val)
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return fmt.Sprintf("rsh #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ALUOpX executes A = A <Op> X
|
// ALUOpX executes A = A <Op> X
|
||||||
type ALUOpX struct {
|
type ALUOpX struct {
|
||||||
Op ALUOp
|
Op ALUOp
|
||||||
|
@ -291,6 +458,34 @@ func (a ALUOpX) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a ALUOpX) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return "add x"
|
||||||
|
case ALUOpSub:
|
||||||
|
return "sub x"
|
||||||
|
case ALUOpMul:
|
||||||
|
return "mul x"
|
||||||
|
case ALUOpDiv:
|
||||||
|
return "div x"
|
||||||
|
case ALUOpMod:
|
||||||
|
return "mod x"
|
||||||
|
case ALUOpAnd:
|
||||||
|
return "and x"
|
||||||
|
case ALUOpOr:
|
||||||
|
return "or x"
|
||||||
|
case ALUOpXor:
|
||||||
|
return "xor x"
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return "lsh x"
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return "rsh x"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NegateA executes A = -A.
|
// NegateA executes A = -A.
|
||||||
type NegateA struct{}
|
type NegateA struct{}
|
||||||
|
|
||||||
|
@ -301,6 +496,11 @@ func (a NegateA) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a NegateA) String() string {
|
||||||
|
return fmt.Sprintf("neg")
|
||||||
|
}
|
||||||
|
|
||||||
// Jump skips the following Skip instructions in the program.
|
// Jump skips the following Skip instructions in the program.
|
||||||
type Jump struct {
|
type Jump struct {
|
||||||
Skip uint32
|
Skip uint32
|
||||||
|
@ -314,6 +514,11 @@ func (a Jump) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a Jump) String() string {
|
||||||
|
return fmt.Sprintf("ja %d", a.Skip)
|
||||||
|
}
|
||||||
|
|
||||||
// JumpIf skips the following Skip instructions in the program if A
|
// JumpIf skips the following Skip instructions in the program if A
|
||||||
// <Cond> Val is true.
|
// <Cond> Val is true.
|
||||||
type JumpIf struct {
|
type JumpIf struct {
|
||||||
|
@ -361,6 +566,51 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a JumpIf) String() string {
|
||||||
|
switch a.Cond {
|
||||||
|
// K == A
|
||||||
|
case JumpEqual:
|
||||||
|
return conditionalJump(a, "jeq", "jneq")
|
||||||
|
// K != A
|
||||||
|
case JumpNotEqual:
|
||||||
|
return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K > A
|
||||||
|
case JumpGreaterThan:
|
||||||
|
return conditionalJump(a, "jgt", "jle")
|
||||||
|
// K < A
|
||||||
|
case JumpLessThan:
|
||||||
|
return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K >= A
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
return conditionalJump(a, "jge", "jlt")
|
||||||
|
// K <= A
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K & A != 0
|
||||||
|
case JumpBitsSet:
|
||||||
|
if a.SkipFalse > 0 {
|
||||||
|
return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue)
|
||||||
|
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String()
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string {
|
||||||
|
if inst.SkipTrue > 0 {
|
||||||
|
if inst.SkipFalse > 0 {
|
||||||
|
return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
// RetA exits the BPF program, returning the value of register A.
|
// RetA exits the BPF program, returning the value of register A.
|
||||||
type RetA struct{}
|
type RetA struct{}
|
||||||
|
|
||||||
|
@ -371,6 +621,11 @@ func (a RetA) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a RetA) String() string {
|
||||||
|
return fmt.Sprintf("ret a")
|
||||||
|
}
|
||||||
|
|
||||||
// RetConstant exits the BPF program, returning a constant value.
|
// RetConstant exits the BPF program, returning a constant value.
|
||||||
type RetConstant struct {
|
type RetConstant struct {
|
||||||
Val uint32
|
Val uint32
|
||||||
|
@ -384,6 +639,11 @@ func (a RetConstant) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a RetConstant) String() string {
|
||||||
|
return fmt.Sprintf("ret #%d", a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
// TXA copies the value of register X to register A.
|
// TXA copies the value of register X to register A.
|
||||||
type TXA struct{}
|
type TXA struct{}
|
||||||
|
|
||||||
|
@ -394,6 +654,11 @@ func (a TXA) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a TXA) String() string {
|
||||||
|
return fmt.Sprintf("txa")
|
||||||
|
}
|
||||||
|
|
||||||
// TAX copies the value of register A to register X.
|
// TAX copies the value of register A to register X.
|
||||||
type TAX struct{}
|
type TAX struct{}
|
||||||
|
|
||||||
|
@ -404,6 +669,11 @@ func (a TAX) Assemble() (RawInstruction, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the the instruction in assembler notation.
|
||||||
|
func (a TAX) String() string {
|
||||||
|
return fmt.Sprintf("tax")
|
||||||
|
}
|
||||||
|
|
||||||
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
||||||
var (
|
var (
|
||||||
cls uint16
|
cls uint16
|
||||||
|
|
377
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
377
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
|
@ -5,6 +5,7 @@
|
||||||
package bpf
|
package bpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -143,11 +144,6 @@ func TestInterop(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that assembly and disassembly match each other.
|
// Check that assembly and disassembly match each other.
|
||||||
//
|
|
||||||
// Because we offer "fake" jump conditions that don't appear in the
|
|
||||||
// machine code, disassembly won't be a 1:1 match with the original
|
|
||||||
// source, although the behavior will be identical. However,
|
|
||||||
// reassembling the disassembly should produce an identical program.
|
|
||||||
func TestAsmDisasm(t *testing.T) {
|
func TestAsmDisasm(t *testing.T) {
|
||||||
prog1, err := Assemble(allInstructions)
|
prog1, err := Assemble(allInstructions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -155,30 +151,375 @@ func TestAsmDisasm(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Logf("Assembled program is %d instructions long", len(prog1))
|
t.Logf("Assembled program is %d instructions long", len(prog1))
|
||||||
|
|
||||||
src, allDecoded := Disassemble(prog1)
|
got, allDecoded := Disassemble(prog1)
|
||||||
if !allDecoded {
|
if !allDecoded {
|
||||||
t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:")
|
t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:")
|
||||||
for i, inst := range src {
|
for i, inst := range got {
|
||||||
if r, ok := inst.(RawInstruction); ok {
|
if r, ok := inst.(RawInstruction); ok {
|
||||||
t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r)
|
t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prog2, err := Assemble(src)
|
if len(allInstructions) != len(got) {
|
||||||
if err != nil {
|
t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(allInstructions), len(got))
|
||||||
t.Fatalf("assembly of Disassemble(Assemble(allInstructions)) failed: %s", err)
|
|
||||||
}
|
}
|
||||||
|
if !reflect.DeepEqual(allInstructions, got) {
|
||||||
if len(prog2) != len(prog1) {
|
|
||||||
t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(prog1), len(prog2))
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(prog1, prog2) {
|
|
||||||
t.Errorf("program mutated by disassembly:")
|
t.Errorf("program mutated by disassembly:")
|
||||||
for i := range prog2 {
|
for i := range got {
|
||||||
if !reflect.DeepEqual(prog1[i], prog2[i]) {
|
if !reflect.DeepEqual(allInstructions[i], got[i]) {
|
||||||
t.Logf(" insn %d, s: %#v, p1: %#v, p2: %#v", i+1, allInstructions[i], prog1[i], prog2[i])
|
t.Logf(" insn %d, s: %#v, p1: %#v, got: %#v", i+1, allInstructions[i], prog1[i], got[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InvalidInstruction struct{}
|
||||||
|
|
||||||
|
func (a InvalidInstruction) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{}, fmt.Errorf("Invalid Instruction")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a InvalidInstruction) String() string {
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestString(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
instruction Instruction
|
||||||
|
assembler string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
instruction: LoadConstant{Dst: RegA, Val: 42},
|
||||||
|
assembler: "ld #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadConstant{Dst: RegX, Val: 42},
|
||||||
|
assembler: "ldx #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadConstant{Dst: 0xffff, Val: 42},
|
||||||
|
assembler: "unknown instruction: bpf.LoadConstant{Dst:0xffff, Val:0x2a}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadScratch{Dst: RegA, N: 3},
|
||||||
|
assembler: "ld M[3]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadScratch{Dst: RegX, N: 3},
|
||||||
|
assembler: "ldx M[3]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadScratch{Dst: 0xffff, N: 3},
|
||||||
|
assembler: "unknown instruction: bpf.LoadScratch{Dst:0xffff, N:3}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadAbsolute{Off: 42, Size: 1},
|
||||||
|
assembler: "ldb [42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadAbsolute{Off: 42, Size: 2},
|
||||||
|
assembler: "ldh [42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadAbsolute{Off: 42, Size: 4},
|
||||||
|
assembler: "ld [42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadAbsolute{Off: 42, Size: -1},
|
||||||
|
assembler: "unknown instruction: bpf.LoadAbsolute{Off:0x2a, Size:-1}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadIndirect{Off: 42, Size: 1},
|
||||||
|
assembler: "ldb [x + 42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadIndirect{Off: 42, Size: 2},
|
||||||
|
assembler: "ldh [x + 42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadIndirect{Off: 42, Size: 4},
|
||||||
|
assembler: "ld [x + 42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadIndirect{Off: 42, Size: -1},
|
||||||
|
assembler: "unknown instruction: bpf.LoadIndirect{Off:0x2a, Size:-1}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadMemShift{Off: 42},
|
||||||
|
assembler: "ldx 4*([42]&0xf)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtLen},
|
||||||
|
assembler: "ld #len",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtProto},
|
||||||
|
assembler: "ld #proto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtType},
|
||||||
|
assembler: "ld #type",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtPayloadOffset},
|
||||||
|
assembler: "ld #poff",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtInterfaceIndex},
|
||||||
|
assembler: "ld #ifidx",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtNetlinkAttr},
|
||||||
|
assembler: "ld #nla",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtNetlinkAttrNested},
|
||||||
|
assembler: "ld #nlan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtMark},
|
||||||
|
assembler: "ld #mark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtQueue},
|
||||||
|
assembler: "ld #queue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtLinkLayerType},
|
||||||
|
assembler: "ld #hatype",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtRXHash},
|
||||||
|
assembler: "ld #rxhash",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtCPUID},
|
||||||
|
assembler: "ld #cpu",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtVLANTag},
|
||||||
|
assembler: "ld #vlan_tci",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtVLANTagPresent},
|
||||||
|
assembler: "ld #vlan_avail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtVLANProto},
|
||||||
|
assembler: "ld #vlan_tpid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: ExtRand},
|
||||||
|
assembler: "ld #rand",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadAbsolute{Off: 0xfffff038, Size: 4},
|
||||||
|
assembler: "ld #rand",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: LoadExtension{Num: 0xfff},
|
||||||
|
assembler: "unknown instruction: bpf.LoadExtension{Num:4095}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: StoreScratch{Src: RegA, N: 3},
|
||||||
|
assembler: "st M[3]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: StoreScratch{Src: RegX, N: 3},
|
||||||
|
assembler: "stx M[3]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: StoreScratch{Src: 0xffff, N: 3},
|
||||||
|
assembler: "unknown instruction: bpf.StoreScratch{Src:0xffff, N:3}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpAdd, Val: 42},
|
||||||
|
assembler: "add #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpSub, Val: 42},
|
||||||
|
assembler: "sub #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpMul, Val: 42},
|
||||||
|
assembler: "mul #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpDiv, Val: 42},
|
||||||
|
assembler: "div #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpOr, Val: 42},
|
||||||
|
assembler: "or #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpAnd, Val: 42},
|
||||||
|
assembler: "and #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
|
||||||
|
assembler: "lsh #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
|
||||||
|
assembler: "rsh #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpMod, Val: 42},
|
||||||
|
assembler: "mod #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: ALUOpXor, Val: 42},
|
||||||
|
assembler: "xor #42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpConstant{Op: 0xffff, Val: 42},
|
||||||
|
assembler: "unknown instruction: bpf.ALUOpConstant{Op:0xffff, Val:0x2a}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpAdd},
|
||||||
|
assembler: "add x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpSub},
|
||||||
|
assembler: "sub x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpMul},
|
||||||
|
assembler: "mul x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpDiv},
|
||||||
|
assembler: "div x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpOr},
|
||||||
|
assembler: "or x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpAnd},
|
||||||
|
assembler: "and x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpShiftLeft},
|
||||||
|
assembler: "lsh x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpShiftRight},
|
||||||
|
assembler: "rsh x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpMod},
|
||||||
|
assembler: "mod x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: ALUOpXor},
|
||||||
|
assembler: "xor x",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: ALUOpX{Op: 0xffff},
|
||||||
|
assembler: "unknown instruction: bpf.ALUOpX{Op:0xffff}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: NegateA{},
|
||||||
|
assembler: "neg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: Jump{Skip: 10},
|
||||||
|
assembler: "ja 10",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
|
||||||
|
assembler: "jeq #42,8,9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8},
|
||||||
|
assembler: "jeq #42,8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipFalse: 8},
|
||||||
|
assembler: "jneq #42,8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
|
||||||
|
assembler: "jneq #42,8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
|
||||||
|
assembler: "jlt #42,7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
|
||||||
|
assembler: "jle #42,6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
|
||||||
|
assembler: "jgt #42,4,5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4},
|
||||||
|
assembler: "jgt #42,4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
|
||||||
|
assembler: "jge #42,3,4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3},
|
||||||
|
assembler: "jge #42,3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||||
|
assembler: "jset #42,2,3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2},
|
||||||
|
assembler: "jset #42,2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||||
|
assembler: "jset #42,3,2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2},
|
||||||
|
assembler: "jset #42,0,2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: JumpIf{Cond: 0xffff, Val: 42, SkipTrue: 1, SkipFalse: 2},
|
||||||
|
assembler: "unknown instruction: bpf.JumpIf{Cond:0xffff, Val:0x2a, SkipTrue:0x1, SkipFalse:0x2}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: TAX{},
|
||||||
|
assembler: "tax",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: TXA{},
|
||||||
|
assembler: "txa",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: RetA{},
|
||||||
|
assembler: "ret a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: RetConstant{Val: 42},
|
||||||
|
assembler: "ret #42",
|
||||||
|
},
|
||||||
|
// Invalid instruction
|
||||||
|
{
|
||||||
|
instruction: InvalidInstruction{},
|
||||||
|
assembler: "unknown instruction: bpf.InvalidInstruction{}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
if input, ok := testCase.instruction.(fmt.Stringer); ok {
|
||||||
|
got := input.String()
|
||||||
|
if got != testCase.assembler {
|
||||||
|
t.Errorf("String did not return expected assembler notation, expected: %s, got: %s", testCase.assembler, got)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Instruction %#v is not a fmt.Stringer", testCase.instruction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go
generated
vendored
1
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go
generated
vendored
|
@ -19,6 +19,7 @@ func TestGo17Context(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.WriteString(w, "ok")
|
io.WriteString(w, "ok")
|
||||||
}))
|
}))
|
||||||
|
defer ts.Close()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
resp, err := Get(ctx, http.DefaultClient, ts.URL)
|
resp, err := Get(ctx, http.DefaultClient, ts.URL)
|
||||||
if resp == nil || err != nil {
|
if resp == nil || err != nil {
|
||||||
|
|
1418
vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
Normal file
1418
vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
575
vendor/golang.org/x/net/dns/dnsmessage/message_test.go
generated
vendored
Normal file
575
vendor/golang.org/x/net/dns/dnsmessage/message_test.go
generated
vendored
Normal file
|
@ -0,0 +1,575 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package dnsmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *Message) String() string {
|
||||||
|
s := fmt.Sprintf("Message: %#v\n", &m.Header)
|
||||||
|
if len(m.Questions) > 0 {
|
||||||
|
s += "-- Questions\n"
|
||||||
|
for _, q := range m.Questions {
|
||||||
|
s += fmt.Sprintf("%#v\n", q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(m.Answers) > 0 {
|
||||||
|
s += "-- Answers\n"
|
||||||
|
for _, a := range m.Answers {
|
||||||
|
s += fmt.Sprintf("%#v\n", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(m.Authorities) > 0 {
|
||||||
|
s += "-- Authorities\n"
|
||||||
|
for _, ns := range m.Authorities {
|
||||||
|
s += fmt.Sprintf("%#v\n", ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(m.Additionals) > 0 {
|
||||||
|
s += "-- Additionals\n"
|
||||||
|
for _, e := range m.Additionals {
|
||||||
|
s += fmt.Sprintf("%#v\n", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQuestionPackUnpack(t *testing.T) {
|
||||||
|
want := Question{
|
||||||
|
Name: ".",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
}
|
||||||
|
buf, err := want.pack(make([]byte, 1, 50), map[string]int{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Packing failed:", err)
|
||||||
|
}
|
||||||
|
var p Parser
|
||||||
|
p.msg = buf
|
||||||
|
p.header.questions = 1
|
||||||
|
p.section = sectionQuestions
|
||||||
|
p.off = 1
|
||||||
|
got, err := p.Question()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
|
||||||
|
}
|
||||||
|
if p.off != len(buf) {
|
||||||
|
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("Got = %+v, want = %+v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNamePackUnpack(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{"", ".", nil},
|
||||||
|
{".", ".", nil},
|
||||||
|
{"google..com", "", errZeroSegLen},
|
||||||
|
{"google.com", "google.com.", nil},
|
||||||
|
{"google..com.", "", errZeroSegLen},
|
||||||
|
{"google.com.", "google.com.", nil},
|
||||||
|
{".google.com.", "", errZeroSegLen},
|
||||||
|
{"www..google.com.", "", errZeroSegLen},
|
||||||
|
{"www.google.com.", "www.google.com.", nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
buf, err := packName(make([]byte, 0, 30), test.in, map[string]int{})
|
||||||
|
if err != test.err {
|
||||||
|
t.Errorf("Packing of %s: got err = %v, want err = %v", test.in, err, test.err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if test.err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
got, n, err := unpackName(buf, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unpacking for %s failed: %v", test.in, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if n != len(buf) {
|
||||||
|
t.Errorf(
|
||||||
|
"Unpacked different amount than packed for %s: got n = %d, want = %d",
|
||||||
|
test.in,
|
||||||
|
n,
|
||||||
|
len(buf),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if got != test.want {
|
||||||
|
t.Errorf("Unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSPackUnpack(t *testing.T) {
|
||||||
|
wants := []Message{
|
||||||
|
{
|
||||||
|
Questions: []Question{
|
||||||
|
{
|
||||||
|
Name: ".",
|
||||||
|
Type: TypeAAAA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Answers: []Resource{},
|
||||||
|
Authorities: []Resource{},
|
||||||
|
Additionals: []Resource{},
|
||||||
|
},
|
||||||
|
largeTestMsg(),
|
||||||
|
}
|
||||||
|
for i, want := range wants {
|
||||||
|
b, err := want.Pack()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%d: packing failed: %v", i, err)
|
||||||
|
}
|
||||||
|
var got Message
|
||||||
|
err = got.Unpack(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%d: unpacking failed: %v", i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSkipAll(t *testing.T) {
|
||||||
|
msg := largeTestMsg()
|
||||||
|
buf, err := msg.Pack()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Packing large test message:", err)
|
||||||
|
}
|
||||||
|
var p Parser
|
||||||
|
if _, err := p.Start(buf); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
f func() error
|
||||||
|
}{
|
||||||
|
{"SkipAllQuestions", p.SkipAllQuestions},
|
||||||
|
{"SkipAllAnswers", p.SkipAllAnswers},
|
||||||
|
{"SkipAllAuthorities", p.SkipAllAuthorities},
|
||||||
|
{"SkipAllAdditionals", p.SkipAllAdditionals},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
for i := 1; i <= 3; i++ {
|
||||||
|
if err := test.f(); err != nil {
|
||||||
|
t.Errorf("Call #%d to %s(): %v", i, test.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSkipNotStarted(t *testing.T) {
|
||||||
|
var p Parser
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
f func() error
|
||||||
|
}{
|
||||||
|
{"SkipAllQuestions", p.SkipAllQuestions},
|
||||||
|
{"SkipAllAnswers", p.SkipAllAnswers},
|
||||||
|
{"SkipAllAuthorities", p.SkipAllAuthorities},
|
||||||
|
{"SkipAllAdditionals", p.SkipAllAdditionals},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
if err := test.f(); err != ErrNotStarted {
|
||||||
|
t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTooManyRecords(t *testing.T) {
|
||||||
|
const recs = int(^uint16(0)) + 1
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
msg Message
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Questions",
|
||||||
|
Message{
|
||||||
|
Questions: make([]Question, recs),
|
||||||
|
},
|
||||||
|
errTooManyQuestions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Answers",
|
||||||
|
Message{
|
||||||
|
Answers: make([]Resource, recs),
|
||||||
|
},
|
||||||
|
errTooManyAnswers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Authorities",
|
||||||
|
Message{
|
||||||
|
Authorities: make([]Resource, recs),
|
||||||
|
},
|
||||||
|
errTooManyAuthorities,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Additionals",
|
||||||
|
Message{
|
||||||
|
Additionals: make([]Resource, recs),
|
||||||
|
},
|
||||||
|
errTooManyAdditionals,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
if _, got := test.msg.Pack(); got != test.want {
|
||||||
|
t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVeryLongTxt(t *testing.T) {
|
||||||
|
want := &TXTResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeTXT,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
Txt: loremIpsum,
|
||||||
|
}
|
||||||
|
buf, err := packResource(make([]byte, 0, 8000), want, map[string]int{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Packing failed:", err)
|
||||||
|
}
|
||||||
|
var hdr ResourceHeader
|
||||||
|
off, err := hdr.unpack(buf, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unpacking ResourceHeader failed:", err)
|
||||||
|
}
|
||||||
|
got, n, err := unpackResource(buf, off, hdr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unpacking failed:", err)
|
||||||
|
}
|
||||||
|
if n != len(buf) {
|
||||||
|
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("Got = %+v, want = %+v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleHeaderSearch() {
|
||||||
|
msg := Message{
|
||||||
|
Header: Header{Response: true, Authoritative: true},
|
||||||
|
Questions: []Question{
|
||||||
|
{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Answers: []Resource{
|
||||||
|
&AResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
A: [4]byte{127, 0, 0, 1},
|
||||||
|
},
|
||||||
|
&AResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
A: [4]byte{127, 0, 0, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := msg.Pack()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantName := "bar.example.com."
|
||||||
|
|
||||||
|
var p Parser
|
||||||
|
if _, err := p.Start(buf); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
q, err := p.Question()
|
||||||
|
if err == ErrSectionDone {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.Name != wantName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Found question for name", wantName)
|
||||||
|
if err := p.SkipAllQuestions(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var gotIPs []net.IP
|
||||||
|
for {
|
||||||
|
h, err := p.AnswerHeader()
|
||||||
|
if err == ErrSectionDone {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h.Type != TypeA && h.Type != TypeAAAA) || h.Class != ClassINET {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(h.Name, wantName) {
|
||||||
|
if err := p.SkipAnswer(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
a, err := p.Answer()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r := a.(type) {
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown type: %T", r))
|
||||||
|
case *AResource:
|
||||||
|
gotIPs = append(gotIPs, r.A[:])
|
||||||
|
case *AAAAResource:
|
||||||
|
gotIPs = append(gotIPs, r.AAAA[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Found question for name bar.example.com.
|
||||||
|
// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func largeTestMsg() Message {
|
||||||
|
return Message{
|
||||||
|
Header: Header{Response: true, Authoritative: true},
|
||||||
|
Questions: []Question{
|
||||||
|
{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Answers: []Resource{
|
||||||
|
&AResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
A: [4]byte{127, 0, 0, 1},
|
||||||
|
},
|
||||||
|
&AResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeA,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
A: [4]byte{127, 0, 0, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Authorities: []Resource{
|
||||||
|
&NSResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeNS,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
NS: "ns1.example.com.",
|
||||||
|
},
|
||||||
|
&NSResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeNS,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
NS: "ns2.example.com.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Additionals: []Resource{
|
||||||
|
&TXTResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeTXT,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
Txt: "So Long, and Thanks for All the Fish",
|
||||||
|
},
|
||||||
|
&TXTResource{
|
||||||
|
ResourceHeader: ResourceHeader{
|
||||||
|
Name: "foo.bar.example.com.",
|
||||||
|
Type: TypeTXT,
|
||||||
|
Class: ClassINET,
|
||||||
|
},
|
||||||
|
Txt: "Hamster Huey and the Gooey Kablooie",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loremIpsum = `
|
||||||
|
Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
|
||||||
|
nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
|
||||||
|
magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
|
||||||
|
regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
|
||||||
|
nam ipsum assentior.
|
||||||
|
|
||||||
|
Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
|
||||||
|
facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
|
||||||
|
no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
|
||||||
|
reformidans et. Qui ei eros porro reformidans, ius suas veritus
|
||||||
|
torquatos ex. Mea te facer alterum consequat.
|
||||||
|
|
||||||
|
Soleat torquatos democritum sed et, no mea congue appareat, facer
|
||||||
|
aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
|
||||||
|
phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
|
||||||
|
suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
|
||||||
|
honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
|
||||||
|
mollis.
|
||||||
|
|
||||||
|
Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
|
||||||
|
vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
|
||||||
|
vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
|
||||||
|
dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
|
||||||
|
pro, vel ne saepe senserit consetetur.
|
||||||
|
|
||||||
|
Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
|
||||||
|
enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
|
||||||
|
sententiae deterruisset ut. At suas timeam euismod cum, offendit
|
||||||
|
appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
|
||||||
|
accusata intellegebat, noluisse instructior sea id. Nec te nonumes
|
||||||
|
habemus appellantur, quis dignissim vituperata eu nam.
|
||||||
|
|
||||||
|
At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
|
||||||
|
iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
|
||||||
|
placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
|
||||||
|
eligendi disputationi. Ius no tation everti impedit, ei magna quidam
|
||||||
|
mediocritatem pri.
|
||||||
|
|
||||||
|
Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
|
||||||
|
ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
|
||||||
|
has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
|
||||||
|
iudico albucius his.
|
||||||
|
|
||||||
|
Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
|
||||||
|
dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
|
||||||
|
an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
|
||||||
|
vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
|
||||||
|
consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
|
||||||
|
usu, dicit graeco disputando id has.
|
||||||
|
|
||||||
|
Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
|
||||||
|
torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
|
||||||
|
ea, usu liber postulant ei.
|
||||||
|
|
||||||
|
Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
|
||||||
|
feugiat duo. Congue option meliore ex qui, noster invenire appellantur
|
||||||
|
ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
|
||||||
|
probo minimum, et nam illud falli tempor.
|
||||||
|
|
||||||
|
Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
|
||||||
|
tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
|
||||||
|
tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
|
||||||
|
|
||||||
|
Ad oratio blandit aliquando pro. Vis et dolorum rationibus
|
||||||
|
philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
|
||||||
|
ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
|
||||||
|
option delenit an. Alii placerat has no, in pri nihil platonem
|
||||||
|
cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
|
||||||
|
an.
|
||||||
|
|
||||||
|
Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
|
||||||
|
accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
|
||||||
|
Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
|
||||||
|
error volumus scripserit. In pro paulo iudico, quo ei dolorem
|
||||||
|
verterem, affert fabellas dissentiet ea vix.
|
||||||
|
|
||||||
|
Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
|
||||||
|
salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
|
||||||
|
nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
|
||||||
|
utroque vis, ex equidem detraxit temporibus has.
|
||||||
|
|
||||||
|
Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
|
||||||
|
pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
|
||||||
|
mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
|
||||||
|
interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
|
||||||
|
eam id.
|
||||||
|
|
||||||
|
An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
|
||||||
|
inciderint no sea. Ea persius maluisset vix, ne vim appellantur
|
||||||
|
instructior, consul quidam definiebas pri id. Cum integre feugiat
|
||||||
|
pericula in, ex sed persius similique, mel ne natum dicit percipitur.
|
||||||
|
|
||||||
|
Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
|
||||||
|
neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
|
||||||
|
rationibus. Eu vel alii honestatis definitiones, mea no nonumy
|
||||||
|
reprehendunt.
|
||||||
|
|
||||||
|
Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
|
||||||
|
adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
|
||||||
|
duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
|
||||||
|
debitis nostrum no, ut vel aliquid vivendo.
|
||||||
|
|
||||||
|
Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
|
||||||
|
Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
|
||||||
|
dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
|
||||||
|
nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
|
||||||
|
|
||||||
|
Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
|
||||||
|
sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
|
||||||
|
definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
|
||||||
|
vis, modus offendit omittantur te mel.
|
||||||
|
|
||||||
|
Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
|
||||||
|
melius conceptam est ne, quo in minimum apeirian delicata, ut ius
|
||||||
|
porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
|
||||||
|
his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
|
||||||
|
per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
|
||||||
|
ad idque fabellas intellegebat.
|
||||||
|
|
||||||
|
Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
|
||||||
|
mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
|
||||||
|
alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
|
||||||
|
nam at.
|
||||||
|
|
||||||
|
Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
|
||||||
|
discere. Nec civibus officiis dissentiunt ex, est te liber ludus
|
||||||
|
elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
|
||||||
|
comprehensam, nam te inermis delectus, saepe inermis senserit.
|
||||||
|
`
|
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
641
vendor/golang.org/x/net/http2/ciphers.go
generated
vendored
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
// A list of the possible cipher suite ids. Taken from
|
||||||
|
// http://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
|
||||||
|
}
|
||||||
|
}
|
309
vendor/golang.org/x/net/http2/ciphers_test.go
generated
vendored
Normal file
309
vendor/golang.org/x/net/http2/ciphers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestIsBadCipherBad(t *testing.T) {
|
||||||
|
for _, c := range badCiphers {
|
||||||
|
if !isBadCipher(c) {
|
||||||
|
t.Errorf("Wrong result for isBadCipher(%d), want true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify we don't give false positives on ciphers not on blacklist
|
||||||
|
func TestIsBadCipherGood(t *testing.T) {
|
||||||
|
goodCiphers := map[uint16]string{
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM: "cipher_TLS_DHE_RSA_WITH_AES_256_CCM",
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM: "cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: "cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||||
|
}
|
||||||
|
for c, name := range goodCiphers {
|
||||||
|
if isBadCipher(c) {
|
||||||
|
t.Errorf("Wrong result for isBadCipher(%d) %s, want false", c, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from https://http2.github.io/http2-spec/#BadCipherSuites,
|
||||||
|
var badCiphers = []uint16{
|
||||||
|
cipher_TLS_NULL_WITH_NULL_NULL,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8,
|
||||||
|
}
|
2
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
2
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
|
@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
||||||
// convering panics into errors.
|
// converting panics into errors.
|
||||||
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
|
146
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
Normal file
146
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Buffer chunks are allocated from a pool to reduce pressure on GC.
|
||||||
|
// The maximum wasted space per dataBuffer is 2x the largest size class,
|
||||||
|
// which happens when the dataBuffer has multiple chunks and there is
|
||||||
|
// one unread byte in both the first and last chunks. We use a few size
|
||||||
|
// classes to minimize overheads for servers that typically receive very
|
||||||
|
// small request bodies.
|
||||||
|
//
|
||||||
|
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
||||||
|
// improved enough that we can instead allocate chunks like this:
|
||||||
|
// make([]byte, max(16<<10, expectedBytesRemaining))
|
||||||
|
var (
|
||||||
|
dataChunkSizeClasses = []int{
|
||||||
|
1 << 10,
|
||||||
|
2 << 10,
|
||||||
|
4 << 10,
|
||||||
|
8 << 10,
|
||||||
|
16 << 10,
|
||||||
|
}
|
||||||
|
dataChunkPools = [...]sync.Pool{
|
||||||
|
{New: func() interface{} { return make([]byte, 1<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 2<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 4<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 8<<10) }},
|
||||||
|
{New: func() interface{} { return make([]byte, 16<<10) }},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDataBufferChunk(size int64) []byte {
|
||||||
|
i := 0
|
||||||
|
for ; i < len(dataChunkSizeClasses)-1; i++ {
|
||||||
|
if size <= int64(dataChunkSizeClasses[i]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataChunkPools[i].Get().([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putDataBufferChunk(p []byte) {
|
||||||
|
for i, n := range dataChunkSizeClasses {
|
||||||
|
if len(p) == n {
|
||||||
|
dataChunkPools[i].Put(p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
||||||
|
// Each dataBuffer is used to read DATA frames on a single stream.
|
||||||
|
// The buffer is divided into chunks so the server can limit the
|
||||||
|
// total memory used by a single connection without limiting the
|
||||||
|
// request body size on any single stream.
|
||||||
|
type dataBuffer struct {
|
||||||
|
chunks [][]byte
|
||||||
|
r int // next byte to read is chunks[0][r]
|
||||||
|
w int // next byte to write is chunks[len(chunks)-1][w]
|
||||||
|
size int // total buffered bytes
|
||||||
|
expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errReadEmpty = errors.New("read from empty dataBuffer")
|
||||||
|
|
||||||
|
// Read copies bytes from the buffer into p.
|
||||||
|
// It is an error to read when no data is available.
|
||||||
|
func (b *dataBuffer) Read(p []byte) (int, error) {
|
||||||
|
if b.size == 0 {
|
||||||
|
return 0, errReadEmpty
|
||||||
|
}
|
||||||
|
var ntotal int
|
||||||
|
for len(p) > 0 && b.size > 0 {
|
||||||
|
readFrom := b.bytesFromFirstChunk()
|
||||||
|
n := copy(p, readFrom)
|
||||||
|
p = p[n:]
|
||||||
|
ntotal += n
|
||||||
|
b.r += n
|
||||||
|
b.size -= n
|
||||||
|
// If the first chunk has been consumed, advance to the next chunk.
|
||||||
|
if b.r == len(b.chunks[0]) {
|
||||||
|
putDataBufferChunk(b.chunks[0])
|
||||||
|
end := len(b.chunks) - 1
|
||||||
|
copy(b.chunks[:end], b.chunks[1:])
|
||||||
|
b.chunks[end] = nil
|
||||||
|
b.chunks = b.chunks[:end]
|
||||||
|
b.r = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ntotal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *dataBuffer) bytesFromFirstChunk() []byte {
|
||||||
|
if len(b.chunks) == 1 {
|
||||||
|
return b.chunks[0][b.r:b.w]
|
||||||
|
}
|
||||||
|
return b.chunks[0][b.r:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of bytes of the unread portion of the buffer.
|
||||||
|
func (b *dataBuffer) Len() int {
|
||||||
|
return b.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write appends p to the buffer.
|
||||||
|
func (b *dataBuffer) Write(p []byte) (int, error) {
|
||||||
|
ntotal := len(p)
|
||||||
|
for len(p) > 0 {
|
||||||
|
// If the last chunk is empty, allocate a new chunk. Try to allocate
|
||||||
|
// enough to fully copy p plus any additional bytes we expect to
|
||||||
|
// receive. However, this may allocate less than len(p).
|
||||||
|
want := int64(len(p))
|
||||||
|
if b.expected > want {
|
||||||
|
want = b.expected
|
||||||
|
}
|
||||||
|
chunk := b.lastChunkOrAlloc(want)
|
||||||
|
n := copy(chunk[b.w:], p)
|
||||||
|
p = p[n:]
|
||||||
|
b.w += n
|
||||||
|
b.size += n
|
||||||
|
b.expected -= int64(n)
|
||||||
|
}
|
||||||
|
return ntotal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
|
||||||
|
if len(b.chunks) != 0 {
|
||||||
|
last := b.chunks[len(b.chunks)-1]
|
||||||
|
if b.w < len(last) {
|
||||||
|
return last
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chunk := getDataBufferChunk(want)
|
||||||
|
b.chunks = append(b.chunks, chunk)
|
||||||
|
b.w = 0
|
||||||
|
return chunk
|
||||||
|
}
|
157
vendor/golang.org/x/net/http2/databuffer_test.go
generated
vendored
Normal file
157
vendor/golang.org/x/net/http2/databuffer_test.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fmtDataChunk(chunk []byte) string {
|
||||||
|
out := ""
|
||||||
|
var last byte
|
||||||
|
var count int
|
||||||
|
for _, c := range chunk {
|
||||||
|
if c != last {
|
||||||
|
if count > 0 {
|
||||||
|
out += fmt.Sprintf(" x %d ", count)
|
||||||
|
count = 0
|
||||||
|
}
|
||||||
|
out += string([]byte{c})
|
||||||
|
last = c
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
out += fmt.Sprintf(" x %d", count)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func fmtDataChunks(chunks [][]byte) string {
|
||||||
|
var out string
|
||||||
|
for _, chunk := range chunks {
|
||||||
|
out += fmt.Sprintf("{%q}", fmtDataChunk(chunk))
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) {
|
||||||
|
// Run setup, then read the remaining bytes from the dataBuffer and check
|
||||||
|
// that they match wantBytes. We use different read sizes to check corner
|
||||||
|
// cases in Read.
|
||||||
|
for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} {
|
||||||
|
t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) {
|
||||||
|
b := setup(t)
|
||||||
|
buf := make([]byte, readSize)
|
||||||
|
var gotRead bytes.Buffer
|
||||||
|
for {
|
||||||
|
n, err := b.Read(buf)
|
||||||
|
gotRead.Write(buf[:n])
|
||||||
|
if err == errReadEmpty {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error after %v bytes: %v", gotRead.Len(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) {
|
||||||
|
t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataBufferAllocation(t *testing.T) {
|
||||||
|
writes := [][]byte{
|
||||||
|
bytes.Repeat([]byte("a"), 1*1024-1),
|
||||||
|
[]byte("a"),
|
||||||
|
bytes.Repeat([]byte("b"), 4*1024-1),
|
||||||
|
[]byte("b"),
|
||||||
|
bytes.Repeat([]byte("c"), 8*1024-1),
|
||||||
|
[]byte("c"),
|
||||||
|
bytes.Repeat([]byte("d"), 16*1024-1),
|
||||||
|
[]byte("d"),
|
||||||
|
bytes.Repeat([]byte("e"), 32*1024),
|
||||||
|
}
|
||||||
|
var wantRead bytes.Buffer
|
||||||
|
for _, p := range writes {
|
||||||
|
wantRead.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
|
||||||
|
b := &dataBuffer{}
|
||||||
|
for _, p := range writes {
|
||||||
|
if n, err := b.Write(p); n != len(p) || err != nil {
|
||||||
|
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
want := [][]byte{
|
||||||
|
bytes.Repeat([]byte("a"), 1*1024),
|
||||||
|
bytes.Repeat([]byte("b"), 4*1024),
|
||||||
|
bytes.Repeat([]byte("c"), 8*1024),
|
||||||
|
bytes.Repeat([]byte("d"), 16*1024),
|
||||||
|
bytes.Repeat([]byte("e"), 16*1024),
|
||||||
|
bytes.Repeat([]byte("e"), 16*1024),
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(b.chunks, want) {
|
||||||
|
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataBufferAllocationWithExpected(t *testing.T) {
|
||||||
|
writes := [][]byte{
|
||||||
|
bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB
|
||||||
|
bytes.Repeat([]byte("b"), 14*1024),
|
||||||
|
bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more
|
||||||
|
bytes.Repeat([]byte("d"), 2*1024),
|
||||||
|
bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB
|
||||||
|
}
|
||||||
|
var wantRead bytes.Buffer
|
||||||
|
for _, p := range writes {
|
||||||
|
wantRead.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
|
||||||
|
b := &dataBuffer{expected: 32 * 1024}
|
||||||
|
for _, p := range writes {
|
||||||
|
if n, err := b.Write(p); n != len(p) || err != nil {
|
||||||
|
t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
want := [][]byte{
|
||||||
|
append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...),
|
||||||
|
append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...),
|
||||||
|
bytes.Repeat([]byte("e"), 1*1024),
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(b.chunks, want) {
|
||||||
|
t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataBufferWriteAfterPartialRead(t *testing.T) {
|
||||||
|
testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer {
|
||||||
|
b := &dataBuffer{}
|
||||||
|
if n, err := b.Write([]byte("abcd")); n != 4 || err != nil {
|
||||||
|
t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err)
|
||||||
|
}
|
||||||
|
p := make([]byte, 2)
|
||||||
|
if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) {
|
||||||
|
t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err)
|
||||||
|
}
|
||||||
|
if n, err := b.Write([]byte("xyz")); n != 3 || err != nil {
|
||||||
|
t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
})
|
||||||
|
}
|
60
vendor/golang.org/x/net/http2/fixed_buffer.go
generated
vendored
60
vendor/golang.org/x/net/http2/fixed_buffer.go
generated
vendored
|
@ -1,60 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
|
|
||||||
// It never allocates, but moves old data as new data is written.
|
|
||||||
type fixedBuffer struct {
|
|
||||||
buf []byte
|
|
||||||
r, w int
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errReadEmpty = errors.New("read from empty fixedBuffer")
|
|
||||||
errWriteFull = errors.New("write on full fixedBuffer")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Read copies bytes from the buffer into p.
|
|
||||||
// It is an error to read when no data is available.
|
|
||||||
func (b *fixedBuffer) Read(p []byte) (n int, err error) {
|
|
||||||
if b.r == b.w {
|
|
||||||
return 0, errReadEmpty
|
|
||||||
}
|
|
||||||
n = copy(p, b.buf[b.r:b.w])
|
|
||||||
b.r += n
|
|
||||||
if b.r == b.w {
|
|
||||||
b.r = 0
|
|
||||||
b.w = 0
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of bytes of the unread portion of the buffer.
|
|
||||||
func (b *fixedBuffer) Len() int {
|
|
||||||
return b.w - b.r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write copies bytes from p into the buffer.
|
|
||||||
// It is an error to write more data than the buffer can hold.
|
|
||||||
func (b *fixedBuffer) Write(p []byte) (n int, err error) {
|
|
||||||
// Slide existing data to beginning.
|
|
||||||
if b.r > 0 && len(p) > len(b.buf)-b.w {
|
|
||||||
copy(b.buf, b.buf[b.r:b.w])
|
|
||||||
b.w -= b.r
|
|
||||||
b.r = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write new data.
|
|
||||||
n = copy(b.buf[b.w:], p)
|
|
||||||
b.w += n
|
|
||||||
if n < len(p) {
|
|
||||||
err = errWriteFull
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
128
vendor/golang.org/x/net/http2/fixed_buffer_test.go
generated
vendored
128
vendor/golang.org/x/net/http2/fixed_buffer_test.go
generated
vendored
|
@ -1,128 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bufferReadTests = []struct {
|
|
||||||
buf fixedBuffer
|
|
||||||
read, wn int
|
|
||||||
werr error
|
|
||||||
wp []byte
|
|
||||||
wbuf fixedBuffer
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
fixedBuffer{[]byte{'a', 0}, 0, 1},
|
|
||||||
5, 1, nil, []byte{'a'},
|
|
||||||
fixedBuffer{[]byte{'a', 0}, 0, 0},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fixedBuffer{[]byte{0, 'a'}, 1, 2},
|
|
||||||
5, 1, nil, []byte{'a'},
|
|
||||||
fixedBuffer{[]byte{0, 'a'}, 0, 0},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fixedBuffer{[]byte{'a', 'b'}, 0, 2},
|
|
||||||
1, 1, nil, []byte{'a'},
|
|
||||||
fixedBuffer{[]byte{'a', 'b'}, 1, 2},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fixedBuffer{[]byte{}, 0, 0},
|
|
||||||
5, 0, errReadEmpty, []byte{},
|
|
||||||
fixedBuffer{[]byte{}, 0, 0},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBufferRead(t *testing.T) {
|
|
||||||
for i, tt := range bufferReadTests {
|
|
||||||
read := make([]byte, tt.read)
|
|
||||||
n, err := tt.buf.Read(read)
|
|
||||||
if n != tt.wn {
|
|
||||||
t.Errorf("#%d: wn = %d want %d", i, n, tt.wn)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != tt.werr {
|
|
||||||
t.Errorf("#%d: werr = %v want %v", i, err, tt.werr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
read = read[:n]
|
|
||||||
if !reflect.DeepEqual(read, tt.wp) {
|
|
||||||
t.Errorf("#%d: read = %+v want %+v", i, read, tt.wp)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(tt.buf, tt.wbuf) {
|
|
||||||
t.Errorf("#%d: buf = %+v want %+v", i, tt.buf, tt.wbuf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var bufferWriteTests = []struct {
|
|
||||||
buf fixedBuffer
|
|
||||||
write, wn int
|
|
||||||
werr error
|
|
||||||
wbuf fixedBuffer
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
buf: fixedBuffer{
|
|
||||||
buf: []byte{},
|
|
||||||
},
|
|
||||||
wbuf: fixedBuffer{
|
|
||||||
buf: []byte{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buf: fixedBuffer{
|
|
||||||
buf: []byte{1, 'a'},
|
|
||||||
},
|
|
||||||
write: 1,
|
|
||||||
wn: 1,
|
|
||||||
wbuf: fixedBuffer{
|
|
||||||
buf: []byte{0, 'a'},
|
|
||||||
w: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buf: fixedBuffer{
|
|
||||||
buf: []byte{'a', 1},
|
|
||||||
r: 1,
|
|
||||||
w: 1,
|
|
||||||
},
|
|
||||||
write: 2,
|
|
||||||
wn: 2,
|
|
||||||
wbuf: fixedBuffer{
|
|
||||||
buf: []byte{0, 0},
|
|
||||||
w: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buf: fixedBuffer{
|
|
||||||
buf: []byte{},
|
|
||||||
},
|
|
||||||
write: 5,
|
|
||||||
werr: errWriteFull,
|
|
||||||
wbuf: fixedBuffer{
|
|
||||||
buf: []byte{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBufferWrite(t *testing.T) {
|
|
||||||
for i, tt := range bufferWriteTests {
|
|
||||||
n, err := tt.buf.Write(make([]byte, tt.write))
|
|
||||||
if n != tt.wn {
|
|
||||||
t.Errorf("#%d: wrote %d bytes; want %d", i, n, tt.wn)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != tt.werr {
|
|
||||||
t.Errorf("#%d: error = %v; want %v", i, err, tt.werr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(tt.buf, tt.wbuf) {
|
|
||||||
t.Errorf("#%d: buf = %+v; want %+v", i, tt.buf, tt.wbuf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
67
vendor/golang.org/x/net/http2/frame.go
generated
vendored
67
vendor/golang.org/x/net/http2/frame.go
generated
vendored
|
@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
|
||||||
// a frameParser parses a frame given its FrameHeader and payload
|
// a frameParser parses a frame given its FrameHeader and payload
|
||||||
// bytes. The length of payload will always equal fh.Length (which
|
// bytes. The length of payload will always equal fh.Length (which
|
||||||
// might be 0).
|
// might be 0).
|
||||||
type frameParser func(fh FrameHeader, payload []byte) (Frame, error)
|
type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
|
||||||
|
|
||||||
var frameParsers = map[FrameType]frameParser{
|
var frameParsers = map[FrameType]frameParser{
|
||||||
FrameData: parseDataFrame,
|
FrameData: parseDataFrame,
|
||||||
|
@ -323,6 +323,8 @@ type Framer struct {
|
||||||
debugFramerBuf *bytes.Buffer
|
debugFramerBuf *bytes.Buffer
|
||||||
debugReadLoggerf func(string, ...interface{})
|
debugReadLoggerf func(string, ...interface{})
|
||||||
debugWriteLoggerf func(string, ...interface{})
|
debugWriteLoggerf func(string, ...interface{})
|
||||||
|
|
||||||
|
frameCache *frameCache // nil if frames aren't reused (default)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *Framer) maxHeaderListSize() uint32 {
|
func (fr *Framer) maxHeaderListSize() uint32 {
|
||||||
|
@ -398,6 +400,27 @@ const (
|
||||||
maxFrameSize = 1<<24 - 1
|
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.
|
// NewFramer returns a Framer that writes frames to w and reads them from r.
|
||||||
func NewFramer(w io.Writer, r io.Reader) *Framer {
|
func NewFramer(w io.Writer, r io.Reader) *Framer {
|
||||||
fr := &Framer{
|
fr := &Framer{
|
||||||
|
@ -477,7 +500,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
|
||||||
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
f, err := typeFrameParser(fh.Type)(fh, payload)
|
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ce, ok := err.(connError); ok {
|
if ce, ok := err.(connError); ok {
|
||||||
return nil, fr.connError(ce.Code, ce.Reason)
|
return nil, fr.connError(ce.Code, ce.Reason)
|
||||||
|
@ -565,7 +588,7 @@ func (f *DataFrame) Data() []byte {
|
||||||
return f.data
|
return f.data
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
|
func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
// DATA frames MUST be associated with a stream. If a
|
// DATA frames MUST be associated with a stream. If a
|
||||||
// DATA frame is received whose stream identifier
|
// DATA frame is received whose stream identifier
|
||||||
|
@ -574,9 +597,9 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
|
||||||
// PROTOCOL_ERROR.
|
// PROTOCOL_ERROR.
|
||||||
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
f := &DataFrame{
|
f := fc.getDataFrame()
|
||||||
FrameHeader: fh,
|
f.FrameHeader = fh
|
||||||
}
|
|
||||||
var padSize byte
|
var padSize byte
|
||||||
if fh.Flags.Has(FlagDataPadded) {
|
if fh.Flags.Has(FlagDataPadded) {
|
||||||
var err error
|
var err error
|
||||||
|
@ -600,6 +623,7 @@ var (
|
||||||
errStreamID = errors.New("invalid stream ID")
|
errStreamID = errors.New("invalid stream ID")
|
||||||
errDepStreamID = errors.New("invalid dependent stream ID")
|
errDepStreamID = errors.New("invalid dependent stream ID")
|
||||||
errPadLength = errors.New("pad length too large")
|
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 {
|
func validStreamIDOrZero(streamID uint32) bool {
|
||||||
|
@ -623,6 +647,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
|
||||||
//
|
//
|
||||||
// If pad is nil, the padding bit is not sent.
|
// If pad is nil, the padding bit is not sent.
|
||||||
// The length of pad must not exceed 255 bytes.
|
// The length of pad must not exceed 255 bytes.
|
||||||
|
// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
|
||||||
//
|
//
|
||||||
// It will perform exactly one Write to the underlying Writer.
|
// It will perform exactly one Write to the underlying Writer.
|
||||||
// It is the caller's responsibility not to violate the maximum frame size
|
// It is the caller's responsibility not to violate the maximum frame size
|
||||||
|
@ -631,9 +656,19 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by
|
||||||
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
||||||
return errStreamID
|
return errStreamID
|
||||||
}
|
}
|
||||||
|
if len(pad) > 0 {
|
||||||
if len(pad) > 255 {
|
if len(pad) > 255 {
|
||||||
return errPadLength
|
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
|
var flags Flags
|
||||||
if endStream {
|
if endStream {
|
||||||
flags |= FlagDataEndStream
|
flags |= FlagDataEndStream
|
||||||
|
@ -660,7 +695,7 @@ type SettingsFrame struct {
|
||||||
p []byte
|
p []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
|
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
|
||||||
// When this (ACK 0x1) bit is set, the payload of the
|
// When this (ACK 0x1) bit is set, the payload of the
|
||||||
// SETTINGS frame MUST be empty. Receipt of a
|
// SETTINGS frame MUST be empty. Receipt of a
|
||||||
|
@ -762,7 +797,7 @@ type PingFrame struct {
|
||||||
|
|
||||||
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
|
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
|
||||||
|
|
||||||
func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
|
func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
||||||
if len(payload) != 8 {
|
if len(payload) != 8 {
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
|
@ -802,7 +837,7 @@ func (f *GoAwayFrame) DebugData() []byte {
|
||||||
return f.debugData
|
return f.debugData
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
if fh.StreamID != 0 {
|
if fh.StreamID != 0 {
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
|
@ -842,7 +877,7 @@ func (f *UnknownFrame) Payload() []byte {
|
||||||
return f.p
|
return f.p
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
return &UnknownFrame{fh, p}, nil
|
return &UnknownFrame{fh, p}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,7 +888,7 @@ type WindowUpdateFrame struct {
|
||||||
Increment uint32 // never read with high bit set
|
Increment uint32 // never read with high bit set
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
if len(p) != 4 {
|
if len(p) != 4 {
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
|
@ -918,7 +953,7 @@ func (f *HeadersFrame) HasPriority() bool {
|
||||||
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
|
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
|
func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
|
||||||
hf := &HeadersFrame{
|
hf := &HeadersFrame{
|
||||||
FrameHeader: fh,
|
FrameHeader: fh,
|
||||||
}
|
}
|
||||||
|
@ -1055,7 +1090,7 @@ func (p PriorityParam) IsZero() bool {
|
||||||
return p == PriorityParam{}
|
return p == PriorityParam{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
|
func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1137,7 @@ type RSTStreamFrame struct {
|
||||||
ErrCode ErrCode
|
ErrCode ErrCode
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
if len(p) != 4 {
|
if len(p) != 4 {
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1167,7 @@ type ContinuationFrame struct {
|
||||||
headerFragBuf []byte
|
headerFragBuf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
|
func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
|
@ -1182,7 +1217,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
|
||||||
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
|
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePushPromise(fh FrameHeader, p []byte) (_ Frame, err error) {
|
func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
|
||||||
pp := &PushPromiseFrame{
|
pp := &PushPromiseFrame{
|
||||||
FrameHeader: fh,
|
FrameHeader: fh,
|
||||||
}
|
}
|
||||||
|
|
91
vendor/golang.org/x/net/http2/frame_test.go
generated
vendored
91
vendor/golang.org/x/net/http2/frame_test.go
generated
vendored
|
@ -141,7 +141,7 @@ func TestWriteDataPadded(t *testing.T) {
|
||||||
streamID: 1,
|
streamID: 1,
|
||||||
endStream: false,
|
endStream: false,
|
||||||
data: []byte("foo"),
|
data: []byte("foo"),
|
||||||
pad: []byte("bar"),
|
pad: []byte{0, 0, 0},
|
||||||
wantHeader: FrameHeader{
|
wantHeader: FrameHeader{
|
||||||
Type: FrameData,
|
Type: FrameData,
|
||||||
Flags: FlagDataPadded,
|
Flags: FlagDataPadded,
|
||||||
|
@ -1096,6 +1096,95 @@ func TestMetaFrameHeader(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetReuseFrames(t *testing.T) {
|
||||||
|
fr, buf := testFramer()
|
||||||
|
fr.SetReuseFrames()
|
||||||
|
|
||||||
|
// Check that DataFrames are reused. Note that
|
||||||
|
// SetReuseFrames only currently implements reuse of DataFrames.
|
||||||
|
firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
|
||||||
|
if df != firstDf {
|
||||||
|
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
df := readAndVerifyDataFrame("", 0, fr, buf, t)
|
||||||
|
if df != firstDf {
|
||||||
|
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
|
||||||
|
if df != firstDf {
|
||||||
|
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetReuseFramesMoreThanOnce(t *testing.T) {
|
||||||
|
fr, buf := testFramer()
|
||||||
|
fr.SetReuseFrames()
|
||||||
|
|
||||||
|
firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
|
||||||
|
fr.SetReuseFrames()
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
|
||||||
|
// SetReuseFrames should be idempotent
|
||||||
|
fr.SetReuseFrames()
|
||||||
|
if df != firstDf {
|
||||||
|
t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoSetReuseFrames(t *testing.T) {
|
||||||
|
fr, buf := testFramer()
|
||||||
|
const numNewDataFrames = 10
|
||||||
|
dfSoFar := make([]interface{}, numNewDataFrames)
|
||||||
|
|
||||||
|
// Check that DataFrames are not reused if SetReuseFrames wasn't called.
|
||||||
|
// SetReuseFrames only currently implements reuse of DataFrames.
|
||||||
|
for i := 0; i < numNewDataFrames; i++ {
|
||||||
|
df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
|
||||||
|
for _, item := range dfSoFar {
|
||||||
|
if df == item {
|
||||||
|
t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dfSoFar[i] = df
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
|
||||||
|
var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
|
||||||
|
fr.WriteData(streamID, true, []byte(data))
|
||||||
|
wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
|
||||||
|
if buf.String() != wantEnc {
|
||||||
|
t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
|
||||||
|
}
|
||||||
|
f, err := fr.ReadFrame()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
df, ok := f.(*DataFrame)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("got %T; want *DataFrame", f)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(df.Data(), []byte(data)) {
|
||||||
|
t.Errorf("got %q; want %q", df.Data(), []byte(data))
|
||||||
|
}
|
||||||
|
if f.Header().Flags&1 == 0 {
|
||||||
|
t.Errorf("didn't see END_STREAM flag")
|
||||||
|
}
|
||||||
|
return df
|
||||||
|
}
|
||||||
|
|
||||||
func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
|
func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
|
||||||
var he hpackEncoder
|
var he hpackEncoder
|
||||||
return he.encodeHeaderRaw(t, pairs...)
|
return he.encodeHeaderRaw(t, pairs...)
|
||||||
|
|
27
vendor/golang.org/x/net/http2/go16.go
generated
vendored
27
vendor/golang.org/x/net/http2/go16.go
generated
vendored
|
@ -7,7 +7,6 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -15,29 +14,3 @@ import (
|
||||||
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
return t1.ExpectContinueTimeout
|
return t1.ExpectContinueTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// 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"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
6
vendor/golang.org/x/net/http2/go18.go
generated
vendored
6
vendor/golang.org/x/net/http2/go18.go
generated
vendored
|
@ -12,7 +12,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() }
|
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
||||||
|
c2 := c.Clone()
|
||||||
|
c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
|
||||||
|
return c2
|
||||||
|
}
|
||||||
|
|
||||||
var _ http.Pusher = (*responseWriter)(nil)
|
var _ http.Pusher = (*responseWriter)(nil)
|
||||||
|
|
||||||
|
|
13
vendor/golang.org/x/net/http2/go18_test.go
generated
vendored
13
vendor/golang.org/x/net/http2/go18_test.go
generated
vendored
|
@ -7,6 +7,7 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -64,3 +65,15 @@ func TestConfigureServerIdleTimeout_Go18(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCertClone(t *testing.T) {
|
||||||
|
c := &tls.Config{
|
||||||
|
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||||
|
panic("shouldn't be called")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c2 := cloneTLSConfig(c)
|
||||||
|
if c2.GetClientCertificate == nil {
|
||||||
|
t.Error("GetClientCertificate is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
16
vendor/golang.org/x/net/http2/go19.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/http2/go19.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configureServer19(s *http.Server, conf *Server) error {
|
||||||
|
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
|
||||||
|
return nil
|
||||||
|
}
|
60
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
Normal file
60
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServerGracefulShutdown(t *testing.T) {
|
||||||
|
var st *serverTester
|
||||||
|
handlerDone := make(chan struct{})
|
||||||
|
st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer close(handlerDone)
|
||||||
|
go st.ts.Config.Shutdown(context.Background())
|
||||||
|
|
||||||
|
ga := st.wantGoAway()
|
||||||
|
if ga.ErrCode != ErrCodeNo {
|
||||||
|
t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
|
||||||
|
}
|
||||||
|
if ga.LastStreamID != 1 {
|
||||||
|
t.Errorf("GOAWAY LastStreamID = %v; want 1", ga.LastStreamID)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("x-foo", "bar")
|
||||||
|
})
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
st.greet()
|
||||||
|
st.bodylessReq1()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-handlerDone:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Fatalf("server did not shutdown?")
|
||||||
|
}
|
||||||
|
hf := st.wantHeaders()
|
||||||
|
goth := st.decodeHeader(hf.HeaderBlockFragment())
|
||||||
|
wanth := [][2]string{
|
||||||
|
{":status", "200"},
|
||||||
|
{"x-foo", "bar"},
|
||||||
|
{"content-type", "text/plain; charset=utf-8"},
|
||||||
|
{"content-length", "0"},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(goth, wanth) {
|
||||||
|
t.Errorf("Got headers %v; want %v", goth, wanth)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := st.cc.Read([]byte{0})
|
||||||
|
if n != 0 || err == nil {
|
||||||
|
t.Errorf("Read = %v, %v; want 0, non-nil", n, err)
|
||||||
|
}
|
||||||
|
}
|
68
vendor/golang.org/x/net/http2/h2demo/h2demo.go
generated
vendored
68
vendor/golang.org/x/net/http2/h2demo/h2demo.go
generated
vendored
|
@ -87,6 +87,7 @@ href="https://golang.org/s/http2bug">file a bug</a>.</p>
|
||||||
<li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li>
|
<li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li>
|
||||||
<li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li>
|
<li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li>
|
||||||
<li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li>
|
<li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li>
|
||||||
|
<li>GET <a href="/serverpush">/serverpush</a> to see a page with server push</li>
|
||||||
<li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li>
|
<li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li>
|
||||||
<li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li>
|
<li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li>
|
||||||
<li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
|
<li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
|
||||||
|
@ -168,8 +169,11 @@ var (
|
||||||
|
|
||||||
// fileServer returns a file-serving handler that proxies URL.
|
// fileServer returns a file-serving handler that proxies URL.
|
||||||
// It lazily fetches URL on the first access and caches its contents forever.
|
// It lazily fetches URL on the first access and caches its contents forever.
|
||||||
func fileServer(url string) http.Handler {
|
func fileServer(url string, latency time.Duration) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if latency > 0 {
|
||||||
|
time.Sleep(latency)
|
||||||
|
}
|
||||||
hi, err := fsGrp.Do(url, func() (interface{}, error) {
|
hi, err := fsGrp.Do(url, func() (interface{}, error) {
|
||||||
fsMu.Lock()
|
fsMu.Lock()
|
||||||
if h, ok := fsCache[url]; ok {
|
if h, ok := fsCache[url]; ok {
|
||||||
|
@ -227,14 +231,18 @@ func clockStreamHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func registerHandlers() {
|
func registerHandlers() {
|
||||||
tiles := newGopherTilesHandler()
|
tiles := newGopherTilesHandler()
|
||||||
|
push := newPushHandler()
|
||||||
|
|
||||||
mux2 := http.NewServeMux()
|
mux2 := http.NewServeMux()
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.TLS == nil {
|
switch {
|
||||||
if r.URL.Path == "/gophertiles" {
|
case r.URL.Path == "/gophertiles":
|
||||||
tiles.ServeHTTP(w, r)
|
tiles.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x
|
||||||
return
|
return
|
||||||
}
|
case strings.HasPrefix(r.URL.Path, "/serverpush"):
|
||||||
|
push.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x
|
||||||
|
return
|
||||||
|
case r.TLS == nil: // do not allow HTTP/1.x for anything else
|
||||||
http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
|
http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -249,8 +257,8 @@ func registerHandlers() {
|
||||||
mux2.ServeHTTP(w, r)
|
mux2.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
mux2.HandleFunc("/", home)
|
mux2.HandleFunc("/", home)
|
||||||
mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png"))
|
mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png", 0))
|
||||||
mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz"))
|
mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz", 0))
|
||||||
mux2.HandleFunc("/reqinfo", reqInfoHandler)
|
mux2.HandleFunc("/reqinfo", reqInfoHandler)
|
||||||
mux2.HandleFunc("/crc32", crcHandler)
|
mux2.HandleFunc("/crc32", crcHandler)
|
||||||
mux2.HandleFunc("/ECHO", echoCapitalHandler)
|
mux2.HandleFunc("/ECHO", echoCapitalHandler)
|
||||||
|
@ -267,6 +275,46 @@ func registerHandlers() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pushResources = map[string]http.Handler{
|
||||||
|
"/serverpush/static/jquery.min.js": fileServer("https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js", 100*time.Millisecond),
|
||||||
|
"/serverpush/static/godocs.js": fileServer("https://golang.org/lib/godoc/godocs.js", 100*time.Millisecond),
|
||||||
|
"/serverpush/static/playground.js": fileServer("https://golang.org/lib/godoc/playground.js", 100*time.Millisecond),
|
||||||
|
"/serverpush/static/style.css": fileServer("https://golang.org/lib/godoc/style.css", 100*time.Millisecond),
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPushHandler() http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
for path, handler := range pushResources {
|
||||||
|
if r.URL.Path == path {
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheBust := time.Now().UnixNano()
|
||||||
|
if pusher, ok := w.(http.Pusher); ok {
|
||||||
|
for path := range pushResources {
|
||||||
|
url := fmt.Sprintf("%s?%d", path, cacheBust)
|
||||||
|
if err := pusher.Push(url, nil); err != nil {
|
||||||
|
log.Printf("Failed to push %v: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond) // fake network latency + parsing time
|
||||||
|
if err := pushTmpl.Execute(w, struct {
|
||||||
|
CacheBust int64
|
||||||
|
HTTPSHost string
|
||||||
|
HTTPHost string
|
||||||
|
}{
|
||||||
|
CacheBust: cacheBust,
|
||||||
|
HTTPSHost: httpsHost(),
|
||||||
|
HTTPHost: httpHost(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Printf("Executing server push template: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func newGopherTilesHandler() http.Handler {
|
func newGopherTilesHandler() http.Handler {
|
||||||
const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
|
const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
|
||||||
res, err := http.Get(gopherURL)
|
res, err := http.Get(gopherURL)
|
||||||
|
@ -393,7 +441,11 @@ func serveProdTLS() error {
|
||||||
GetCertificate: m.GetCertificate,
|
GetCertificate: m.GetCertificate,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
http2.ConfigureServer(srv, &http2.Server{})
|
http2.ConfigureServer(srv, &http2.Server{
|
||||||
|
NewWriteScheduler: func() http2.WriteScheduler {
|
||||||
|
return http2.NewPriorityWriteScheduler(nil)
|
||||||
|
},
|
||||||
|
})
|
||||||
ln, err := net.Listen("tcp", ":443")
|
ln, err := net.Listen("tcp", ":443")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
1991
vendor/golang.org/x/net/http2/h2demo/tmpl.go
generated
vendored
Normal file
1991
vendor/golang.org/x/net/http2/h2demo/tmpl.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
12
vendor/golang.org/x/net/http2/h2i/h2i.go
generated
vendored
12
vendor/golang.org/x/net/http2/h2i/h2i.go
generated
vendored
|
@ -88,6 +88,14 @@ func withPort(host string) string {
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withoutPort strips the port from addr if present.
|
||||||
|
func withoutPort(addr string) string {
|
||||||
|
if h, _, err := net.SplitHostPort(addr); err == nil {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
// h2i is the app's state.
|
// h2i is the app's state.
|
||||||
type h2i struct {
|
type h2i struct {
|
||||||
host string
|
host string
|
||||||
|
@ -134,7 +142,7 @@ func main() {
|
||||||
|
|
||||||
func (app *h2i) Main() error {
|
func (app *h2i) Main() error {
|
||||||
cfg := &tls.Config{
|
cfg := &tls.Config{
|
||||||
ServerName: app.host,
|
ServerName: withoutPort(app.host),
|
||||||
NextProtos: strings.Split(*flagNextProto, ","),
|
NextProtos: strings.Split(*flagNextProto, ","),
|
||||||
InsecureSkipVerify: *flagInsecure,
|
InsecureSkipVerify: *flagInsecure,
|
||||||
}
|
}
|
||||||
|
@ -473,7 +481,7 @@ func (app *h2i) encodeHeaders(req *http.Request) []byte {
|
||||||
host = req.URL.Host
|
host = req.URL.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
path := req.URL.Path
|
path := req.RequestURI
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "/"
|
path = "/"
|
||||||
}
|
}
|
||||||
|
|
27
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
27
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
|
@ -39,6 +39,7 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||||
tableSizeUpdate: false,
|
tableSizeUpdate: false,
|
||||||
w: w,
|
w: w,
|
||||||
}
|
}
|
||||||
|
e.dynTab.table.init()
|
||||||
e.dynTab.setMaxSize(initialHeaderTableSize)
|
e.dynTab.setMaxSize(initialHeaderTableSize)
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
@ -88,29 +89,17 @@ func (e *Encoder) WriteField(f HeaderField) error {
|
||||||
// only name matches, i points to that index and nameValueMatch
|
// only name matches, i points to that index and nameValueMatch
|
||||||
// becomes false.
|
// becomes false.
|
||||||
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
|
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
|
||||||
for idx, hf := range staticTable {
|
i, nameValueMatch = staticTable.search(f)
|
||||||
if !constantTimeStringCompare(hf.Name, f.Name) {
|
if nameValueMatch {
|
||||||
continue
|
return i, true
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
i = uint64(idx + 1)
|
|
||||||
}
|
|
||||||
if f.Sensitive {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !constantTimeStringCompare(hf.Value, f.Value) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i = uint64(idx + 1)
|
|
||||||
nameValueMatch = true
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
j, nameValueMatch := e.dynTab.search(f)
|
j, nameValueMatch := e.dynTab.table.search(f)
|
||||||
if nameValueMatch || (i == 0 && j != 0) {
|
if nameValueMatch || (i == 0 && j != 0) {
|
||||||
i = j + uint64(len(staticTable))
|
return j + uint64(staticTable.len()), nameValueMatch
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
return i, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMaxDynamicTableSize changes the dynamic header table size to v.
|
// SetMaxDynamicTableSize changes the dynamic header table size to v.
|
||||||
|
|
70
vendor/golang.org/x/net/http2/hpack/encode_test.go
generated
vendored
70
vendor/golang.org/x/net/http2/hpack/encode_test.go
generated
vendored
|
@ -7,6 +7,8 @@ package hpack
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -101,17 +103,20 @@ func TestEncoderSearchTable(t *testing.T) {
|
||||||
wantMatch bool
|
wantMatch bool
|
||||||
}{
|
}{
|
||||||
// Name and Value match
|
// Name and Value match
|
||||||
{pair("foo", "bar"), uint64(len(staticTable) + 3), true},
|
{pair("foo", "bar"), uint64(staticTable.len()) + 3, true},
|
||||||
{pair("blake", "miz"), uint64(len(staticTable) + 2), true},
|
{pair("blake", "miz"), uint64(staticTable.len()) + 2, true},
|
||||||
{pair(":method", "GET"), 2, true},
|
{pair(":method", "GET"), 2, true},
|
||||||
|
|
||||||
// Only name match because Sensitive == true
|
// Only name match because Sensitive == true. This is allowed to match
|
||||||
{HeaderField{":method", "GET", true}, 2, false},
|
// any ":method" entry. The current implementation uses the last entry
|
||||||
|
// added in newStaticTable.
|
||||||
|
{HeaderField{":method", "GET", true}, 3, false},
|
||||||
|
|
||||||
// Only Name matches
|
// Only Name matches
|
||||||
{pair("foo", "..."), uint64(len(staticTable) + 3), false},
|
{pair("foo", "..."), uint64(staticTable.len()) + 3, false},
|
||||||
{pair("blake", "..."), uint64(len(staticTable) + 2), false},
|
{pair("blake", "..."), uint64(staticTable.len()) + 2, false},
|
||||||
{pair(":method", "..."), 2, false},
|
// As before, this is allowed to match any ":method" entry.
|
||||||
|
{pair(":method", "..."), 3, false},
|
||||||
|
|
||||||
// None match
|
// None match
|
||||||
{pair("foo-", "bar"), 0, false},
|
{pair("foo-", "bar"), 0, false},
|
||||||
|
@ -328,3 +333,54 @@ func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) {
|
||||||
func removeSpace(s string) string {
|
func removeSpace(s string) string {
|
||||||
return strings.Replace(s, " ", "", -1)
|
return strings.Replace(s, " ", "", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncoderSearchTable(b *testing.B) {
|
||||||
|
e := NewEncoder(nil)
|
||||||
|
|
||||||
|
// A sample of possible header fields.
|
||||||
|
// This is not based on any actual data from HTTP/2 traces.
|
||||||
|
var possible []HeaderField
|
||||||
|
for _, f := range staticTable.ents {
|
||||||
|
if f.Value == "" {
|
||||||
|
possible = append(possible, f)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Generate 5 random values, except for cookie and set-cookie,
|
||||||
|
// which we know can have many values in practice.
|
||||||
|
num := 5
|
||||||
|
if f.Name == "cookie" || f.Name == "set-cookie" {
|
||||||
|
num = 25
|
||||||
|
}
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
|
||||||
|
possible = append(possible, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k := 0; k < 10; k++ {
|
||||||
|
f := HeaderField{
|
||||||
|
Name: fmt.Sprintf("x-header-%d", k),
|
||||||
|
Sensitive: rand.Int()%2 == 0,
|
||||||
|
}
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
f.Value = fmt.Sprintf("%s-%d", f.Name, i)
|
||||||
|
possible = append(possible, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a random sample to the dynamic table. This very loosely simulates
|
||||||
|
// a history of 100 requests with 20 header fields per request.
|
||||||
|
for r := 0; r < 100*20; r++ {
|
||||||
|
f := possible[rand.Int31n(int32(len(possible)))]
|
||||||
|
// Skip if this is in the staticTable verbatim.
|
||||||
|
if _, has := staticTable.search(f); !has {
|
||||||
|
e.dynTab.add(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
for _, f := range possible {
|
||||||
|
e.searchTable(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
100
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
100
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
|
@ -102,6 +102,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod
|
||||||
emit: emitFunc,
|
emit: emitFunc,
|
||||||
emitEnabled: true,
|
emitEnabled: true,
|
||||||
}
|
}
|
||||||
|
d.dynTab.table.init()
|
||||||
d.dynTab.allowedMaxSize = maxDynamicTableSize
|
d.dynTab.allowedMaxSize = maxDynamicTableSize
|
||||||
d.dynTab.setMaxSize(maxDynamicTableSize)
|
d.dynTab.setMaxSize(maxDynamicTableSize)
|
||||||
return d
|
return d
|
||||||
|
@ -154,12 +155,9 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type dynamicTable struct {
|
type dynamicTable struct {
|
||||||
// ents is the FIFO described at
|
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
|
||||||
// The newest (low index) is append at the end, and items are
|
table headerFieldTable
|
||||||
// evicted from the front.
|
size uint32 // in bytes
|
||||||
ents []HeaderField
|
|
||||||
size uint32
|
|
||||||
maxSize uint32 // current maxSize
|
maxSize uint32 // current maxSize
|
||||||
allowedMaxSize uint32 // maxSize may go up to this, inclusive
|
allowedMaxSize uint32 // maxSize may go up to this, inclusive
|
||||||
}
|
}
|
||||||
|
@ -169,95 +167,45 @@ func (dt *dynamicTable) setMaxSize(v uint32) {
|
||||||
dt.evict()
|
dt.evict()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change dynamicTable to be a struct with a slice and a size int field,
|
|
||||||
// per http://http2.github.io/http2-spec/compression.html#rfc.section.4.1:
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Then make add increment the size. maybe the max size should move from Decoder to
|
|
||||||
// dynamicTable and add should return an ok bool if there was enough space.
|
|
||||||
//
|
|
||||||
// Later we'll need a remove operation on dynamicTable.
|
|
||||||
|
|
||||||
func (dt *dynamicTable) add(f HeaderField) {
|
func (dt *dynamicTable) add(f HeaderField) {
|
||||||
dt.ents = append(dt.ents, f)
|
dt.table.addEntry(f)
|
||||||
dt.size += f.Size()
|
dt.size += f.Size()
|
||||||
dt.evict()
|
dt.evict()
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're too big, evict old stuff (front of the slice)
|
// If we're too big, evict old stuff.
|
||||||
func (dt *dynamicTable) evict() {
|
func (dt *dynamicTable) evict() {
|
||||||
base := dt.ents // keep base pointer of slice
|
var n int
|
||||||
for dt.size > dt.maxSize {
|
for dt.size > dt.maxSize && n < dt.table.len() {
|
||||||
dt.size -= dt.ents[0].Size()
|
dt.size -= dt.table.ents[n].Size()
|
||||||
dt.ents = dt.ents[1:]
|
n++
|
||||||
}
|
}
|
||||||
|
dt.table.evictOldest(n)
|
||||||
// Shift slice contents down if we evicted things.
|
|
||||||
if len(dt.ents) != len(base) {
|
|
||||||
copy(base, dt.ents)
|
|
||||||
dt.ents = base[:len(dt.ents)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// constantTimeStringCompare compares string a and b in a constant
|
|
||||||
// time manner.
|
|
||||||
func constantTimeStringCompare(a, b string) bool {
|
|
||||||
if len(a) != len(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
c := byte(0)
|
|
||||||
|
|
||||||
for i := 0; i < len(a); i++ {
|
|
||||||
c |= a[i] ^ b[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return c == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search searches f in the table. The return value i is 0 if there is
|
|
||||||
// no name match. If there is name match or name/value match, i is the
|
|
||||||
// index of that entry (1-based). If both name and value match,
|
|
||||||
// nameValueMatch becomes true.
|
|
||||||
func (dt *dynamicTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
|
|
||||||
l := len(dt.ents)
|
|
||||||
for j := l - 1; j >= 0; j-- {
|
|
||||||
ent := dt.ents[j]
|
|
||||||
if !constantTimeStringCompare(ent.Name, f.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
i = uint64(l - j)
|
|
||||||
}
|
|
||||||
if f.Sensitive {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !constantTimeStringCompare(ent.Value, f.Value) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i = uint64(l - j)
|
|
||||||
nameValueMatch = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) maxTableIndex() int {
|
func (d *Decoder) maxTableIndex() int {
|
||||||
return len(d.dynTab.ents) + len(staticTable)
|
// This should never overflow. RFC 7540 Section 6.5.2 limits the size of
|
||||||
|
// the dynamic table to 2^32 bytes, where each entry will occupy more than
|
||||||
|
// one byte. Further, the staticTable has a fixed, small length.
|
||||||
|
return d.dynTab.table.len() + staticTable.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
|
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
|
||||||
if i < 1 {
|
// See Section 2.3.3.
|
||||||
|
if i == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if i <= uint64(staticTable.len()) {
|
||||||
|
return staticTable.ents[i-1], true
|
||||||
|
}
|
||||||
if i > uint64(d.maxTableIndex()) {
|
if i > uint64(d.maxTableIndex()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if i <= uint64(len(staticTable)) {
|
// In the dynamic table, newer entries have lower indices.
|
||||||
return staticTable[i-1], true
|
// However, dt.ents[0] is the oldest entry. Hence, dt.ents is
|
||||||
}
|
// the reversed dynamic table.
|
||||||
dents := d.dynTab.ents
|
dt := d.dynTab.table
|
||||||
return dents[len(dents)-(int(i)-len(staticTable))], true
|
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes an entire block.
|
// Decode decodes an entire block.
|
||||||
|
|
150
vendor/golang.org/x/net/http2/hpack/hpack_test.go
generated
vendored
150
vendor/golang.org/x/net/http2/hpack/hpack_test.go
generated
vendored
|
@ -5,117 +5,16 @@
|
||||||
package hpack
|
package hpack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStaticTable(t *testing.T) {
|
|
||||||
fromSpec := `
|
|
||||||
+-------+-----------------------------+---------------+
|
|
||||||
| 1 | :authority | |
|
|
||||||
| 2 | :method | GET |
|
|
||||||
| 3 | :method | POST |
|
|
||||||
| 4 | :path | / |
|
|
||||||
| 5 | :path | /index.html |
|
|
||||||
| 6 | :scheme | http |
|
|
||||||
| 7 | :scheme | https |
|
|
||||||
| 8 | :status | 200 |
|
|
||||||
| 9 | :status | 204 |
|
|
||||||
| 10 | :status | 206 |
|
|
||||||
| 11 | :status | 304 |
|
|
||||||
| 12 | :status | 400 |
|
|
||||||
| 13 | :status | 404 |
|
|
||||||
| 14 | :status | 500 |
|
|
||||||
| 15 | accept-charset | |
|
|
||||||
| 16 | accept-encoding | gzip, deflate |
|
|
||||||
| 17 | accept-language | |
|
|
||||||
| 18 | accept-ranges | |
|
|
||||||
| 19 | accept | |
|
|
||||||
| 20 | access-control-allow-origin | |
|
|
||||||
| 21 | age | |
|
|
||||||
| 22 | allow | |
|
|
||||||
| 23 | authorization | |
|
|
||||||
| 24 | cache-control | |
|
|
||||||
| 25 | content-disposition | |
|
|
||||||
| 26 | content-encoding | |
|
|
||||||
| 27 | content-language | |
|
|
||||||
| 28 | content-length | |
|
|
||||||
| 29 | content-location | |
|
|
||||||
| 30 | content-range | |
|
|
||||||
| 31 | content-type | |
|
|
||||||
| 32 | cookie | |
|
|
||||||
| 33 | date | |
|
|
||||||
| 34 | etag | |
|
|
||||||
| 35 | expect | |
|
|
||||||
| 36 | expires | |
|
|
||||||
| 37 | from | |
|
|
||||||
| 38 | host | |
|
|
||||||
| 39 | if-match | |
|
|
||||||
| 40 | if-modified-since | |
|
|
||||||
| 41 | if-none-match | |
|
|
||||||
| 42 | if-range | |
|
|
||||||
| 43 | if-unmodified-since | |
|
|
||||||
| 44 | last-modified | |
|
|
||||||
| 45 | link | |
|
|
||||||
| 46 | location | |
|
|
||||||
| 47 | max-forwards | |
|
|
||||||
| 48 | proxy-authenticate | |
|
|
||||||
| 49 | proxy-authorization | |
|
|
||||||
| 50 | range | |
|
|
||||||
| 51 | referer | |
|
|
||||||
| 52 | refresh | |
|
|
||||||
| 53 | retry-after | |
|
|
||||||
| 54 | server | |
|
|
||||||
| 55 | set-cookie | |
|
|
||||||
| 56 | strict-transport-security | |
|
|
||||||
| 57 | transfer-encoding | |
|
|
||||||
| 58 | user-agent | |
|
|
||||||
| 59 | vary | |
|
|
||||||
| 60 | via | |
|
|
||||||
| 61 | www-authenticate | |
|
|
||||||
+-------+-----------------------------+---------------+
|
|
||||||
`
|
|
||||||
bs := bufio.NewScanner(strings.NewReader(fromSpec))
|
|
||||||
re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
|
|
||||||
for bs.Scan() {
|
|
||||||
l := bs.Text()
|
|
||||||
if !strings.Contains(l, "|") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m := re.FindStringSubmatch(l)
|
|
||||||
if m == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i, err := strconv.Atoi(m[1])
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Bogus integer on line %q", l)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i < 1 || i > len(staticTable) {
|
|
||||||
t.Errorf("Bogus index %d on line %q", i, l)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got, want := staticTable[i-1].Name, m[2]; got != want {
|
|
||||||
t.Errorf("header index %d name = %q; want %q", i, got, want)
|
|
||||||
}
|
|
||||||
if got, want := staticTable[i-1].Value, m[3]; got != want {
|
|
||||||
t.Errorf("header index %d value = %q; want %q", i, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := bs.Err(); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) mustAt(idx int) HeaderField {
|
func (d *Decoder) mustAt(idx int) HeaderField {
|
||||||
if hf, ok := d.at(uint64(idx)); !ok {
|
if hf, ok := d.at(uint64(idx)); !ok {
|
||||||
panic(fmt.Sprintf("bogus index %d", idx))
|
panic(fmt.Sprintf("bogus index %d", idx))
|
||||||
|
@ -132,10 +31,10 @@ func TestDynamicTableAt(t *testing.T) {
|
||||||
}
|
}
|
||||||
d.dynTab.add(pair("foo", "bar"))
|
d.dynTab.add(pair("foo", "bar"))
|
||||||
d.dynTab.add(pair("blake", "miz"))
|
d.dynTab.add(pair("blake", "miz"))
|
||||||
if got, want := at(len(staticTable)+1), (pair("blake", "miz")); got != want {
|
if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
|
||||||
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
if got, want := at(len(staticTable)+2), (pair("foo", "bar")); got != want {
|
if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
|
||||||
t.Errorf("at(dyn 2) = %v; want %v", got, want)
|
t.Errorf("at(dyn 2) = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
if got, want := at(3), (pair(":method", "POST")); got != want {
|
if got, want := at(3), (pair(":method", "POST")); got != want {
|
||||||
|
@ -143,41 +42,6 @@ func TestDynamicTableAt(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDynamicTableSearch(t *testing.T) {
|
|
||||||
dt := dynamicTable{}
|
|
||||||
dt.setMaxSize(4096)
|
|
||||||
|
|
||||||
dt.add(pair("foo", "bar"))
|
|
||||||
dt.add(pair("blake", "miz"))
|
|
||||||
dt.add(pair(":method", "GET"))
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
hf HeaderField
|
|
||||||
wantI uint64
|
|
||||||
wantMatch bool
|
|
||||||
}{
|
|
||||||
// Name and Value match
|
|
||||||
{pair("foo", "bar"), 3, true},
|
|
||||||
{pair(":method", "GET"), 1, true},
|
|
||||||
|
|
||||||
// Only name match because of Sensitive == true
|
|
||||||
{HeaderField{"blake", "miz", true}, 2, false},
|
|
||||||
|
|
||||||
// Only Name matches
|
|
||||||
{pair("foo", "..."), 3, false},
|
|
||||||
{pair("blake", "..."), 2, false},
|
|
||||||
{pair(":method", "..."), 1, false},
|
|
||||||
|
|
||||||
// None match
|
|
||||||
{pair("foo-", "bar"), 0, false},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
if gotI, gotMatch := dt.search(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
|
|
||||||
t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDynamicTableSizeEvict(t *testing.T) {
|
func TestDynamicTableSizeEvict(t *testing.T) {
|
||||||
d := NewDecoder(4096, nil)
|
d := NewDecoder(4096, nil)
|
||||||
if want := uint32(0); d.dynTab.size != want {
|
if want := uint32(0); d.dynTab.size != want {
|
||||||
|
@ -196,7 +60,7 @@ func TestDynamicTableSizeEvict(t *testing.T) {
|
||||||
if want := uint32(6 + 32); d.dynTab.size != want {
|
if want := uint32(6 + 32); d.dynTab.size != want {
|
||||||
t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
|
t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
|
||||||
}
|
}
|
||||||
if got, want := d.mustAt(len(staticTable)+1), (pair("foo", "bar")); got != want {
|
if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
|
||||||
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
t.Errorf("at(dyn 1) = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
add(pair("long", strings.Repeat("x", 500)))
|
add(pair("long", strings.Repeat("x", 500)))
|
||||||
|
@ -255,9 +119,9 @@ func TestDecoderDecode(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
|
func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
|
||||||
hf = make([]HeaderField, len(dt.ents))
|
hf = make([]HeaderField, len(dt.table.ents))
|
||||||
for i := range hf {
|
for i := range hf {
|
||||||
hf[i] = dt.ents[len(dt.ents)-1-i]
|
hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -784,6 +648,10 @@ func TestHuffmanFuzzCrash(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pair(name, value string) HeaderField {
|
||||||
|
return HeaderField{Name: name, Value: value}
|
||||||
|
}
|
||||||
|
|
||||||
func dehex(s string) []byte {
|
func dehex(s string) []byte {
|
||||||
s = strings.Replace(s, " ", "", -1)
|
s = strings.Replace(s, " ", "", -1)
|
||||||
s = strings.Replace(s, "\n", "", -1)
|
s = strings.Replace(s, "\n", "", -1)
|
||||||
|
|
255
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
255
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
|
@ -4,73 +4,200 @@
|
||||||
|
|
||||||
package hpack
|
package hpack
|
||||||
|
|
||||||
func pair(name, value string) HeaderField {
|
import (
|
||||||
return HeaderField{Name: name, Value: value}
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// headerFieldTable implements a list of HeaderFields.
|
||||||
|
// This is used to implement the static and dynamic tables.
|
||||||
|
type headerFieldTable struct {
|
||||||
|
// For static tables, entries are never evicted.
|
||||||
|
//
|
||||||
|
// For dynamic tables, entries are evicted from ents[0] and added to the end.
|
||||||
|
// Each entry has a unique id that starts at one and increments for each
|
||||||
|
// entry that is added. This unique id is stable across evictions, meaning
|
||||||
|
// it can be used as a pointer to a specific entry. As in hpack, unique ids
|
||||||
|
// are 1-based. The unique id for ents[k] is k + evictCount + 1.
|
||||||
|
//
|
||||||
|
// Zero is not a valid unique id.
|
||||||
|
//
|
||||||
|
// evictCount should not overflow in any remotely practical situation. In
|
||||||
|
// practice, we will have one dynamic table per HTTP/2 connection. If we
|
||||||
|
// assume a very powerful server that handles 1M QPS per connection and each
|
||||||
|
// request adds (then evicts) 100 entries from the table, it would still take
|
||||||
|
// 2M years for evictCount to overflow.
|
||||||
|
ents []HeaderField
|
||||||
|
evictCount uint64
|
||||||
|
|
||||||
|
// byName maps a HeaderField name to the unique id of the newest entry with
|
||||||
|
// the same name. See above for a definition of "unique id".
|
||||||
|
byName map[string]uint64
|
||||||
|
|
||||||
|
// byNameValue maps a HeaderField name/value pair to the unique id of the newest
|
||||||
|
// entry with the same name and value. See above for a definition of "unique id".
|
||||||
|
byNameValue map[pairNameValue]uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type pairNameValue struct {
|
||||||
|
name, value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *headerFieldTable) init() {
|
||||||
|
t.byName = make(map[string]uint64)
|
||||||
|
t.byNameValue = make(map[pairNameValue]uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// len reports the number of entries in the table.
|
||||||
|
func (t *headerFieldTable) len() int {
|
||||||
|
return len(t.ents)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addEntry adds a new entry.
|
||||||
|
func (t *headerFieldTable) addEntry(f HeaderField) {
|
||||||
|
id := uint64(t.len()) + t.evictCount + 1
|
||||||
|
t.byName[f.Name] = id
|
||||||
|
t.byNameValue[pairNameValue{f.Name, f.Value}] = id
|
||||||
|
t.ents = append(t.ents, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// evictOldest evicts the n oldest entries in the table.
|
||||||
|
func (t *headerFieldTable) evictOldest(n int) {
|
||||||
|
if n > t.len() {
|
||||||
|
panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
|
||||||
|
}
|
||||||
|
for k := 0; k < n; k++ {
|
||||||
|
f := t.ents[k]
|
||||||
|
id := t.evictCount + uint64(k) + 1
|
||||||
|
if t.byName[f.Name] == id {
|
||||||
|
delete(t.byName, f.Name)
|
||||||
|
}
|
||||||
|
if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
|
||||||
|
delete(t.byNameValue, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(t.ents, t.ents[n:])
|
||||||
|
for k := t.len() - n; k < t.len(); k++ {
|
||||||
|
t.ents[k] = HeaderField{} // so strings can be garbage collected
|
||||||
|
}
|
||||||
|
t.ents = t.ents[:t.len()-n]
|
||||||
|
if t.evictCount+uint64(n) < t.evictCount {
|
||||||
|
panic("evictCount overflow")
|
||||||
|
}
|
||||||
|
t.evictCount += uint64(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// search finds f in the table. If there is no match, i is 0.
|
||||||
|
// If both name and value match, i is the matched index and nameValueMatch
|
||||||
|
// becomes true. If only name matches, i points to that index and
|
||||||
|
// nameValueMatch becomes false.
|
||||||
|
//
|
||||||
|
// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
|
||||||
|
// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
|
||||||
|
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
|
||||||
|
// table, the return value i actually refers to the entry t.ents[t.len()-i].
|
||||||
|
//
|
||||||
|
// All tables are assumed to be a dynamic tables except for the global
|
||||||
|
// staticTable pointer.
|
||||||
|
//
|
||||||
|
// See Section 2.3.3.
|
||||||
|
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
|
||||||
|
if !f.Sensitive {
|
||||||
|
if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
|
||||||
|
return t.idToIndex(id), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id := t.byName[f.Name]; id != 0 {
|
||||||
|
return t.idToIndex(id), false
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// idToIndex converts a unique id to an HPACK index.
|
||||||
|
// See Section 2.3.3.
|
||||||
|
func (t *headerFieldTable) idToIndex(id uint64) uint64 {
|
||||||
|
if id <= t.evictCount {
|
||||||
|
panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
|
||||||
|
}
|
||||||
|
k := id - t.evictCount - 1 // convert id to an index t.ents[k]
|
||||||
|
if t != staticTable {
|
||||||
|
return uint64(t.len()) - k // dynamic table
|
||||||
|
}
|
||||||
|
return k + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
||||||
var staticTable = [...]HeaderField{
|
var staticTable = newStaticTable()
|
||||||
pair(":authority", ""), // index 1 (1-based)
|
var staticTableEntries = [...]HeaderField{
|
||||||
pair(":method", "GET"),
|
{Name: ":authority"},
|
||||||
pair(":method", "POST"),
|
{Name: ":method", Value: "GET"},
|
||||||
pair(":path", "/"),
|
{Name: ":method", Value: "POST"},
|
||||||
pair(":path", "/index.html"),
|
{Name: ":path", Value: "/"},
|
||||||
pair(":scheme", "http"),
|
{Name: ":path", Value: "/index.html"},
|
||||||
pair(":scheme", "https"),
|
{Name: ":scheme", Value: "http"},
|
||||||
pair(":status", "200"),
|
{Name: ":scheme", Value: "https"},
|
||||||
pair(":status", "204"),
|
{Name: ":status", Value: "200"},
|
||||||
pair(":status", "206"),
|
{Name: ":status", Value: "204"},
|
||||||
pair(":status", "304"),
|
{Name: ":status", Value: "206"},
|
||||||
pair(":status", "400"),
|
{Name: ":status", Value: "304"},
|
||||||
pair(":status", "404"),
|
{Name: ":status", Value: "400"},
|
||||||
pair(":status", "500"),
|
{Name: ":status", Value: "404"},
|
||||||
pair("accept-charset", ""),
|
{Name: ":status", Value: "500"},
|
||||||
pair("accept-encoding", "gzip, deflate"),
|
{Name: "accept-charset"},
|
||||||
pair("accept-language", ""),
|
{Name: "accept-encoding", Value: "gzip, deflate"},
|
||||||
pair("accept-ranges", ""),
|
{Name: "accept-language"},
|
||||||
pair("accept", ""),
|
{Name: "accept-ranges"},
|
||||||
pair("access-control-allow-origin", ""),
|
{Name: "accept"},
|
||||||
pair("age", ""),
|
{Name: "access-control-allow-origin"},
|
||||||
pair("allow", ""),
|
{Name: "age"},
|
||||||
pair("authorization", ""),
|
{Name: "allow"},
|
||||||
pair("cache-control", ""),
|
{Name: "authorization"},
|
||||||
pair("content-disposition", ""),
|
{Name: "cache-control"},
|
||||||
pair("content-encoding", ""),
|
{Name: "content-disposition"},
|
||||||
pair("content-language", ""),
|
{Name: "content-encoding"},
|
||||||
pair("content-length", ""),
|
{Name: "content-language"},
|
||||||
pair("content-location", ""),
|
{Name: "content-length"},
|
||||||
pair("content-range", ""),
|
{Name: "content-location"},
|
||||||
pair("content-type", ""),
|
{Name: "content-range"},
|
||||||
pair("cookie", ""),
|
{Name: "content-type"},
|
||||||
pair("date", ""),
|
{Name: "cookie"},
|
||||||
pair("etag", ""),
|
{Name: "date"},
|
||||||
pair("expect", ""),
|
{Name: "etag"},
|
||||||
pair("expires", ""),
|
{Name: "expect"},
|
||||||
pair("from", ""),
|
{Name: "expires"},
|
||||||
pair("host", ""),
|
{Name: "from"},
|
||||||
pair("if-match", ""),
|
{Name: "host"},
|
||||||
pair("if-modified-since", ""),
|
{Name: "if-match"},
|
||||||
pair("if-none-match", ""),
|
{Name: "if-modified-since"},
|
||||||
pair("if-range", ""),
|
{Name: "if-none-match"},
|
||||||
pair("if-unmodified-since", ""),
|
{Name: "if-range"},
|
||||||
pair("last-modified", ""),
|
{Name: "if-unmodified-since"},
|
||||||
pair("link", ""),
|
{Name: "last-modified"},
|
||||||
pair("location", ""),
|
{Name: "link"},
|
||||||
pair("max-forwards", ""),
|
{Name: "location"},
|
||||||
pair("proxy-authenticate", ""),
|
{Name: "max-forwards"},
|
||||||
pair("proxy-authorization", ""),
|
{Name: "proxy-authenticate"},
|
||||||
pair("range", ""),
|
{Name: "proxy-authorization"},
|
||||||
pair("referer", ""),
|
{Name: "range"},
|
||||||
pair("refresh", ""),
|
{Name: "referer"},
|
||||||
pair("retry-after", ""),
|
{Name: "refresh"},
|
||||||
pair("server", ""),
|
{Name: "retry-after"},
|
||||||
pair("set-cookie", ""),
|
{Name: "server"},
|
||||||
pair("strict-transport-security", ""),
|
{Name: "set-cookie"},
|
||||||
pair("transfer-encoding", ""),
|
{Name: "strict-transport-security"},
|
||||||
pair("user-agent", ""),
|
{Name: "transfer-encoding"},
|
||||||
pair("vary", ""),
|
{Name: "user-agent"},
|
||||||
pair("via", ""),
|
{Name: "vary"},
|
||||||
pair("www-authenticate", ""),
|
{Name: "via"},
|
||||||
|
{Name: "www-authenticate"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStaticTable() *headerFieldTable {
|
||||||
|
t := &headerFieldTable{}
|
||||||
|
t.init()
|
||||||
|
for _, e := range staticTableEntries[:] {
|
||||||
|
t.addEntry(e)
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
var huffmanCodes = [256]uint32{
|
var huffmanCodes = [256]uint32{
|
||||||
|
|
214
vendor/golang.org/x/net/http2/hpack/tables_test.go
generated
vendored
Normal file
214
vendor/golang.org/x/net/http2/hpack/tables_test.go
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHeaderFieldTable(t *testing.T) {
|
||||||
|
table := &headerFieldTable{}
|
||||||
|
table.init()
|
||||||
|
table.addEntry(pair("key1", "value1-1"))
|
||||||
|
table.addEntry(pair("key2", "value2-1"))
|
||||||
|
table.addEntry(pair("key1", "value1-2"))
|
||||||
|
table.addEntry(pair("key3", "value3-1"))
|
||||||
|
table.addEntry(pair("key4", "value4-1"))
|
||||||
|
table.addEntry(pair("key2", "value2-2"))
|
||||||
|
|
||||||
|
// Tests will be run twice: once before evicting anything, and
|
||||||
|
// again after evicting the three oldest entries.
|
||||||
|
tests := []struct {
|
||||||
|
f HeaderField
|
||||||
|
beforeWantStaticI uint64
|
||||||
|
beforeWantMatch bool
|
||||||
|
afterWantStaticI uint64
|
||||||
|
afterWantMatch bool
|
||||||
|
}{
|
||||||
|
{HeaderField{"key1", "value1-1", false}, 1, true, 0, false},
|
||||||
|
{HeaderField{"key1", "value1-2", false}, 3, true, 0, false},
|
||||||
|
{HeaderField{"key1", "value1-3", false}, 3, false, 0, false},
|
||||||
|
{HeaderField{"key2", "value2-1", false}, 2, true, 3, false},
|
||||||
|
{HeaderField{"key2", "value2-2", false}, 6, true, 3, true},
|
||||||
|
{HeaderField{"key2", "value2-3", false}, 6, false, 3, false},
|
||||||
|
{HeaderField{"key4", "value4-1", false}, 5, true, 2, true},
|
||||||
|
// Name match only, because sensitive.
|
||||||
|
{HeaderField{"key4", "value4-1", true}, 5, false, 2, false},
|
||||||
|
// Key not found.
|
||||||
|
{HeaderField{"key5", "value5-x", false}, 0, false, 0, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
staticToDynamic := func(i uint64) uint64 {
|
||||||
|
if i == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return uint64(table.len()) - i + 1 // dynamic is the reversed table
|
||||||
|
}
|
||||||
|
|
||||||
|
searchStatic := func(f HeaderField) (uint64, bool) {
|
||||||
|
old := staticTable
|
||||||
|
staticTable = table
|
||||||
|
defer func() { staticTable = old }()
|
||||||
|
return staticTable.search(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchDynamic := func(f HeaderField) (uint64, bool) {
|
||||||
|
return table.search(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
gotI, gotMatch := searchStatic(test.f)
|
||||||
|
if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||||
|
t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||||
|
}
|
||||||
|
gotI, gotMatch = searchDynamic(test.f)
|
||||||
|
wantDynamicI := staticToDynamic(test.beforeWantStaticI)
|
||||||
|
if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||||
|
t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evictOldest(3)
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
gotI, gotMatch := searchStatic(test.f)
|
||||||
|
if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||||
|
t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||||
|
}
|
||||||
|
gotI, gotMatch = searchDynamic(test.f)
|
||||||
|
wantDynamicI := staticToDynamic(test.afterWantStaticI)
|
||||||
|
if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
|
||||||
|
t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHeaderFieldTable_LookupMapEviction(t *testing.T) {
|
||||||
|
table := &headerFieldTable{}
|
||||||
|
table.init()
|
||||||
|
table.addEntry(pair("key1", "value1-1"))
|
||||||
|
table.addEntry(pair("key2", "value2-1"))
|
||||||
|
table.addEntry(pair("key1", "value1-2"))
|
||||||
|
table.addEntry(pair("key3", "value3-1"))
|
||||||
|
table.addEntry(pair("key4", "value4-1"))
|
||||||
|
table.addEntry(pair("key2", "value2-2"))
|
||||||
|
|
||||||
|
// evict all pairs
|
||||||
|
table.evictOldest(table.len())
|
||||||
|
|
||||||
|
if l := table.len(); l > 0 {
|
||||||
|
t.Errorf("table.len() = %d, want 0", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l := len(table.byName); l > 0 {
|
||||||
|
t.Errorf("len(table.byName) = %d, want 0", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l := len(table.byNameValue); l > 0 {
|
||||||
|
t.Errorf("len(table.byNameValue) = %d, want 0", l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStaticTable(t *testing.T) {
|
||||||
|
fromSpec := `
|
||||||
|
+-------+-----------------------------+---------------+
|
||||||
|
| 1 | :authority | |
|
||||||
|
| 2 | :method | GET |
|
||||||
|
| 3 | :method | POST |
|
||||||
|
| 4 | :path | / |
|
||||||
|
| 5 | :path | /index.html |
|
||||||
|
| 6 | :scheme | http |
|
||||||
|
| 7 | :scheme | https |
|
||||||
|
| 8 | :status | 200 |
|
||||||
|
| 9 | :status | 204 |
|
||||||
|
| 10 | :status | 206 |
|
||||||
|
| 11 | :status | 304 |
|
||||||
|
| 12 | :status | 400 |
|
||||||
|
| 13 | :status | 404 |
|
||||||
|
| 14 | :status | 500 |
|
||||||
|
| 15 | accept-charset | |
|
||||||
|
| 16 | accept-encoding | gzip, deflate |
|
||||||
|
| 17 | accept-language | |
|
||||||
|
| 18 | accept-ranges | |
|
||||||
|
| 19 | accept | |
|
||||||
|
| 20 | access-control-allow-origin | |
|
||||||
|
| 21 | age | |
|
||||||
|
| 22 | allow | |
|
||||||
|
| 23 | authorization | |
|
||||||
|
| 24 | cache-control | |
|
||||||
|
| 25 | content-disposition | |
|
||||||
|
| 26 | content-encoding | |
|
||||||
|
| 27 | content-language | |
|
||||||
|
| 28 | content-length | |
|
||||||
|
| 29 | content-location | |
|
||||||
|
| 30 | content-range | |
|
||||||
|
| 31 | content-type | |
|
||||||
|
| 32 | cookie | |
|
||||||
|
| 33 | date | |
|
||||||
|
| 34 | etag | |
|
||||||
|
| 35 | expect | |
|
||||||
|
| 36 | expires | |
|
||||||
|
| 37 | from | |
|
||||||
|
| 38 | host | |
|
||||||
|
| 39 | if-match | |
|
||||||
|
| 40 | if-modified-since | |
|
||||||
|
| 41 | if-none-match | |
|
||||||
|
| 42 | if-range | |
|
||||||
|
| 43 | if-unmodified-since | |
|
||||||
|
| 44 | last-modified | |
|
||||||
|
| 45 | link | |
|
||||||
|
| 46 | location | |
|
||||||
|
| 47 | max-forwards | |
|
||||||
|
| 48 | proxy-authenticate | |
|
||||||
|
| 49 | proxy-authorization | |
|
||||||
|
| 50 | range | |
|
||||||
|
| 51 | referer | |
|
||||||
|
| 52 | refresh | |
|
||||||
|
| 53 | retry-after | |
|
||||||
|
| 54 | server | |
|
||||||
|
| 55 | set-cookie | |
|
||||||
|
| 56 | strict-transport-security | |
|
||||||
|
| 57 | transfer-encoding | |
|
||||||
|
| 58 | user-agent | |
|
||||||
|
| 59 | vary | |
|
||||||
|
| 60 | via | |
|
||||||
|
| 61 | www-authenticate | |
|
||||||
|
+-------+-----------------------------+---------------+
|
||||||
|
`
|
||||||
|
bs := bufio.NewScanner(strings.NewReader(fromSpec))
|
||||||
|
re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
|
||||||
|
for bs.Scan() {
|
||||||
|
l := bs.Text()
|
||||||
|
if !strings.Contains(l, "|") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m := re.FindStringSubmatch(l)
|
||||||
|
if m == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
i, err := strconv.Atoi(m[1])
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Bogus integer on line %q", l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i < 1 || i > staticTable.len() {
|
||||||
|
t.Errorf("Bogus index %d on line %q", i, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got, want := staticTable.ents[i-1].Name, m[2]; got != want {
|
||||||
|
t.Errorf("header index %d name = %q; want %q", i, got, want)
|
||||||
|
}
|
||||||
|
if got, want := staticTable.ents[i-1].Value, m[3]; got != want {
|
||||||
|
t.Errorf("header index %d value = %q; want %q", i, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := bs.Err(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
25
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
25
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
|
@ -7,7 +7,6 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -20,27 +19,3 @@ func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// 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"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
16
vendor/golang.org/x/net/http2/not_go19.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/http2/not_go19.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// 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.9
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configureServer19(s *http.Server, conf *Server) error {
|
||||||
|
// not supported prior to go1.9
|
||||||
|
return nil
|
||||||
|
}
|
14
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
14
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
|
@ -16,7 +16,7 @@ import (
|
||||||
type pipe struct {
|
type pipe struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
c sync.Cond // c.L lazily initialized to &p.mu
|
c sync.Cond // c.L lazily initialized to &p.mu
|
||||||
b pipeBuffer
|
b pipeBuffer // nil when done reading
|
||||||
err error // read error once empty. non-nil means closed.
|
err error // read error once empty. non-nil means closed.
|
||||||
breakErr error // immediate read error (caller doesn't see rest of b)
|
breakErr error // immediate read error (caller doesn't see rest of b)
|
||||||
donec chan struct{} // closed on error
|
donec chan struct{} // closed on error
|
||||||
|
@ -32,6 +32,9 @@ type pipeBuffer interface {
|
||||||
func (p *pipe) Len() int {
|
func (p *pipe) Len() int {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
if p.b == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return p.b.Len()
|
return p.b.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
if p.breakErr != nil {
|
if p.breakErr != nil {
|
||||||
return 0, p.breakErr
|
return 0, p.breakErr
|
||||||
}
|
}
|
||||||
if p.b.Len() > 0 {
|
if p.b != nil && p.b.Len() > 0 {
|
||||||
return p.b.Read(d)
|
return p.b.Read(d)
|
||||||
}
|
}
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
|
@ -55,6 +58,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
p.readFn() // e.g. copy trailers
|
p.readFn() // e.g. copy trailers
|
||||||
p.readFn = nil // not sticky like p.err
|
p.readFn = nil // not sticky like p.err
|
||||||
}
|
}
|
||||||
|
p.b = nil
|
||||||
return 0, p.err
|
return 0, p.err
|
||||||
}
|
}
|
||||||
p.c.Wait()
|
p.c.Wait()
|
||||||
|
@ -75,6 +79,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
return 0, errClosedPipeWrite
|
return 0, errClosedPipeWrite
|
||||||
}
|
}
|
||||||
|
if p.breakErr != nil {
|
||||||
|
return len(d), nil // discard when there is no reader
|
||||||
|
}
|
||||||
return p.b.Write(d)
|
return p.b.Write(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +116,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.readFn = fn
|
p.readFn = fn
|
||||||
|
if dst == &p.breakErr {
|
||||||
|
p.b = nil
|
||||||
|
}
|
||||||
*dst = err
|
*dst = err
|
||||||
p.closeDoneLocked()
|
p.closeDoneLocked()
|
||||||
}
|
}
|
||||||
|
|
21
vendor/golang.org/x/net/http2/pipe_test.go
generated
vendored
21
vendor/golang.org/x/net/http2/pipe_test.go
generated
vendored
|
@ -92,6 +92,13 @@ func TestPipeCloseWithError(t *testing.T) {
|
||||||
if err != a {
|
if err != a {
|
||||||
t.Logf("read error = %v, %v", err, a)
|
t.Logf("read error = %v, %v", err, a)
|
||||||
}
|
}
|
||||||
|
// Read and Write should fail.
|
||||||
|
if n, err := p.Write([]byte("abc")); err != errClosedPipeWrite || n != 0 {
|
||||||
|
t.Errorf("Write(abc) after close\ngot %v, %v\nwant 0, %v", n, err, errClosedPipeWrite)
|
||||||
|
}
|
||||||
|
if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
|
||||||
|
t.Errorf("Read() after close\ngot %v, nil\nwant 0, %v", n, errClosedPipeWrite)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPipeBreakWithError(t *testing.T) {
|
func TestPipeBreakWithError(t *testing.T) {
|
||||||
|
@ -106,4 +113,18 @@ func TestPipeBreakWithError(t *testing.T) {
|
||||||
if err != a {
|
if err != a {
|
||||||
t.Logf("read error = %v, %v", err, a)
|
t.Logf("read error = %v, %v", err, a)
|
||||||
}
|
}
|
||||||
|
if p.b != nil {
|
||||||
|
t.Errorf("buffer should be nil after BreakWithError")
|
||||||
|
}
|
||||||
|
// Write should succeed silently.
|
||||||
|
if n, err := p.Write([]byte("abc")); err != nil || n != 3 {
|
||||||
|
t.Errorf("Write(abc) after break\ngot %v, %v\nwant 0, nil", n, err)
|
||||||
|
}
|
||||||
|
if p.b != nil {
|
||||||
|
t.Errorf("buffer should be nil after Write")
|
||||||
|
}
|
||||||
|
// Read should fail.
|
||||||
|
if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
|
||||||
|
t.Errorf("Read() after close\ngot %v, nil\nwant 0, not nil", n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
311
vendor/golang.org/x/net/http2/server.go
generated
vendored
311
vendor/golang.org/x/net/http2/server.go
generated
vendored
|
@ -110,9 +110,41 @@ type Server struct {
|
||||||
// activity for the purposes of IdleTimeout.
|
// activity for the purposes of IdleTimeout.
|
||||||
IdleTimeout time.Duration
|
IdleTimeout time.Duration
|
||||||
|
|
||||||
|
// MaxUploadBufferPerConnection is the size of the initial flow
|
||||||
|
// control window for each connections. The HTTP/2 spec does not
|
||||||
|
// allow this to be smaller than 65535 or larger than 2^32-1.
|
||||||
|
// If the value is outside this range, a default value will be
|
||||||
|
// used instead.
|
||||||
|
MaxUploadBufferPerConnection int32
|
||||||
|
|
||||||
|
// MaxUploadBufferPerStream is the size of the initial flow control
|
||||||
|
// window for each stream. The HTTP/2 spec does not allow this to
|
||||||
|
// be larger than 2^32-1. If the value is zero or larger than the
|
||||||
|
// maximum, a default value will be used instead.
|
||||||
|
MaxUploadBufferPerStream int32
|
||||||
|
|
||||||
// NewWriteScheduler constructs a write scheduler for a connection.
|
// NewWriteScheduler constructs a write scheduler for a connection.
|
||||||
// If nil, a default scheduler is chosen.
|
// If nil, a default scheduler is chosen.
|
||||||
NewWriteScheduler func() WriteScheduler
|
NewWriteScheduler func() WriteScheduler
|
||||||
|
|
||||||
|
// Internal state. This is a pointer (rather than embedded directly)
|
||||||
|
// so that we don't embed a Mutex in this struct, which will make the
|
||||||
|
// struct non-copyable, which might break some callers.
|
||||||
|
state *serverInternalState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||||
|
if s.MaxUploadBufferPerConnection > initialWindowSize {
|
||||||
|
return s.MaxUploadBufferPerConnection
|
||||||
|
}
|
||||||
|
return 1 << 20
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) initialStreamRecvWindowSize() int32 {
|
||||||
|
if s.MaxUploadBufferPerStream > 0 {
|
||||||
|
return s.MaxUploadBufferPerStream
|
||||||
|
}
|
||||||
|
return 1 << 20
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) maxReadFrameSize() uint32 {
|
func (s *Server) maxReadFrameSize() uint32 {
|
||||||
|
@ -129,6 +161,40 @@ func (s *Server) maxConcurrentStreams() uint32 {
|
||||||
return defaultMaxStreams
|
return defaultMaxStreams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type serverInternalState struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
activeConns map[*serverConn]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) registerConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
s.activeConns[sc] = struct{}{}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) unregisterConn(sc *serverConn) {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
delete(s.activeConns, sc)
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serverInternalState) startGracefulShutdown() {
|
||||||
|
if s == nil {
|
||||||
|
return // if the Server was used without calling ConfigureServer
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
for sc := range s.activeConns {
|
||||||
|
sc.startGracefulShutdown()
|
||||||
|
}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
||||||
//
|
//
|
||||||
// The configuration conf may be nil.
|
// The configuration conf may be nil.
|
||||||
|
@ -141,9 +207,13 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
conf = new(Server)
|
conf = new(Server)
|
||||||
}
|
}
|
||||||
|
conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
|
||||||
if err := configureServer18(s, conf); err != nil {
|
if err := configureServer18(s, conf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := configureServer19(s, conf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if s.TLSConfig == nil {
|
if s.TLSConfig == nil {
|
||||||
s.TLSConfig = new(tls.Config)
|
s.TLSConfig = new(tls.Config)
|
||||||
|
@ -265,25 +335,40 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||||
streams: make(map[uint32]*stream),
|
streams: make(map[uint32]*stream),
|
||||||
readFrameCh: make(chan readFrameResult),
|
readFrameCh: make(chan readFrameResult),
|
||||||
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
wantWriteFrameCh: make(chan FrameWriteRequest, 8),
|
||||||
wantStartPushCh: make(chan startPushRequest, 8),
|
serveMsgCh: make(chan interface{}, 8),
|
||||||
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
|
||||||
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
||||||
doneServing: make(chan struct{}),
|
doneServing: make(chan struct{}),
|
||||||
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
|
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
|
||||||
advMaxStreams: s.maxConcurrentStreams(),
|
advMaxStreams: s.maxConcurrentStreams(),
|
||||||
initialWindowSize: initialWindowSize,
|
initialStreamSendWindowSize: initialWindowSize,
|
||||||
maxFrameSize: initialMaxFrameSize,
|
maxFrameSize: initialMaxFrameSize,
|
||||||
headerTableSize: initialHeaderTableSize,
|
headerTableSize: initialHeaderTableSize,
|
||||||
serveG: newGoroutineLock(),
|
serveG: newGoroutineLock(),
|
||||||
pushEnabled: true,
|
pushEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.state.registerConn(sc)
|
||||||
|
defer s.state.unregisterConn(sc)
|
||||||
|
|
||||||
|
// The net/http package sets the write deadline from the
|
||||||
|
// http.Server.WriteTimeout during the TLS handshake, but then
|
||||||
|
// passes the connection off to us with the deadline already set.
|
||||||
|
// Write deadlines are set per stream in serverConn.newStream.
|
||||||
|
// Disarm the net.Conn write deadline here.
|
||||||
|
if sc.hs.WriteTimeout != 0 {
|
||||||
|
sc.conn.SetWriteDeadline(time.Time{})
|
||||||
|
}
|
||||||
|
|
||||||
if s.NewWriteScheduler != nil {
|
if s.NewWriteScheduler != nil {
|
||||||
sc.writeSched = s.NewWriteScheduler()
|
sc.writeSched = s.NewWriteScheduler()
|
||||||
} else {
|
} else {
|
||||||
sc.writeSched = NewRandomWriteScheduler()
|
sc.writeSched = NewRandomWriteScheduler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These start at the RFC-specified defaults. If there is a higher
|
||||||
|
// configured value for inflow, that will be updated when we send a
|
||||||
|
// WINDOW_UPDATE shortly after sending SETTINGS.
|
||||||
sc.flow.add(initialWindowSize)
|
sc.flow.add(initialWindowSize)
|
||||||
sc.inflow.add(initialWindowSize)
|
sc.inflow.add(initialWindowSize)
|
||||||
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
||||||
|
@ -366,10 +451,9 @@ type serverConn struct {
|
||||||
doneServing chan struct{} // closed when serverConn.serve ends
|
doneServing chan struct{} // closed when serverConn.serve ends
|
||||||
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
||||||
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
|
||||||
wantStartPushCh chan startPushRequest // from handlers -> serve
|
|
||||||
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
||||||
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
||||||
testHookCh chan func(int) // code to run on the serve loop
|
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
||||||
flow flow // conn-wide (not stream-specific) outbound flow control
|
flow flow // conn-wide (not stream-specific) outbound flow control
|
||||||
inflow flow // conn-wide inbound flow control
|
inflow flow // conn-wide inbound flow control
|
||||||
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
||||||
|
@ -389,7 +473,7 @@ type serverConn struct {
|
||||||
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
|
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
|
||||||
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
||||||
streams map[uint32]*stream
|
streams map[uint32]*stream
|
||||||
initialWindowSize int32
|
initialStreamSendWindowSize int32
|
||||||
maxFrameSize int32
|
maxFrameSize int32
|
||||||
headerTableSize uint32
|
headerTableSize uint32
|
||||||
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
||||||
|
@ -401,14 +485,15 @@ type serverConn struct {
|
||||||
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
||||||
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
||||||
goAwayCode ErrCode
|
goAwayCode ErrCode
|
||||||
shutdownTimerCh <-chan time.Time // nil until used
|
|
||||||
shutdownTimer *time.Timer // nil until used
|
shutdownTimer *time.Timer // nil until used
|
||||||
idleTimer *time.Timer // nil if unused
|
idleTimer *time.Timer // nil if unused
|
||||||
idleTimerCh <-chan time.Time // nil if unused
|
|
||||||
|
|
||||||
// Owned by the writeFrameAsync goroutine:
|
// Owned by the writeFrameAsync goroutine:
|
||||||
headerWriteBuf bytes.Buffer
|
headerWriteBuf bytes.Buffer
|
||||||
hpackEncoder *hpack.Encoder
|
hpackEncoder *hpack.Encoder
|
||||||
|
|
||||||
|
// Used by startGracefulShutdown.
|
||||||
|
shutdownOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) maxHeaderListSize() uint32 {
|
func (sc *serverConn) maxHeaderListSize() uint32 {
|
||||||
|
@ -456,7 +541,7 @@ type stream struct {
|
||||||
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
||||||
gotTrailerHeader bool // HEADER frame for trailers was seen
|
gotTrailerHeader bool // HEADER frame for trailers was seen
|
||||||
wroteHeaders bool // whether we wrote headers (not status 100)
|
wroteHeaders bool // whether we wrote headers (not status 100)
|
||||||
reqBuf []byte // if non-nil, body pipe buffer to return later at EOF
|
writeDeadline *time.Timer // nil if unused
|
||||||
|
|
||||||
trailer http.Header // accumulated trailers
|
trailer http.Header // accumulated trailers
|
||||||
reqTrailer http.Header // handler's Request.Trailer
|
reqTrailer http.Header // handler's Request.Trailer
|
||||||
|
@ -686,15 +771,17 @@ func (sc *serverConn) serve() {
|
||||||
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
|
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
|
||||||
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
||||||
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
||||||
|
{SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
|
||||||
// TODO: more actual settings, notably
|
|
||||||
// SettingInitialWindowSize, but then we also
|
|
||||||
// want to bump up the conn window size the
|
|
||||||
// same amount here right after the settings
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
sc.unackedSettings++
|
sc.unackedSettings++
|
||||||
|
|
||||||
|
// Each connection starts with intialWindowSize inflow tokens.
|
||||||
|
// If a higher value is configured, we add more tokens.
|
||||||
|
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
|
||||||
|
sc.sendWindowUpdate(nil, int(diff))
|
||||||
|
}
|
||||||
|
|
||||||
if err := sc.readPreface(); err != nil {
|
if err := sc.readPreface(); err != nil {
|
||||||
sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
|
sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
|
@ -707,27 +794,25 @@ func (sc *serverConn) serve() {
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
|
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout != 0 {
|
||||||
sc.idleTimer = time.NewTimer(sc.srv.IdleTimeout)
|
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||||
defer sc.idleTimer.Stop()
|
defer sc.idleTimer.Stop()
|
||||||
sc.idleTimerCh = sc.idleTimer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
var gracefulShutdownCh <-chan struct{}
|
|
||||||
if sc.hs != nil {
|
|
||||||
gracefulShutdownCh = h1ServerShutdownChan(sc.hs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go sc.readFrames() // closed by defer sc.conn.Close above
|
go sc.readFrames() // closed by defer sc.conn.Close above
|
||||||
|
|
||||||
settingsTimer := time.NewTimer(firstSettingsTimeout)
|
settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
|
||||||
|
defer settingsTimer.Stop()
|
||||||
|
|
||||||
loopNum := 0
|
loopNum := 0
|
||||||
for {
|
for {
|
||||||
loopNum++
|
loopNum++
|
||||||
select {
|
select {
|
||||||
case wr := <-sc.wantWriteFrameCh:
|
case wr := <-sc.wantWriteFrameCh:
|
||||||
|
if se, ok := wr.write.(StreamError); ok {
|
||||||
|
sc.resetStream(se)
|
||||||
|
break
|
||||||
|
}
|
||||||
sc.writeFrame(wr)
|
sc.writeFrame(wr)
|
||||||
case spr := <-sc.wantStartPushCh:
|
|
||||||
sc.startPush(spr)
|
|
||||||
case res := <-sc.wroteFrameCh:
|
case res := <-sc.wroteFrameCh:
|
||||||
sc.wroteFrame(res)
|
sc.wroteFrame(res)
|
||||||
case res := <-sc.readFrameCh:
|
case res := <-sc.readFrameCh:
|
||||||
|
@ -735,26 +820,37 @@ func (sc *serverConn) serve() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res.readMore()
|
res.readMore()
|
||||||
if settingsTimer.C != nil {
|
if settingsTimer != nil {
|
||||||
settingsTimer.Stop()
|
settingsTimer.Stop()
|
||||||
settingsTimer.C = nil
|
settingsTimer = nil
|
||||||
}
|
}
|
||||||
case m := <-sc.bodyReadCh:
|
case m := <-sc.bodyReadCh:
|
||||||
sc.noteBodyRead(m.st, m.n)
|
sc.noteBodyRead(m.st, m.n)
|
||||||
case <-settingsTimer.C:
|
case msg := <-sc.serveMsgCh:
|
||||||
|
switch v := msg.(type) {
|
||||||
|
case func(int):
|
||||||
|
v(loopNum) // for testing
|
||||||
|
case *serverMessage:
|
||||||
|
switch v {
|
||||||
|
case settingsTimerMsg:
|
||||||
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
||||||
return
|
return
|
||||||
case <-gracefulShutdownCh:
|
case idleTimerMsg:
|
||||||
gracefulShutdownCh = nil
|
|
||||||
sc.startGracefulShutdown()
|
|
||||||
case <-sc.shutdownTimerCh:
|
|
||||||
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
|
||||||
return
|
|
||||||
case <-sc.idleTimerCh:
|
|
||||||
sc.vlogf("connection is idle")
|
sc.vlogf("connection is idle")
|
||||||
sc.goAway(ErrCodeNo)
|
sc.goAway(ErrCodeNo)
|
||||||
case fn := <-sc.testHookCh:
|
case shutdownTimerMsg:
|
||||||
fn(loopNum)
|
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
||||||
|
return
|
||||||
|
case gracefulShutdownMsg:
|
||||||
|
sc.startGracefulShutdownInternal()
|
||||||
|
default:
|
||||||
|
panic("unknown timer")
|
||||||
|
}
|
||||||
|
case *startPushRequest:
|
||||||
|
sc.startPush(v)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected type %T", v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
|
if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
|
||||||
|
@ -763,6 +859,36 @@ func (sc *serverConn) serve() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
|
||||||
|
select {
|
||||||
|
case <-sc.doneServing:
|
||||||
|
case <-sharedCh:
|
||||||
|
close(privateCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverMessage int
|
||||||
|
|
||||||
|
// Message values sent to serveMsgCh.
|
||||||
|
var (
|
||||||
|
settingsTimerMsg = new(serverMessage)
|
||||||
|
idleTimerMsg = new(serverMessage)
|
||||||
|
shutdownTimerMsg = new(serverMessage)
|
||||||
|
gracefulShutdownMsg = new(serverMessage)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
||||||
|
func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
|
||||||
|
func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
|
||||||
|
|
||||||
|
func (sc *serverConn) sendServeMsg(msg interface{}) {
|
||||||
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
select {
|
||||||
|
case sc.serveMsgCh <- msg:
|
||||||
|
case <-sc.doneServing:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// readPreface reads the ClientPreface greeting from the peer
|
// readPreface reads the ClientPreface greeting from the peer
|
||||||
// or returns an error on timeout or an invalid greeting.
|
// or returns an error on timeout or an invalid greeting.
|
||||||
func (sc *serverConn) readPreface() error {
|
func (sc *serverConn) readPreface() error {
|
||||||
|
@ -1004,7 +1130,11 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
|
||||||
// stateClosed after the RST_STREAM frame is
|
// stateClosed after the RST_STREAM frame is
|
||||||
// written.
|
// written.
|
||||||
st.state = stateHalfClosedLocal
|
st.state = stateHalfClosedLocal
|
||||||
sc.resetStream(streamError(st.id, ErrCodeCancel))
|
// Section 8.1: a server MAY request that the client abort
|
||||||
|
// transmission of a request without error by sending a
|
||||||
|
// RST_STREAM with an error code of NO_ERROR after sending
|
||||||
|
// a complete response.
|
||||||
|
sc.resetStream(streamError(st.id, ErrCodeNo))
|
||||||
case stateHalfClosedRemote:
|
case stateHalfClosedRemote:
|
||||||
sc.closeStream(st, errHandlerComplete)
|
sc.closeStream(st, errHandlerComplete)
|
||||||
}
|
}
|
||||||
|
@ -1076,10 +1206,19 @@ func (sc *serverConn) scheduleFrameWrite() {
|
||||||
sc.inFrameScheduleLoop = false
|
sc.inFrameScheduleLoop = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// startGracefulShutdown sends a GOAWAY with ErrCodeNo to tell the
|
// startGracefulShutdown gracefully shuts down a connection. This
|
||||||
// client we're gracefully shutting down. The connection isn't closed
|
// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
|
||||||
// until all current streams are done.
|
// shutting down. The connection isn't closed until all current
|
||||||
|
// streams are done.
|
||||||
|
//
|
||||||
|
// startGracefulShutdown returns immediately; it does not wait until
|
||||||
|
// the connection has shut down.
|
||||||
func (sc *serverConn) startGracefulShutdown() {
|
func (sc *serverConn) startGracefulShutdown() {
|
||||||
|
sc.serveG.checkNotOn() // NOT
|
||||||
|
sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc *serverConn) startGracefulShutdownInternal() {
|
||||||
sc.goAwayIn(ErrCodeNo, 0)
|
sc.goAwayIn(ErrCodeNo, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,8 +1250,7 @@ func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
||||||
|
|
||||||
func (sc *serverConn) shutDownIn(d time.Duration) {
|
func (sc *serverConn) shutDownIn(d time.Duration) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
sc.shutdownTimer = time.NewTimer(d)
|
sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
|
||||||
sc.shutdownTimerCh = sc.shutdownTimer.C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) resetStream(se StreamError) {
|
func (sc *serverConn) resetStream(se StreamError) {
|
||||||
|
@ -1295,6 +1433,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
||||||
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
|
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
|
||||||
}
|
}
|
||||||
st.state = stateClosed
|
st.state = stateClosed
|
||||||
|
if st.writeDeadline != nil {
|
||||||
|
st.writeDeadline.Stop()
|
||||||
|
}
|
||||||
if st.isPushed() {
|
if st.isPushed() {
|
||||||
sc.curPushedStreams--
|
sc.curPushedStreams--
|
||||||
} else {
|
} else {
|
||||||
|
@ -1307,7 +1448,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
||||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||||
}
|
}
|
||||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p := st.body; p != nil {
|
if p := st.body; p != nil {
|
||||||
|
@ -1385,9 +1526,9 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
|
||||||
// adjust the size of all stream flow control windows that it
|
// adjust the size of all stream flow control windows that it
|
||||||
// maintains by the difference between the new value and the
|
// maintains by the difference between the new value and the
|
||||||
// old value."
|
// old value."
|
||||||
old := sc.initialWindowSize
|
old := sc.initialStreamSendWindowSize
|
||||||
sc.initialWindowSize = int32(val)
|
sc.initialStreamSendWindowSize = int32(val)
|
||||||
growth := sc.initialWindowSize - old // may be negative
|
growth := int32(val) - old // may be negative
|
||||||
for _, st := range sc.streams {
|
for _, st := range sc.streams {
|
||||||
if !st.flow.add(growth) {
|
if !st.flow.add(growth) {
|
||||||
// 6.9.2 Initial Flow Control Window Size
|
// 6.9.2 Initial Flow Control Window Size
|
||||||
|
@ -1494,7 +1635,7 @@ func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
|
||||||
} else {
|
} else {
|
||||||
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
|
||||||
}
|
}
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.8
|
// http://tools.ietf.org/html/rfc7540#section-6.8
|
||||||
// We should not create any new streams, which means we should disable push.
|
// We should not create any new streams, which means we should disable push.
|
||||||
sc.pushEnabled = false
|
sc.pushEnabled = false
|
||||||
|
@ -1533,6 +1674,12 @@ func (st *stream) copyTrailersToHandlerRequest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
|
||||||
|
// when the stream's WriteTimeout has fired.
|
||||||
|
func (st *stream) onWriteTimeout() {
|
||||||
|
st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
|
||||||
|
}
|
||||||
|
|
||||||
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
id := f.StreamID
|
id := f.StreamID
|
||||||
|
@ -1709,9 +1856,12 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
||||||
}
|
}
|
||||||
st.cw.Init()
|
st.cw.Init()
|
||||||
st.flow.conn = &sc.flow // link to conn-level counter
|
st.flow.conn = &sc.flow // link to conn-level counter
|
||||||
st.flow.add(sc.initialWindowSize)
|
st.flow.add(sc.initialStreamSendWindowSize)
|
||||||
st.inflow.conn = &sc.inflow // link to conn-level counter
|
st.inflow.conn = &sc.inflow // link to conn-level counter
|
||||||
st.inflow.add(initialWindowSize) // TODO: update this when we send a higher initial window size in the initial settings
|
st.inflow.add(sc.srv.initialStreamRecvWindowSize())
|
||||||
|
if sc.hs.WriteTimeout != 0 {
|
||||||
|
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
sc.streams[id] = st
|
sc.streams[id] = st
|
||||||
sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
|
sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
|
||||||
|
@ -1775,16 +1925,14 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if bodyOpen {
|
if bodyOpen {
|
||||||
st.reqBuf = getRequestBodyBuf()
|
|
||||||
req.Body.(*requestBody).pipe = &pipe{
|
|
||||||
b: &fixedBuffer{buf: st.reqBuf},
|
|
||||||
}
|
|
||||||
|
|
||||||
if vv, ok := rp.header["Content-Length"]; ok {
|
if vv, ok := rp.header["Content-Length"]; ok {
|
||||||
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
|
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
|
||||||
} else {
|
} else {
|
||||||
req.ContentLength = -1
|
req.ContentLength = -1
|
||||||
}
|
}
|
||||||
|
req.Body.(*requestBody).pipe = &pipe{
|
||||||
|
b: &dataBuffer{expected: req.ContentLength},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rw, req, nil
|
return rw, req, nil
|
||||||
}
|
}
|
||||||
|
@ -1880,24 +2028,6 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
||||||
return rw, req, nil
|
return rw, req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var reqBodyCache = make(chan []byte, 8)
|
|
||||||
|
|
||||||
func getRequestBodyBuf() []byte {
|
|
||||||
select {
|
|
||||||
case b := <-reqBodyCache:
|
|
||||||
return b
|
|
||||||
default:
|
|
||||||
return make([]byte, initialWindowSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func putRequestBodyBuf(b []byte) {
|
|
||||||
select {
|
|
||||||
case reqBodyCache <- b:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run on its own goroutine.
|
// Run on its own goroutine.
|
||||||
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
||||||
didPanic := true
|
didPanic := true
|
||||||
|
@ -1993,12 +2123,6 @@ func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
|
||||||
case <-sc.doneServing:
|
case <-sc.doneServing:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == io.EOF {
|
|
||||||
if buf := st.reqBuf; buf != nil {
|
|
||||||
st.reqBuf = nil // shouldn't matter; field unused by other
|
|
||||||
putRequestBodyBuf(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) noteBodyRead(st *stream, n int) {
|
func (sc *serverConn) noteBodyRead(st *stream, n int) {
|
||||||
|
@ -2504,7 +2628,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
||||||
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := startPushRequest{
|
msg := &startPushRequest{
|
||||||
parent: st,
|
parent: st,
|
||||||
method: opts.Method,
|
method: opts.Method,
|
||||||
url: u,
|
url: u,
|
||||||
|
@ -2517,7 +2641,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
|
||||||
return errClientDisconnected
|
return errClientDisconnected
|
||||||
case <-st.cw:
|
case <-st.cw:
|
||||||
return errStreamClosed
|
return errStreamClosed
|
||||||
case sc.wantStartPushCh <- msg:
|
case sc.serveMsgCh <- msg:
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -2539,7 +2663,7 @@ type startPushRequest struct {
|
||||||
done chan error
|
done chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) startPush(msg startPushRequest) {
|
func (sc *serverConn) startPush(msg *startPushRequest) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
// http://tools.ietf.org/html/rfc7540#section-6.6.
|
||||||
|
@ -2578,7 +2702,7 @@ func (sc *serverConn) startPush(msg startPushRequest) {
|
||||||
// A server that is unable to establish a new stream identifier can send a GOAWAY
|
// A server that is unable to establish a new stream identifier can send a GOAWAY
|
||||||
// frame so that the client is forced to open a new connection for new streams.
|
// frame so that the client is forced to open a new connection for new streams.
|
||||||
if sc.maxPushPromiseID+2 >= 1<<31 {
|
if sc.maxPushPromiseID+2 >= 1<<31 {
|
||||||
sc.startGracefulShutdown()
|
sc.startGracefulShutdownInternal()
|
||||||
return 0, ErrPushLimitReached
|
return 0, ErrPushLimitReached
|
||||||
}
|
}
|
||||||
sc.maxPushPromiseID += 2
|
sc.maxPushPromiseID += 2
|
||||||
|
@ -2703,31 +2827,6 @@ var badTrailer = map[string]bool{
|
||||||
"Www-Authenticate": true,
|
"Www-Authenticate": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// h1ServerShutdownChan returns a channel that will be closed when the
|
|
||||||
// provided *http.Server wants to shut down.
|
|
||||||
//
|
|
||||||
// This is a somewhat hacky way to get at http1 innards. It works
|
|
||||||
// when the http2 code is bundled into the net/http package in the
|
|
||||||
// standard library. The alternatives ended up making the cmd/go tool
|
|
||||||
// depend on http Servers. This is the lightest option for now.
|
|
||||||
// This is tested via the TestServeShutdown* tests in net/http.
|
|
||||||
func h1ServerShutdownChan(hs *http.Server) <-chan struct{} {
|
|
||||||
if fn := testh1ServerShutdownChan; fn != nil {
|
|
||||||
return fn(hs)
|
|
||||||
}
|
|
||||||
var x interface{} = hs
|
|
||||||
type I interface {
|
|
||||||
getDoneChan() <-chan struct{}
|
|
||||||
}
|
|
||||||
if hs, ok := x.(I); ok {
|
|
||||||
return hs.getDoneChan()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional test hook for h1ServerShutdownChan.
|
|
||||||
var testh1ServerShutdownChan func(hs *http.Server) <-chan struct{}
|
|
||||||
|
|
||||||
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
||||||
// disabled. See comments on h1ServerShutdownChan above for why
|
// disabled. See comments on h1ServerShutdownChan above for why
|
||||||
// the code is written this way.
|
// the code is written this way.
|
||||||
|
|
17
vendor/golang.org/x/net/http2/server_push_test.go
generated
vendored
17
vendor/golang.org/x/net/http2/server_push_test.go
generated
vendored
|
@ -430,18 +430,20 @@ func TestServer_Push_RejectForbiddenHeader(t *testing.T) {
|
||||||
func TestServer_Push_StateTransitions(t *testing.T) {
|
func TestServer_Push_StateTransitions(t *testing.T) {
|
||||||
const body = "foo"
|
const body = "foo"
|
||||||
|
|
||||||
startedPromise := make(chan bool)
|
gotPromise := make(chan bool)
|
||||||
finishedPush := make(chan bool)
|
finishedPush := make(chan bool)
|
||||||
|
|
||||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.URL.RequestURI() {
|
switch r.URL.RequestURI() {
|
||||||
case "/":
|
case "/":
|
||||||
if err := w.(http.Pusher).Push("/pushed", nil); err != nil {
|
if err := w.(http.Pusher).Push("/pushed", nil); err != nil {
|
||||||
t.Errorf("Push error: %v", err)
|
t.Errorf("Push error: %v", err)
|
||||||
}
|
}
|
||||||
close(startedPromise)
|
|
||||||
// Don't finish this request until the push finishes so we don't
|
// Don't finish this request until the push finishes so we don't
|
||||||
// nondeterministically interleave output frames with the push.
|
// nondeterministically interleave output frames with the push.
|
||||||
<-finishedPush
|
<-finishedPush
|
||||||
|
case "/pushed":
|
||||||
|
<-gotPromise
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/html")
|
w.Header().Set("Content-Type", "text/html")
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(body)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(body)))
|
||||||
|
@ -458,11 +460,16 @@ func TestServer_Push_StateTransitions(t *testing.T) {
|
||||||
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
||||||
}
|
}
|
||||||
getSlash(st)
|
getSlash(st)
|
||||||
<-startedPromise
|
// After the PUSH_PROMISE is sent, the stream should be stateHalfClosedRemote.
|
||||||
|
st.wantPushPromise()
|
||||||
if got, want := st.streamState(2), stateHalfClosedRemote; got != want {
|
if got, want := st.streamState(2), stateHalfClosedRemote; got != want {
|
||||||
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
t.Fatalf("streamState(2)=%v, want %v", got, want)
|
||||||
}
|
}
|
||||||
st.wantPushPromise()
|
// We stall the HTTP handler for "/pushed" until the above check. If we don't
|
||||||
|
// stall the handler, then the handler might write HEADERS and DATA and finish
|
||||||
|
// the stream before we check st.streamState(2) -- should that happen, we'll
|
||||||
|
// see stateClosed and fail the above check.
|
||||||
|
close(gotPromise)
|
||||||
st.wantHeaders()
|
st.wantHeaders()
|
||||||
if df := st.wantData(); !df.StreamEnded() {
|
if df := st.wantData(); !df.StreamEnded() {
|
||||||
t.Fatal("expected END_STREAM flag on DATA")
|
t.Fatal("expected END_STREAM flag on DATA")
|
||||||
|
@ -501,7 +508,7 @@ func TestServer_Push_RejectAfterGoAway(t *testing.T) {
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
st.sc.testHookCh <- func(loopNum int) {
|
st.sc.serveMsgCh <- func(loopNum int) {
|
||||||
if !st.sc.pushEnabled {
|
if !st.sc.pushEnabled {
|
||||||
readyOnce.Do(func() { close(ready) })
|
readyOnce.Do(func() { close(ready) })
|
||||||
}
|
}
|
||||||
|
|
207
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
207
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
|
@ -80,6 +80,7 @@ type serverTesterOpt string
|
||||||
|
|
||||||
var optOnlyServer = serverTesterOpt("only_server")
|
var optOnlyServer = serverTesterOpt("only_server")
|
||||||
var optQuiet = serverTesterOpt("quiet_logging")
|
var optQuiet = serverTesterOpt("quiet_logging")
|
||||||
|
var optFramerReuseFrames = serverTesterOpt("frame_reuse_frames")
|
||||||
|
|
||||||
func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester {
|
func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester {
|
||||||
resetHooks()
|
resetHooks()
|
||||||
|
@ -91,7 +92,7 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
|
||||||
NextProtos: []string{NextProtoTLS},
|
NextProtos: []string{NextProtoTLS},
|
||||||
}
|
}
|
||||||
|
|
||||||
var onlyServer, quiet bool
|
var onlyServer, quiet, framerReuseFrames bool
|
||||||
h2server := new(Server)
|
h2server := new(Server)
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch v := opt.(type) {
|
switch v := opt.(type) {
|
||||||
|
@ -107,6 +108,8 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
|
||||||
onlyServer = true
|
onlyServer = true
|
||||||
case optQuiet:
|
case optQuiet:
|
||||||
quiet = true
|
quiet = true
|
||||||
|
case optFramerReuseFrames:
|
||||||
|
framerReuseFrames = true
|
||||||
}
|
}
|
||||||
case func(net.Conn, http.ConnState):
|
case func(net.Conn, http.ConnState):
|
||||||
ts.Config.ConnState = v
|
ts.Config.ConnState = v
|
||||||
|
@ -139,7 +142,6 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
|
||||||
st.scMu.Lock()
|
st.scMu.Lock()
|
||||||
defer st.scMu.Unlock()
|
defer st.scMu.Unlock()
|
||||||
st.sc = v
|
st.sc = v
|
||||||
st.sc.testHookCh = make(chan func(int))
|
|
||||||
}
|
}
|
||||||
log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st}))
|
log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st}))
|
||||||
if !onlyServer {
|
if !onlyServer {
|
||||||
|
@ -149,6 +151,9 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
|
||||||
}
|
}
|
||||||
st.cc = cc
|
st.cc = cc
|
||||||
st.fr = NewFramer(cc, cc)
|
st.fr = NewFramer(cc, cc)
|
||||||
|
if framerReuseFrames {
|
||||||
|
st.fr.SetReuseFrames()
|
||||||
|
}
|
||||||
if !logFrameReads && !logFrameWrites {
|
if !logFrameReads && !logFrameWrites {
|
||||||
st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
|
st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
|
||||||
m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
|
m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
|
||||||
|
@ -181,7 +186,7 @@ func (st *serverTester) addLogFilter(phrase string) {
|
||||||
|
|
||||||
func (st *serverTester) stream(id uint32) *stream {
|
func (st *serverTester) stream(id uint32) *stream {
|
||||||
ch := make(chan *stream, 1)
|
ch := make(chan *stream, 1)
|
||||||
st.sc.testHookCh <- func(int) {
|
st.sc.serveMsgCh <- func(int) {
|
||||||
ch <- st.sc.streams[id]
|
ch <- st.sc.streams[id]
|
||||||
}
|
}
|
||||||
return <-ch
|
return <-ch
|
||||||
|
@ -189,7 +194,7 @@ func (st *serverTester) stream(id uint32) *stream {
|
||||||
|
|
||||||
func (st *serverTester) streamState(id uint32) streamState {
|
func (st *serverTester) streamState(id uint32) streamState {
|
||||||
ch := make(chan streamState, 1)
|
ch := make(chan streamState, 1)
|
||||||
st.sc.testHookCh <- func(int) {
|
st.sc.serveMsgCh <- func(int) {
|
||||||
state, _ := st.sc.state(id)
|
state, _ := st.sc.state(id)
|
||||||
ch <- state
|
ch <- state
|
||||||
}
|
}
|
||||||
|
@ -199,7 +204,7 @@ func (st *serverTester) streamState(id uint32) streamState {
|
||||||
// loopNum reports how many times this conn's select loop has gone around.
|
// loopNum reports how many times this conn's select loop has gone around.
|
||||||
func (st *serverTester) loopNum() int {
|
func (st *serverTester) loopNum() int {
|
||||||
lastc := make(chan int, 1)
|
lastc := make(chan int, 1)
|
||||||
st.sc.testHookCh <- func(loopNum int) {
|
st.sc.serveMsgCh <- func(loopNum int) {
|
||||||
lastc <- loopNum
|
lastc <- loopNum
|
||||||
}
|
}
|
||||||
return <-lastc
|
return <-lastc
|
||||||
|
@ -254,11 +259,52 @@ func (st *serverTester) Close() {
|
||||||
// greet initiates the client's HTTP/2 connection into a state where
|
// greet initiates the client's HTTP/2 connection into a state where
|
||||||
// frames may be sent.
|
// frames may be sent.
|
||||||
func (st *serverTester) greet() {
|
func (st *serverTester) greet() {
|
||||||
|
st.greetAndCheckSettings(func(Setting) error { return nil })
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error) {
|
||||||
st.writePreface()
|
st.writePreface()
|
||||||
st.writeInitialSettings()
|
st.writeInitialSettings()
|
||||||
st.wantSettings()
|
st.wantSettings().ForeachSetting(checkSetting)
|
||||||
st.writeSettingsAck()
|
st.writeSettingsAck()
|
||||||
st.wantSettingsAck()
|
|
||||||
|
// The initial WINDOW_UPDATE and SETTINGS ACK can come in any order.
|
||||||
|
var gotSettingsAck bool
|
||||||
|
var gotWindowUpdate bool
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
f, err := st.readFrame()
|
||||||
|
if err != nil {
|
||||||
|
st.t.Fatal(err)
|
||||||
|
}
|
||||||
|
switch f := f.(type) {
|
||||||
|
case *SettingsFrame:
|
||||||
|
if !f.Header().Flags.Has(FlagSettingsAck) {
|
||||||
|
st.t.Fatal("Settings Frame didn't have ACK set")
|
||||||
|
}
|
||||||
|
gotSettingsAck = true
|
||||||
|
|
||||||
|
case *WindowUpdateFrame:
|
||||||
|
if f.FrameHeader.StreamID != 0 {
|
||||||
|
st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID, 0)
|
||||||
|
}
|
||||||
|
incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
|
||||||
|
if f.Increment != incr {
|
||||||
|
st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr)
|
||||||
|
}
|
||||||
|
gotWindowUpdate = true
|
||||||
|
|
||||||
|
default:
|
||||||
|
st.t.Fatalf("Wanting a settings ACK or window update, received a %T", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !gotSettingsAck {
|
||||||
|
st.t.Fatalf("Didn't get a settings ACK")
|
||||||
|
}
|
||||||
|
if !gotWindowUpdate {
|
||||||
|
st.t.Fatalf("Didn't get a window update")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *serverTester) writePreface() {
|
func (st *serverTester) writePreface() {
|
||||||
|
@ -578,12 +624,7 @@ func TestServer(t *testing.T) {
|
||||||
server sends in the HTTP/2 connection.
|
server sends in the HTTP/2 connection.
|
||||||
`)
|
`)
|
||||||
|
|
||||||
st.writePreface()
|
st.greet()
|
||||||
st.writeInitialSettings()
|
|
||||||
st.wantSettings()
|
|
||||||
st.writeSettingsAck()
|
|
||||||
st.wantSettingsAck()
|
|
||||||
|
|
||||||
st.writeHeaders(HeadersFrameParam{
|
st.writeHeaders(HeadersFrameParam{
|
||||||
StreamID: 1, // clients send odd numbers
|
StreamID: 1, // clients send odd numbers
|
||||||
BlockFragment: st.encodeHeader(),
|
BlockFragment: st.encodeHeader(),
|
||||||
|
@ -1192,7 +1233,7 @@ func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) {
|
||||||
EndStream: false,
|
EndStream: false,
|
||||||
EndHeaders: true,
|
EndHeaders: true,
|
||||||
})
|
})
|
||||||
st.writeDataPadded(1, false, []byte("abcdef"), []byte("1234"))
|
st.writeDataPadded(1, false, []byte("abcdef"), []byte{0, 0, 0, 0})
|
||||||
|
|
||||||
// Expect to immediately get our 5 bytes of padding back for
|
// Expect to immediately get our 5 bytes of padding back for
|
||||||
// both the connection and stream (4 bytes of padding + 1 byte of length)
|
// both the connection and stream (4 bytes of padding + 1 byte of length)
|
||||||
|
@ -2310,7 +2351,7 @@ func TestServer_NoCrash_HandlerClose_Then_ClientClose(t *testing.T) {
|
||||||
|
|
||||||
// Sent when the a Handler closes while a client has
|
// Sent when the a Handler closes while a client has
|
||||||
// indicated it's still sending DATA:
|
// indicated it's still sending DATA:
|
||||||
st.wantRSTStream(1, ErrCodeCancel)
|
st.wantRSTStream(1, ErrCodeNo)
|
||||||
|
|
||||||
// Now the handler has ended, so it's ended its
|
// Now the handler has ended, so it's ended its
|
||||||
// stream, but the client hasn't closed its side
|
// stream, but the client hasn't closed its side
|
||||||
|
@ -2390,6 +2431,7 @@ func TestServer_Rejects_TLSBadCipher(t *testing.T) {
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
@ -2595,11 +2637,9 @@ func TestServerDoS_MaxHeaderListSize(t *testing.T) {
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
// shake hands
|
// shake hands
|
||||||
st.writePreface()
|
|
||||||
st.writeInitialSettings()
|
|
||||||
frameSize := defaultMaxReadFrameSize
|
frameSize := defaultMaxReadFrameSize
|
||||||
var advHeaderListSize *uint32
|
var advHeaderListSize *uint32
|
||||||
st.wantSettings().ForeachSetting(func(s Setting) error {
|
st.greetAndCheckSettings(func(s Setting) error {
|
||||||
switch s.ID {
|
switch s.ID {
|
||||||
case SettingMaxFrameSize:
|
case SettingMaxFrameSize:
|
||||||
if s.Val < minMaxFrameSize {
|
if s.Val < minMaxFrameSize {
|
||||||
|
@ -2614,8 +2654,6 @@ func TestServerDoS_MaxHeaderListSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
st.writeSettingsAck()
|
|
||||||
st.wantSettingsAck()
|
|
||||||
|
|
||||||
if advHeaderListSize == nil {
|
if advHeaderListSize == nil {
|
||||||
t.Errorf("server didn't advertise a max header list size")
|
t.Errorf("server didn't advertise a max header list size")
|
||||||
|
@ -2994,6 +3032,89 @@ func BenchmarkServerPosts(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send a stream of messages from server to client in separate data frames.
|
||||||
|
// Brings up performance issues seen in long streams.
|
||||||
|
// Created to show problem in go issue #18502
|
||||||
|
func BenchmarkServerToClientStreamDefaultOptions(b *testing.B) {
|
||||||
|
benchmarkServerToClientStream(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Justification for Change-Id: Iad93420ef6c3918f54249d867098f1dadfa324d8
|
||||||
|
// Expect to see memory/alloc reduction by opting in to Frame reuse with the Framer.
|
||||||
|
func BenchmarkServerToClientStreamReuseFrames(b *testing.B) {
|
||||||
|
benchmarkServerToClientStream(b, optFramerReuseFrames)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkServerToClientStream(b *testing.B, newServerOpts ...interface{}) {
|
||||||
|
defer disableGoroutineTracking()()
|
||||||
|
b.ReportAllocs()
|
||||||
|
const msgLen = 1
|
||||||
|
// default window size
|
||||||
|
const windowSize = 1<<16 - 1
|
||||||
|
|
||||||
|
// next message to send from the server and for the client to expect
|
||||||
|
nextMsg := func(i int) []byte {
|
||||||
|
msg := make([]byte, msgLen)
|
||||||
|
msg[0] = byte(i)
|
||||||
|
if len(msg) != msgLen {
|
||||||
|
panic("invalid test setup msg length")
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Consume the (empty) body from th peer before replying, otherwise
|
||||||
|
// the server will sometimes (depending on scheduling) send the peer a
|
||||||
|
// a RST_STREAM with the CANCEL error code.
|
||||||
|
if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil {
|
||||||
|
b.Errorf("Copy error; got %v, %v; want 0, nil", n, err)
|
||||||
|
}
|
||||||
|
for i := 0; i < b.N; i += 1 {
|
||||||
|
w.Write(nextMsg(i))
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
}, newServerOpts...)
|
||||||
|
defer st.Close()
|
||||||
|
st.greet()
|
||||||
|
|
||||||
|
const id = uint32(1)
|
||||||
|
|
||||||
|
st.writeHeaders(HeadersFrameParam{
|
||||||
|
StreamID: id,
|
||||||
|
BlockFragment: st.encodeHeader(":method", "POST"),
|
||||||
|
EndStream: false,
|
||||||
|
EndHeaders: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
st.writeData(id, true, nil)
|
||||||
|
st.wantHeaders()
|
||||||
|
|
||||||
|
var pendingWindowUpdate = uint32(0)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i += 1 {
|
||||||
|
expected := nextMsg(i)
|
||||||
|
df := st.wantData()
|
||||||
|
if bytes.Compare(expected, df.data) != 0 {
|
||||||
|
b.Fatalf("Bad message received; want %v; got %v", expected, df.data)
|
||||||
|
}
|
||||||
|
// try to send infrequent but large window updates so they don't overwhelm the test
|
||||||
|
pendingWindowUpdate += uint32(len(df.data))
|
||||||
|
if pendingWindowUpdate >= windowSize/2 {
|
||||||
|
if err := st.fr.WriteWindowUpdate(0, pendingWindowUpdate); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := st.fr.WriteWindowUpdate(id, pendingWindowUpdate); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
pendingWindowUpdate = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df := st.wantData()
|
||||||
|
if !df.StreamEnded() {
|
||||||
|
b.Fatalf("DATA didn't have END_STREAM; got %v", df)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// go-fuzz bug, originally reported at https://github.com/bradfitz/http2/issues/53
|
// go-fuzz bug, originally reported at https://github.com/bradfitz/http2/issues/53
|
||||||
// Verify we don't hang.
|
// Verify we don't hang.
|
||||||
func TestIssue53(t *testing.T) {
|
func TestIssue53(t *testing.T) {
|
||||||
|
@ -3295,6 +3416,7 @@ func TestServerHandleCustomConn(t *testing.T) {
|
||||||
fakeConnState := tls.ConnectionState{
|
fakeConnState := tls.ConnectionState{
|
||||||
ServerName: testString,
|
ServerName: testString,
|
||||||
Version: tls.VersionTLS12,
|
Version: tls.VersionTLS12,
|
||||||
|
CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
}
|
}
|
||||||
go s.ServeConn(connStateConn{c1, fakeConnState}, &ServeConnOpts{
|
go s.ServeConn(connStateConn{c1, fakeConnState}, &ServeConnOpts{
|
||||||
BaseConfig: &http.Server{
|
BaseConfig: &http.Server{
|
||||||
|
@ -3563,48 +3685,3 @@ func TestRequestBodyReadCloseRace(t *testing.T) {
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerGracefulShutdown(t *testing.T) {
|
|
||||||
shutdownCh := make(chan struct{})
|
|
||||||
defer func() { testh1ServerShutdownChan = nil }()
|
|
||||||
testh1ServerShutdownChan = func(*http.Server) <-chan struct{} { return shutdownCh }
|
|
||||||
|
|
||||||
var st *serverTester
|
|
||||||
handlerDone := make(chan struct{})
|
|
||||||
st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
defer close(handlerDone)
|
|
||||||
close(shutdownCh)
|
|
||||||
|
|
||||||
ga := st.wantGoAway()
|
|
||||||
if ga.ErrCode != ErrCodeNo {
|
|
||||||
t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
|
|
||||||
}
|
|
||||||
if ga.LastStreamID != 1 {
|
|
||||||
t.Errorf("GOAWAY LastStreamID = %v; want 1", ga.LastStreamID)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("x-foo", "bar")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
st.greet()
|
|
||||||
st.bodylessReq1()
|
|
||||||
|
|
||||||
<-handlerDone
|
|
||||||
hf := st.wantHeaders()
|
|
||||||
goth := st.decodeHeader(hf.HeaderBlockFragment())
|
|
||||||
wanth := [][2]string{
|
|
||||||
{":status", "200"},
|
|
||||||
{"x-foo", "bar"},
|
|
||||||
{"content-type", "text/plain; charset=utf-8"},
|
|
||||||
{"content-length", "0"},
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(goth, wanth) {
|
|
||||||
t.Errorf("Got headers %v; want %v", goth, wanth)
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := st.cc.Read([]byte{0})
|
|
||||||
if n != 0 || err == nil {
|
|
||||||
t.Errorf("Read = %v, %v; want 0, non-nil", n, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
12
vendor/golang.org/x/net/http2/transport.go
generated
vendored
12
vendor/golang.org/x/net/http2/transport.go
generated
vendored
|
@ -658,8 +658,6 @@ func commaSeparatedTrailers(req *http.Request) (string, error) {
|
||||||
}
|
}
|
||||||
if len(keys) > 0 {
|
if len(keys) > 0 {
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
// TODO: could do better allocation-wise here, but trailers are rare,
|
|
||||||
// so being lazy for now.
|
|
||||||
return strings.Join(keys, ","), nil
|
return strings.Join(keys, ","), nil
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
|
@ -1530,8 +1528,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer) // TODO(bradfitz): recycle this garbage
|
cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}}
|
||||||
cs.bufPipe = pipe{b: buf}
|
|
||||||
cs.bytesRemain = res.ContentLength
|
cs.bytesRemain = res.ContentLength
|
||||||
res.Body = transportResponseBody{cs}
|
res.Body = transportResponseBody{cs}
|
||||||
go cs.awaitRequestCancel(cs.req)
|
go cs.awaitRequestCancel(cs.req)
|
||||||
|
@ -1658,6 +1655,7 @@ func (b transportResponseBody) Close() error {
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
if !serverSentStreamEnd {
|
if !serverSentStreamEnd {
|
||||||
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
||||||
|
cs.didReset = true
|
||||||
}
|
}
|
||||||
// Return connection-level flow control.
|
// Return connection-level flow control.
|
||||||
if unread > 0 {
|
if unread > 0 {
|
||||||
|
@ -1705,12 +1703,6 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
if len(data) > 0 && cs.bufPipe.b == nil {
|
|
||||||
// Data frame after it's already closed?
|
|
||||||
cc.logf("http2: Transport received DATA frame for closed stream; closing connection")
|
|
||||||
return ConnectionError(ErrCodeProtocol)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check connection-level flow control.
|
// Check connection-level flow control.
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
if cs.inflow.available() >= int32(f.Length) {
|
if cs.inflow.available() >= int32(f.Length) {
|
||||||
|
|
57
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
57
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
|
@ -66,6 +66,7 @@ type fakeTLSConn struct {
|
||||||
func (c *fakeTLSConn) ConnectionState() tls.ConnectionState {
|
func (c *fakeTLSConn) ConnectionState() tls.ConnectionState {
|
||||||
return tls.ConnectionState{
|
return tls.ConnectionState{
|
||||||
Version: tls.VersionTLS12,
|
Version: tls.VersionTLS12,
|
||||||
|
CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2406,7 +2407,7 @@ func TestTransportReturnsDataPaddingFlowControl(t *testing.T) {
|
||||||
EndStream: false,
|
EndStream: false,
|
||||||
BlockFragment: buf.Bytes(),
|
BlockFragment: buf.Bytes(),
|
||||||
})
|
})
|
||||||
pad := []byte("12345")
|
pad := make([]byte, 5)
|
||||||
ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
|
ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
|
||||||
|
|
||||||
f, err := ct.readNonSettingsFrame()
|
f, err := ct.readNonSettingsFrame()
|
||||||
|
@ -2914,3 +2915,57 @@ func TestAuthorityAddr(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 20448: stop allocating for DATA frames' payload after
|
||||||
|
// Response.Body.Close is called.
|
||||||
|
func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
|
||||||
|
megabyteZero := make([]byte, 1<<20)
|
||||||
|
|
||||||
|
writeErr := make(chan error, 1)
|
||||||
|
|
||||||
|
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
var sum int64
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
n, err := w.Write(megabyteZero)
|
||||||
|
sum += int64(n)
|
||||||
|
if err != nil {
|
||||||
|
writeErr <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Logf("wrote all %d bytes", sum)
|
||||||
|
writeErr <- nil
|
||||||
|
}, optOnlyServer)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
tr := &Transport{TLSClientConfig: tlsConfigInsecure}
|
||||||
|
defer tr.CloseIdleConnections()
|
||||||
|
c := &http.Client{Transport: tr}
|
||||||
|
res, err := c.Get(st.ts.URL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var buf [1]byte
|
||||||
|
if _, err := res.Body.Read(buf[:]); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if err := res.Body.Close(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
trb, ok := res.Body.(transportResponseBody)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("res.Body = %T; want transportResponseBody", res.Body)
|
||||||
|
}
|
||||||
|
if trb.cs.bufPipe.b != nil {
|
||||||
|
t.Errorf("response body pipe is still open")
|
||||||
|
}
|
||||||
|
|
||||||
|
gotErr := <-writeErr
|
||||||
|
if gotErr == nil {
|
||||||
|
t.Errorf("Handler unexpectedly managed to write its entire response without getting an error")
|
||||||
|
} else if gotErr != errStreamClosed {
|
||||||
|
t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
2
vendor/golang.org/x/net/http2/writesched_priority.go
generated
vendored
|
@ -53,7 +53,7 @@ type PriorityWriteSchedulerConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
||||||
// frames by following HTTP/2 priorities as described in RFC 7340 Section 5.3.
|
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
|
||||||
// If cfg is nil, default options are used.
|
// If cfg is nil, default options are used.
|
||||||
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
|
|
2
vendor/golang.org/x/net/http2/writesched_priority_test.go
generated
vendored
2
vendor/golang.org/x/net/http2/writesched_priority_test.go
generated
vendored
|
@ -434,7 +434,7 @@ func TestPriorityFlowControl(t *testing.T) {
|
||||||
t.Fatalf("Pop(%d)=false, want true", i)
|
t.Fatalf("Pop(%d)=false, want true", i)
|
||||||
}
|
}
|
||||||
if got, want := wr.DataSize(), 8; got != want {
|
if got, want := wr.DataSize(), 8; got != want {
|
||||||
t.Fatalf("Pop(%d)=%d bytes, want %d bytes", got, want)
|
t.Fatalf("Pop(%d)=%d bytes, want %d bytes", i, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
vendor/golang.org/x/net/http2/writesched_random_test.go
generated
vendored
2
vendor/golang.org/x/net/http2/writesched_random_test.go
generated
vendored
|
@ -30,7 +30,7 @@ func TestRandomScheduler(t *testing.T) {
|
||||||
t.Fatalf("got %d frames, expected 6", len(order))
|
t.Fatalf("got %d frames, expected 6", len(order))
|
||||||
}
|
}
|
||||||
if order[0].StreamID() != 0 || order[1].StreamID() != 0 {
|
if order[0].StreamID() != 0 || order[1].StreamID() != 0 {
|
||||||
t.Fatalf("expected non-stream frames first", order[0], order[1])
|
t.Fatal("expected non-stream frames first", order[0], order[1])
|
||||||
}
|
}
|
||||||
got := make(map[uint32]bool)
|
got := make(map[uint32]bool)
|
||||||
for _, wr := range order[2:] {
|
for _, wr := range order[2:] {
|
||||||
|
|
65
vendor/golang.org/x/net/idna/example_test.go
generated
vendored
Normal file
65
vendor/golang.org/x/net/idna/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package idna_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/net/idna"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleProfile() {
|
||||||
|
// Raw Punycode has no restrictions and does no mappings.
|
||||||
|
fmt.Println(idna.ToASCII(""))
|
||||||
|
fmt.Println(idna.ToASCII("*.faß.com"))
|
||||||
|
fmt.Println(idna.Punycode.ToASCII("*.faß.com"))
|
||||||
|
|
||||||
|
// Rewrite IDN for lookup. This (currently) uses transitional mappings to
|
||||||
|
// find a balance between IDNA2003 and IDNA2008 compatibility.
|
||||||
|
fmt.Println(idna.Lookup.ToASCII(""))
|
||||||
|
fmt.Println(idna.Lookup.ToASCII("www.faß.com"))
|
||||||
|
|
||||||
|
// Convert an IDN to ASCII for registration purposes. This changes the
|
||||||
|
// encoding, but reports an error if the input was illformed.
|
||||||
|
fmt.Println(idna.Registration.ToASCII(""))
|
||||||
|
fmt.Println(idna.Registration.ToASCII("www.faß.com"))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// *.xn--fa-hia.com <nil>
|
||||||
|
// *.xn--fa-hia.com <nil>
|
||||||
|
// <nil>
|
||||||
|
// www.fass.com <nil>
|
||||||
|
// idna: invalid label ""
|
||||||
|
// www.xn--fa-hia.com <nil>
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleNew() {
|
||||||
|
var p *idna.Profile
|
||||||
|
|
||||||
|
// Raw Punycode has no restrictions and does no mappings.
|
||||||
|
p = idna.New()
|
||||||
|
fmt.Println(p.ToASCII("*.faß.com"))
|
||||||
|
|
||||||
|
// Do mappings. Note that star is not allowed in a DNS lookup.
|
||||||
|
p = idna.New(
|
||||||
|
idna.MapForLookup(),
|
||||||
|
idna.Transitional(true)) // Map ß -> ss
|
||||||
|
fmt.Println(p.ToASCII("*.faß.com"))
|
||||||
|
|
||||||
|
// Set up a profile maps for lookup, but allows wild cards.
|
||||||
|
p = idna.New(
|
||||||
|
idna.MapForLookup(),
|
||||||
|
idna.Transitional(true), // Map ß -> ss
|
||||||
|
idna.StrictDomainName(false)) // Set more permissive ASCII rules.
|
||||||
|
fmt.Println(p.ToASCII("*.faß.com"))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// *.xn--fa-hia.com <nil>
|
||||||
|
// *.fass.com idna: disallowed rune U+002E
|
||||||
|
// *.fass.com <nil>
|
||||||
|
}
|
670
vendor/golang.org/x/net/idna/idna.go
generated
vendored
670
vendor/golang.org/x/net/idna/idna.go
generated
vendored
|
@ -1,61 +1,661 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package idna implements IDNA2008 (Internationalized Domain Names for
|
// Package idna implements IDNA2008 using the compatibility processing
|
||||||
// Applications), defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and
|
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||||
// RFC 5894.
|
// deal with the transition from IDNA2003.
|
||||||
|
//
|
||||||
|
// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
|
||||||
|
// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
|
||||||
|
// UTS #46 is defined in http://www.unicode.org/reports/tr46.
|
||||||
|
// See http://unicode.org/cldr/utility/idna.jsp for a visualization of the
|
||||||
|
// differences between these two standards.
|
||||||
package idna // import "golang.org/x/net/idna"
|
package idna // import "golang.org/x/net/idna"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"golang.org/x/text/secure/bidirule"
|
||||||
|
"golang.org/x/text/unicode/norm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(nigeltao): specify when errors occur. For example, is ToASCII(".") or
|
// NOTE: Unlike common practice in Go APIs, the functions will return a
|
||||||
// ToASCII("foo\x00") an error? See also http://www.unicode.org/faq/idn.html#11
|
// sanitized domain name in case of errors. Browsers sometimes use a partially
|
||||||
|
// evaluated string as lookup.
|
||||||
|
// TODO: the current error handling is, in my opinion, the least opinionated.
|
||||||
|
// Other strategies are also viable, though:
|
||||||
|
// Option 1) Return an empty string in case of error, but allow the user to
|
||||||
|
// specify explicitly which errors to ignore.
|
||||||
|
// Option 2) Return the partially evaluated string if it is itself a valid
|
||||||
|
// string, otherwise return the empty string in case of error.
|
||||||
|
// Option 3) Option 1 and 2.
|
||||||
|
// Option 4) Always return an empty string for now and implement Option 1 as
|
||||||
|
// needed, and document that the return string may not be empty in case of
|
||||||
|
// error in the future.
|
||||||
|
// I think Option 1 is best, but it is quite opinionated.
|
||||||
|
|
||||||
// acePrefix is the ASCII Compatible Encoding prefix.
|
// ToASCII is a wrapper for Punycode.ToASCII.
|
||||||
const acePrefix = "xn--"
|
func ToASCII(s string) (string, error) {
|
||||||
|
return Punycode.process(s, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUnicode is a wrapper for Punycode.ToUnicode.
|
||||||
|
func ToUnicode(s string) (string, error) {
|
||||||
|
return Punycode.process(s, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Option configures a Profile at creation time.
|
||||||
|
type Option func(*options)
|
||||||
|
|
||||||
|
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||||
|
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||||
|
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||||
|
// compatibility. It is used by most browsers when resolving domain names. This
|
||||||
|
// option is only meaningful if combined with MapForLookup.
|
||||||
|
func Transitional(transitional bool) Option {
|
||||||
|
return func(o *options) { o.transitional = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||||
|
// are longer than allowed by the RFC.
|
||||||
|
func VerifyDNSLength(verify bool) Option {
|
||||||
|
return func(o *options) { o.verifyDNSLength = verify }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateLabels sets whether to check the mandatory label validation criteria
|
||||||
|
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
||||||
|
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
||||||
|
func ValidateLabels(enable bool) Option {
|
||||||
|
return func(o *options) {
|
||||||
|
// Don't override existing mappings, but set one that at least checks
|
||||||
|
// normalization if it is not set.
|
||||||
|
if o.mapping == nil && enable {
|
||||||
|
o.mapping = normalize
|
||||||
|
}
|
||||||
|
o.trie = trie
|
||||||
|
o.validateLabels = enable
|
||||||
|
o.fromPuny = validateFromPunycode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictDomainName limits the set of permissable ASCII characters to those
|
||||||
|
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||||
|
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
||||||
|
//
|
||||||
|
// This option is useful, for instance, for browsers that allow characters
|
||||||
|
// outside this range, for example a '_' (U+005F LOW LINE). See
|
||||||
|
// http://www.rfc-editor.org/std/std3.txt for more details This option
|
||||||
|
// corresponds to the UseSTD3ASCIIRules option in UTS #46.
|
||||||
|
func StrictDomainName(use bool) Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.trie = trie
|
||||||
|
o.useSTD3Rules = use
|
||||||
|
o.fromPuny = validateFromPunycode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: the following options pull in tables. The tables should not be linked
|
||||||
|
// in as long as the options are not used.
|
||||||
|
|
||||||
|
// BidiRule enables the Bidi rule as defined in RFC 5893. Any application
|
||||||
|
// that relies on proper validation of labels should include this rule.
|
||||||
|
func BidiRule() Option {
|
||||||
|
return func(o *options) { o.bidirule = bidirule.ValidString }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateForRegistration sets validation options to verify that a given IDN is
|
||||||
|
// properly formatted for registration as defined by Section 4 of RFC 5891.
|
||||||
|
func ValidateForRegistration() Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.mapping = validateRegistration
|
||||||
|
StrictDomainName(true)(o)
|
||||||
|
ValidateLabels(true)(o)
|
||||||
|
VerifyDNSLength(true)(o)
|
||||||
|
BidiRule()(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapForLookup sets validation and mapping options such that a given IDN is
|
||||||
|
// transformed for domain name lookup according to the requirements set out in
|
||||||
|
// Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894,
|
||||||
|
// RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option
|
||||||
|
// to add this check.
|
||||||
|
//
|
||||||
|
// The mappings include normalization and mapping case, width and other
|
||||||
|
// compatibility mappings.
|
||||||
|
func MapForLookup() Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.mapping = validateAndMap
|
||||||
|
StrictDomainName(true)(o)
|
||||||
|
ValidateLabels(true)(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
transitional bool
|
||||||
|
useSTD3Rules bool
|
||||||
|
validateLabels bool
|
||||||
|
verifyDNSLength bool
|
||||||
|
|
||||||
|
trie *idnaTrie
|
||||||
|
|
||||||
|
// fromPuny calls validation rules when converting A-labels to U-labels.
|
||||||
|
fromPuny func(p *Profile, s string) error
|
||||||
|
|
||||||
|
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||||
|
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||||
|
mapping func(p *Profile, s string) (string, error)
|
||||||
|
|
||||||
|
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||||
|
// defined in RFC 5893.
|
||||||
|
bidirule func(s string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Profile defines the configuration of a IDNA mapper.
|
||||||
|
type Profile struct {
|
||||||
|
options
|
||||||
|
}
|
||||||
|
|
||||||
|
func apply(o *options, opts []Option) {
|
||||||
|
for _, f := range opts {
|
||||||
|
f(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Profile.
|
||||||
|
//
|
||||||
|
// With no options, the returned Profile is the most permissive and equals the
|
||||||
|
// Punycode Profile. Options can be passed to further restrict the Profile. The
|
||||||
|
// MapForLookup and ValidateForRegistration options set a collection of options,
|
||||||
|
// for lookup and registration purposes respectively, which can be tailored by
|
||||||
|
// adding more fine-grained options, where later options override earlier
|
||||||
|
// options.
|
||||||
|
func New(o ...Option) *Profile {
|
||||||
|
p := &Profile{}
|
||||||
|
apply(&p.options, o)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
||||||
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
||||||
// ToASCII("golang") is "golang".
|
// ToASCII("golang") is "golang". If an error is encountered it will return
|
||||||
func ToASCII(s string) (string, error) {
|
// an error and a (partially) processed result.
|
||||||
if ascii(s) {
|
func (p *Profile) ToASCII(s string) (string, error) {
|
||||||
return s, nil
|
return p.process(s, true)
|
||||||
}
|
|
||||||
labels := strings.Split(s, ".")
|
|
||||||
for i, label := range labels {
|
|
||||||
if !ascii(label) {
|
|
||||||
a, err := encode(acePrefix, label)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
labels[i] = a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(labels, "."), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
||||||
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
||||||
// ToUnicode("golang") is "golang".
|
// ToUnicode("golang") is "golang". If an error is encountered it will return
|
||||||
func ToUnicode(s string) (string, error) {
|
// an error and a (partially) processed result.
|
||||||
if !strings.Contains(s, acePrefix) {
|
func (p *Profile) ToUnicode(s string) (string, error) {
|
||||||
return s, nil
|
pp := *p
|
||||||
|
pp.transitional = false
|
||||||
|
return pp.process(s, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String reports a string with a description of the profile for debugging
|
||||||
|
// purposes. The string format may change with different versions.
|
||||||
|
func (p *Profile) String() string {
|
||||||
|
s := ""
|
||||||
|
if p.transitional {
|
||||||
|
s = "Transitional"
|
||||||
|
} else {
|
||||||
|
s = "NonTransitional"
|
||||||
|
}
|
||||||
|
if p.useSTD3Rules {
|
||||||
|
s += ":UseSTD3Rules"
|
||||||
|
}
|
||||||
|
if p.validateLabels {
|
||||||
|
s += ":ValidateLabels"
|
||||||
|
}
|
||||||
|
if p.verifyDNSLength {
|
||||||
|
s += ":VerifyDNSLength"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Punycode is a Profile that does raw punycode processing with a minimum
|
||||||
|
// of validation.
|
||||||
|
Punycode *Profile = punycode
|
||||||
|
|
||||||
|
// Lookup is the recommended profile for looking up domain names, according
|
||||||
|
// to Section 5 of RFC 5891. The exact configuration of this profile may
|
||||||
|
// change over time.
|
||||||
|
Lookup *Profile = lookup
|
||||||
|
|
||||||
|
// Display is the recommended profile for displaying domain names.
|
||||||
|
// The configuration of this profile may change over time.
|
||||||
|
Display *Profile = display
|
||||||
|
|
||||||
|
// Registration is the recommended profile for checking whether a given
|
||||||
|
// IDN is valid for registration, according to Section 4 of RFC 5891.
|
||||||
|
Registration *Profile = registration
|
||||||
|
|
||||||
|
punycode = &Profile{}
|
||||||
|
lookup = &Profile{options{
|
||||||
|
transitional: true,
|
||||||
|
useSTD3Rules: true,
|
||||||
|
validateLabels: true,
|
||||||
|
trie: trie,
|
||||||
|
fromPuny: validateFromPunycode,
|
||||||
|
mapping: validateAndMap,
|
||||||
|
bidirule: bidirule.ValidString,
|
||||||
|
}}
|
||||||
|
display = &Profile{options{
|
||||||
|
useSTD3Rules: true,
|
||||||
|
validateLabels: true,
|
||||||
|
trie: trie,
|
||||||
|
fromPuny: validateFromPunycode,
|
||||||
|
mapping: validateAndMap,
|
||||||
|
bidirule: bidirule.ValidString,
|
||||||
|
}}
|
||||||
|
registration = &Profile{options{
|
||||||
|
useSTD3Rules: true,
|
||||||
|
validateLabels: true,
|
||||||
|
verifyDNSLength: true,
|
||||||
|
trie: trie,
|
||||||
|
fromPuny: validateFromPunycode,
|
||||||
|
mapping: validateRegistration,
|
||||||
|
bidirule: bidirule.ValidString,
|
||||||
|
}}
|
||||||
|
|
||||||
|
// TODO: profiles
|
||||||
|
// Register: recommended for approving domain names: don't do any mappings
|
||||||
|
// but rather reject on invalid input. Bundle or block deviation characters.
|
||||||
|
)
|
||||||
|
|
||||||
|
type labelError struct{ label, code_ string }
|
||||||
|
|
||||||
|
func (e labelError) code() string { return e.code_ }
|
||||||
|
func (e labelError) Error() string {
|
||||||
|
return fmt.Sprintf("idna: invalid label %q", e.label)
|
||||||
|
}
|
||||||
|
|
||||||
|
type runeError rune
|
||||||
|
|
||||||
|
func (e runeError) code() string { return "P1" }
|
||||||
|
func (e runeError) Error() string {
|
||||||
|
return fmt.Sprintf("idna: disallowed rune %U", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// process implements the algorithm described in section 4 of UTS #46,
|
||||||
|
// see http://www.unicode.org/reports/tr46.
|
||||||
|
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||||
|
var err error
|
||||||
|
if p.mapping != nil {
|
||||||
|
s, err = p.mapping(p, s)
|
||||||
|
}
|
||||||
|
// Remove leading empty labels.
|
||||||
|
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||||
|
}
|
||||||
|
// It seems like we should only create this error on ToASCII, but the
|
||||||
|
// UTS 46 conformance tests suggests we should always check this.
|
||||||
|
if err == nil && p.verifyDNSLength && s == "" {
|
||||||
|
err = &labelError{s, "A4"}
|
||||||
|
}
|
||||||
|
labels := labelIter{orig: s}
|
||||||
|
for ; !labels.done(); labels.next() {
|
||||||
|
label := labels.label()
|
||||||
|
if label == "" {
|
||||||
|
// Empty labels are not okay. The label iterator skips the last
|
||||||
|
// label if it is empty.
|
||||||
|
if err == nil && p.verifyDNSLength {
|
||||||
|
err = &labelError{s, "A4"}
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
labels := strings.Split(s, ".")
|
|
||||||
for i, label := range labels {
|
|
||||||
if strings.HasPrefix(label, acePrefix) {
|
if strings.HasPrefix(label, acePrefix) {
|
||||||
u, err := decode(label[len(acePrefix):])
|
u, err2 := decode(label[len(acePrefix):])
|
||||||
if err != nil {
|
if err2 != nil {
|
||||||
return "", err
|
if err == nil {
|
||||||
|
err = err2
|
||||||
}
|
}
|
||||||
labels[i] = u
|
// Spec says keep the old label.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
labels.set(u)
|
||||||
|
if err == nil && p.validateLabels {
|
||||||
|
err = p.fromPuny(p, u)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// This should be called on NonTransitional, according to the
|
||||||
|
// spec, but that currently does not have any effect. Use the
|
||||||
|
// original profile to preserve options.
|
||||||
|
err = p.validateLabel(u)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
err = p.validateLabel(label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(labels, "."), nil
|
if toASCII {
|
||||||
|
for labels.reset(); !labels.done(); labels.next() {
|
||||||
|
label := labels.label()
|
||||||
|
if !ascii(label) {
|
||||||
|
a, err2 := encode(acePrefix, label)
|
||||||
|
if err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
|
label = a
|
||||||
|
labels.set(a)
|
||||||
|
}
|
||||||
|
n := len(label)
|
||||||
|
if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
|
||||||
|
err = &labelError{label, "A4"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = labels.result()
|
||||||
|
if toASCII && p.verifyDNSLength && err == nil {
|
||||||
|
// Compute the length of the domain name minus the root label and its dot.
|
||||||
|
n := len(s)
|
||||||
|
if n > 0 && s[n-1] == '.' {
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
if len(s) < 1 || n > 253 {
|
||||||
|
err = &labelError{s, "A4"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalize(p *Profile, s string) (string, error) {
|
||||||
|
return norm.NFC.String(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRegistration(p *Profile, s string) (string, error) {
|
||||||
|
if !norm.NFC.IsNormalString(s) {
|
||||||
|
return s, &labelError{s, "V1"}
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
for i := 0; i < len(s); {
|
||||||
|
v, sz := trie.lookupString(s[i:])
|
||||||
|
i += sz
|
||||||
|
// Copy bytes not copied so far.
|
||||||
|
switch p.simplify(info(v).category()) {
|
||||||
|
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||||
|
// for strict conformance to IDNA2008.
|
||||||
|
case valid, deviation:
|
||||||
|
case disallowed, mapped, unknown, ignored:
|
||||||
|
if err == nil {
|
||||||
|
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||||
|
err = runeError(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateAndMap(p *Profile, s string) (string, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
b []byte
|
||||||
|
k int
|
||||||
|
)
|
||||||
|
for i := 0; i < len(s); {
|
||||||
|
v, sz := trie.lookupString(s[i:])
|
||||||
|
start := i
|
||||||
|
i += sz
|
||||||
|
// Copy bytes not copied so far.
|
||||||
|
switch p.simplify(info(v).category()) {
|
||||||
|
case valid:
|
||||||
|
continue
|
||||||
|
case disallowed:
|
||||||
|
if err == nil {
|
||||||
|
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||||
|
err = runeError(r)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case mapped, deviation:
|
||||||
|
b = append(b, s[k:start]...)
|
||||||
|
b = info(v).appendMapping(b, s[start:i])
|
||||||
|
case ignored:
|
||||||
|
b = append(b, s[k:start]...)
|
||||||
|
// drop the rune
|
||||||
|
case unknown:
|
||||||
|
b = append(b, s[k:start]...)
|
||||||
|
b = append(b, "\ufffd"...)
|
||||||
|
}
|
||||||
|
k = i
|
||||||
|
}
|
||||||
|
if k == 0 {
|
||||||
|
// No changes so far.
|
||||||
|
s = norm.NFC.String(s)
|
||||||
|
} else {
|
||||||
|
b = append(b, s[k:]...)
|
||||||
|
if norm.NFC.QuickSpan(b) != len(b) {
|
||||||
|
b = norm.NFC.Bytes(b)
|
||||||
|
}
|
||||||
|
// TODO: the punycode converters require strings as input.
|
||||||
|
s = string(b)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// A labelIter allows iterating over domain name labels.
|
||||||
|
type labelIter struct {
|
||||||
|
orig string
|
||||||
|
slice []string
|
||||||
|
curStart int
|
||||||
|
curEnd int
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelIter) reset() {
|
||||||
|
l.curStart = 0
|
||||||
|
l.curEnd = 0
|
||||||
|
l.i = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelIter) done() bool {
|
||||||
|
return l.curStart >= len(l.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelIter) result() string {
|
||||||
|
if l.slice != nil {
|
||||||
|
return strings.Join(l.slice, ".")
|
||||||
|
}
|
||||||
|
return l.orig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelIter) label() string {
|
||||||
|
if l.slice != nil {
|
||||||
|
return l.slice[l.i]
|
||||||
|
}
|
||||||
|
p := strings.IndexByte(l.orig[l.curStart:], '.')
|
||||||
|
l.curEnd = l.curStart + p
|
||||||
|
if p == -1 {
|
||||||
|
l.curEnd = len(l.orig)
|
||||||
|
}
|
||||||
|
return l.orig[l.curStart:l.curEnd]
|
||||||
|
}
|
||||||
|
|
||||||
|
// next sets the value to the next label. It skips the last label if it is empty.
|
||||||
|
func (l *labelIter) next() {
|
||||||
|
l.i++
|
||||||
|
if l.slice != nil {
|
||||||
|
if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" {
|
||||||
|
l.curStart = len(l.orig)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l.curStart = l.curEnd + 1
|
||||||
|
if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' {
|
||||||
|
l.curStart = len(l.orig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *labelIter) set(s string) {
|
||||||
|
if l.slice == nil {
|
||||||
|
l.slice = strings.Split(l.orig, ".")
|
||||||
|
}
|
||||||
|
l.slice[l.i] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// acePrefix is the ASCII Compatible Encoding prefix.
|
||||||
|
const acePrefix = "xn--"
|
||||||
|
|
||||||
|
func (p *Profile) simplify(cat category) category {
|
||||||
|
switch cat {
|
||||||
|
case disallowedSTD3Mapped:
|
||||||
|
if p.useSTD3Rules {
|
||||||
|
cat = disallowed
|
||||||
|
} else {
|
||||||
|
cat = mapped
|
||||||
|
}
|
||||||
|
case disallowedSTD3Valid:
|
||||||
|
if p.useSTD3Rules {
|
||||||
|
cat = disallowed
|
||||||
|
} else {
|
||||||
|
cat = valid
|
||||||
|
}
|
||||||
|
case deviation:
|
||||||
|
if !p.transitional {
|
||||||
|
cat = valid
|
||||||
|
}
|
||||||
|
case validNV8, validXV8:
|
||||||
|
// TODO: handle V2008
|
||||||
|
cat = valid
|
||||||
|
}
|
||||||
|
return cat
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateFromPunycode(p *Profile, s string) error {
|
||||||
|
if !norm.NFC.IsNormalString(s) {
|
||||||
|
return &labelError{s, "V1"}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(s); {
|
||||||
|
v, sz := trie.lookupString(s[i:])
|
||||||
|
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||||
|
return &labelError{s, "V6"}
|
||||||
|
}
|
||||||
|
i += sz
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
zwnj = "\u200c"
|
||||||
|
zwj = "\u200d"
|
||||||
|
)
|
||||||
|
|
||||||
|
type joinState int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
stateStart joinState = iota
|
||||||
|
stateVirama
|
||||||
|
stateBefore
|
||||||
|
stateBeforeVirama
|
||||||
|
stateAfter
|
||||||
|
stateFAIL
|
||||||
|
)
|
||||||
|
|
||||||
|
var joinStates = [][numJoinTypes]joinState{
|
||||||
|
stateStart: {
|
||||||
|
joiningL: stateBefore,
|
||||||
|
joiningD: stateBefore,
|
||||||
|
joinZWNJ: stateFAIL,
|
||||||
|
joinZWJ: stateFAIL,
|
||||||
|
joinVirama: stateVirama,
|
||||||
|
},
|
||||||
|
stateVirama: {
|
||||||
|
joiningL: stateBefore,
|
||||||
|
joiningD: stateBefore,
|
||||||
|
},
|
||||||
|
stateBefore: {
|
||||||
|
joiningL: stateBefore,
|
||||||
|
joiningD: stateBefore,
|
||||||
|
joiningT: stateBefore,
|
||||||
|
joinZWNJ: stateAfter,
|
||||||
|
joinZWJ: stateFAIL,
|
||||||
|
joinVirama: stateBeforeVirama,
|
||||||
|
},
|
||||||
|
stateBeforeVirama: {
|
||||||
|
joiningL: stateBefore,
|
||||||
|
joiningD: stateBefore,
|
||||||
|
joiningT: stateBefore,
|
||||||
|
},
|
||||||
|
stateAfter: {
|
||||||
|
joiningL: stateFAIL,
|
||||||
|
joiningD: stateBefore,
|
||||||
|
joiningT: stateAfter,
|
||||||
|
joiningR: stateStart,
|
||||||
|
joinZWNJ: stateFAIL,
|
||||||
|
joinZWJ: stateFAIL,
|
||||||
|
joinVirama: stateAfter, // no-op as we can't accept joiners here
|
||||||
|
},
|
||||||
|
stateFAIL: {
|
||||||
|
0: stateFAIL,
|
||||||
|
joiningL: stateFAIL,
|
||||||
|
joiningD: stateFAIL,
|
||||||
|
joiningT: stateFAIL,
|
||||||
|
joiningR: stateFAIL,
|
||||||
|
joinZWNJ: stateFAIL,
|
||||||
|
joinZWJ: stateFAIL,
|
||||||
|
joinVirama: stateFAIL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||||
|
// already implicitly satisfied by the overall implementation.
|
||||||
|
func (p *Profile) validateLabel(s string) error {
|
||||||
|
if s == "" {
|
||||||
|
if p.verifyDNSLength {
|
||||||
|
return &labelError{s, "A4"}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p.bidirule != nil && !p.bidirule(s) {
|
||||||
|
return &labelError{s, "B"}
|
||||||
|
}
|
||||||
|
if !p.validateLabels {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
trie := p.trie // p.validateLabels is only set if trie is set.
|
||||||
|
if len(s) > 4 && s[2] == '-' && s[3] == '-' {
|
||||||
|
return &labelError{s, "V2"}
|
||||||
|
}
|
||||||
|
if s[0] == '-' || s[len(s)-1] == '-' {
|
||||||
|
return &labelError{s, "V3"}
|
||||||
|
}
|
||||||
|
// TODO: merge the use of this in the trie.
|
||||||
|
v, sz := trie.lookupString(s)
|
||||||
|
x := info(v)
|
||||||
|
if x.isModifier() {
|
||||||
|
return &labelError{s, "V5"}
|
||||||
|
}
|
||||||
|
// Quickly return in the absence of zero-width (non) joiners.
|
||||||
|
if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
st := stateStart
|
||||||
|
for i := 0; ; {
|
||||||
|
jt := x.joinType()
|
||||||
|
if s[i:i+sz] == zwj {
|
||||||
|
jt = joinZWJ
|
||||||
|
} else if s[i:i+sz] == zwnj {
|
||||||
|
jt = joinZWNJ
|
||||||
|
}
|
||||||
|
st = joinStates[st][jt]
|
||||||
|
if x.isViramaModifier() {
|
||||||
|
st = joinStates[st][joinVirama]
|
||||||
|
}
|
||||||
|
if i += sz; i == len(s) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v, sz = trie.lookupString(s[i:])
|
||||||
|
x = info(v)
|
||||||
|
}
|
||||||
|
if st == stateFAIL || st == stateAfter {
|
||||||
|
return &labelError{s, "C"}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ascii(s string) bool {
|
func ascii(s string) bool {
|
||||||
|
|
23
vendor/golang.org/x/net/idna/punycode.go
generated
vendored
23
vendor/golang.org/x/net/idna/punycode.go
generated
vendored
|
@ -1,4 +1,6 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,7 +9,6 @@ package idna
|
||||||
// This file implements the Punycode algorithm from RFC 3492.
|
// This file implements the Punycode algorithm from RFC 3492.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -27,6 +28,8 @@ const (
|
||||||
tmin int32 = 1
|
tmin int32 = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func punyError(s string) error { return &labelError{s, "A3"} }
|
||||||
|
|
||||||
// decode decodes a string as specified in section 6.2.
|
// decode decodes a string as specified in section 6.2.
|
||||||
func decode(encoded string) (string, error) {
|
func decode(encoded string) (string, error) {
|
||||||
if encoded == "" {
|
if encoded == "" {
|
||||||
|
@ -34,7 +37,7 @@ func decode(encoded string) (string, error) {
|
||||||
}
|
}
|
||||||
pos := 1 + strings.LastIndex(encoded, "-")
|
pos := 1 + strings.LastIndex(encoded, "-")
|
||||||
if pos == 1 {
|
if pos == 1 {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
if pos == len(encoded) {
|
if pos == len(encoded) {
|
||||||
return encoded[:len(encoded)-1], nil
|
return encoded[:len(encoded)-1], nil
|
||||||
|
@ -50,16 +53,16 @@ func decode(encoded string) (string, error) {
|
||||||
oldI, w := i, int32(1)
|
oldI, w := i, int32(1)
|
||||||
for k := base; ; k += base {
|
for k := base; ; k += base {
|
||||||
if pos == len(encoded) {
|
if pos == len(encoded) {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
digit, ok := decodeDigit(encoded[pos])
|
digit, ok := decodeDigit(encoded[pos])
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
pos++
|
pos++
|
||||||
i += digit * w
|
i += digit * w
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
t := k - bias
|
t := k - bias
|
||||||
if t < tmin {
|
if t < tmin {
|
||||||
|
@ -72,7 +75,7 @@ func decode(encoded string) (string, error) {
|
||||||
}
|
}
|
||||||
w *= base - t
|
w *= base - t
|
||||||
if w >= math.MaxInt32/base {
|
if w >= math.MaxInt32/base {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x := int32(len(output) + 1)
|
x := int32(len(output) + 1)
|
||||||
|
@ -80,7 +83,7 @@ func decode(encoded string) (string, error) {
|
||||||
n += i / x
|
n += i / x
|
||||||
i %= x
|
i %= x
|
||||||
if n > utf8.MaxRune || len(output) >= 1024 {
|
if n > utf8.MaxRune || len(output) >= 1024 {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
return "", punyError(encoded)
|
||||||
}
|
}
|
||||||
output = append(output, 0)
|
output = append(output, 0)
|
||||||
copy(output[i+1:], output[i:])
|
copy(output[i+1:], output[i:])
|
||||||
|
@ -121,14 +124,14 @@ func encode(prefix, s string) (string, error) {
|
||||||
}
|
}
|
||||||
delta += (m - n) * (h + 1)
|
delta += (m - n) * (h + 1)
|
||||||
if delta < 0 {
|
if delta < 0 {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", s)
|
return "", punyError(s)
|
||||||
}
|
}
|
||||||
n = m
|
n = m
|
||||||
for _, r := range s {
|
for _, r := range s {
|
||||||
if r < n {
|
if r < n {
|
||||||
delta++
|
delta++
|
||||||
if delta < 0 {
|
if delta < 0 {
|
||||||
return "", fmt.Errorf("idna: invalid label %q", s)
|
return "", punyError(s)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
4477
vendor/golang.org/x/net/idna/tables.go
generated
vendored
Normal file
4477
vendor/golang.org/x/net/idna/tables.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
72
vendor/golang.org/x/net/idna/trie.go
generated
vendored
Normal file
72
vendor/golang.org/x/net/idna/trie.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
|
// 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 idna
|
||||||
|
|
||||||
|
// appendMapping appends the mapping for the respective rune. isMapped must be
|
||||||
|
// true. A mapping is a categorization of a rune as defined in UTS #46.
|
||||||
|
func (c info) appendMapping(b []byte, s string) []byte {
|
||||||
|
index := int(c >> indexShift)
|
||||||
|
if c&xorBit == 0 {
|
||||||
|
s := mappings[index:]
|
||||||
|
return append(b, s[1:s[0]+1]...)
|
||||||
|
}
|
||||||
|
b = append(b, s...)
|
||||||
|
if c&inlineXOR == inlineXOR {
|
||||||
|
// TODO: support and handle two-byte inline masks
|
||||||
|
b[len(b)-1] ^= byte(index)
|
||||||
|
} else {
|
||||||
|
for p := len(b) - int(xorData[index]); p < len(b); p++ {
|
||||||
|
index++
|
||||||
|
b[p] ^= xorData[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sparse block handling code.
|
||||||
|
|
||||||
|
type valueRange struct {
|
||||||
|
value uint16 // header: value:stride
|
||||||
|
lo, hi byte // header: lo:n
|
||||||
|
}
|
||||||
|
|
||||||
|
type sparseBlocks struct {
|
||||||
|
values []valueRange
|
||||||
|
offset []uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
var idnaSparse = sparseBlocks{
|
||||||
|
values: idnaSparseValues[:],
|
||||||
|
offset: idnaSparseOffset[:],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't use newIdnaTrie to avoid unconditional linking in of the table.
|
||||||
|
var trie = &idnaTrie{}
|
||||||
|
|
||||||
|
// lookup determines the type of block n and looks up the value for b.
|
||||||
|
// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
|
||||||
|
// is a list of ranges with an accompanying value. Given a matching range r,
|
||||||
|
// the value for b is by r.value + (b - r.lo) * stride.
|
||||||
|
func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
|
||||||
|
offset := t.offset[n]
|
||||||
|
header := t.values[offset]
|
||||||
|
lo := offset + 1
|
||||||
|
hi := lo + uint16(header.lo)
|
||||||
|
for lo < hi {
|
||||||
|
m := lo + (hi-lo)/2
|
||||||
|
r := t.values[m]
|
||||||
|
if r.lo <= b && b <= r.hi {
|
||||||
|
return r.value + uint16(b-r.lo)*header.value
|
||||||
|
}
|
||||||
|
if b < r.lo {
|
||||||
|
hi = m
|
||||||
|
} else {
|
||||||
|
lo = m + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
114
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
Normal file
114
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
|
package idna
|
||||||
|
|
||||||
|
// This file contains definitions for interpreting the trie value of the idna
|
||||||
|
// trie generated by "go run gen*.go". It is shared by both the generator
|
||||||
|
// program and the resultant package. Sharing is achieved by the generator
|
||||||
|
// copying gen_trieval.go to trieval.go and changing what's above this comment.
|
||||||
|
|
||||||
|
// info holds information from the IDNA mapping table for a single rune. It is
|
||||||
|
// the value returned by a trie lookup. In most cases, all information fits in
|
||||||
|
// a 16-bit value. For mappings, this value may contain an index into a slice
|
||||||
|
// with the mapped string. Such mappings can consist of the actual mapped value
|
||||||
|
// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
|
||||||
|
// input rune. This technique is used by the cases packages and reduces the
|
||||||
|
// table size significantly.
|
||||||
|
//
|
||||||
|
// The per-rune values have the following format:
|
||||||
|
//
|
||||||
|
// if mapped {
|
||||||
|
// if inlinedXOR {
|
||||||
|
// 15..13 inline XOR marker
|
||||||
|
// 12..11 unused
|
||||||
|
// 10..3 inline XOR mask
|
||||||
|
// } else {
|
||||||
|
// 15..3 index into xor or mapping table
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// 15..13 unused
|
||||||
|
// 12 modifier (including virama)
|
||||||
|
// 11 virama modifier
|
||||||
|
// 10..8 joining type
|
||||||
|
// 7..3 category type
|
||||||
|
// }
|
||||||
|
// 2 use xor pattern
|
||||||
|
// 1..0 mapped category
|
||||||
|
//
|
||||||
|
// See the definitions below for a more detailed description of the various
|
||||||
|
// bits.
|
||||||
|
type info uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
catSmallMask = 0x3
|
||||||
|
catBigMask = 0xF8
|
||||||
|
indexShift = 3
|
||||||
|
xorBit = 0x4 // interpret the index as an xor pattern
|
||||||
|
inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
|
||||||
|
|
||||||
|
joinShift = 8
|
||||||
|
joinMask = 0x07
|
||||||
|
|
||||||
|
viramaModifier = 0x0800
|
||||||
|
modifier = 0x1000
|
||||||
|
)
|
||||||
|
|
||||||
|
// A category corresponds to a category defined in the IDNA mapping table.
|
||||||
|
type category uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
unknown category = 0 // not defined currently in unicode.
|
||||||
|
mapped category = 1
|
||||||
|
disallowedSTD3Mapped category = 2
|
||||||
|
deviation category = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
valid category = 0x08
|
||||||
|
validNV8 category = 0x18
|
||||||
|
validXV8 category = 0x28
|
||||||
|
disallowed category = 0x40
|
||||||
|
disallowedSTD3Valid category = 0x80
|
||||||
|
ignored category = 0xC0
|
||||||
|
)
|
||||||
|
|
||||||
|
// join types and additional rune information
|
||||||
|
const (
|
||||||
|
joiningL = (iota + 1)
|
||||||
|
joiningD
|
||||||
|
joiningT
|
||||||
|
joiningR
|
||||||
|
|
||||||
|
//the following types are derived during processing
|
||||||
|
joinZWJ
|
||||||
|
joinZWNJ
|
||||||
|
joinVirama
|
||||||
|
numJoinTypes
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c info) isMapped() bool {
|
||||||
|
return c&0x3 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c info) category() category {
|
||||||
|
small := c & catSmallMask
|
||||||
|
if small != 0 {
|
||||||
|
return category(small)
|
||||||
|
}
|
||||||
|
return category(c & catBigMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c info) joinType() info {
|
||||||
|
if c.isMapped() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (c >> joinShift) & joinMask
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c info) isModifier() bool {
|
||||||
|
return c&(modifier|catSmallMask) == modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c info) isViramaModifier() bool {
|
||||||
|
return c&(viramaModifier|catSmallMask) == viramaModifier
|
||||||
|
}
|
6
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
6
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
|
@ -4,7 +4,7 @@
|
||||||
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
||||||
package iana // import "golang.org/x/net/internal/iana"
|
package iana // import "golang.org/x/net/internal/iana"
|
||||||
|
|
||||||
// Differentiated Services Field Codepoints (DSCP), Updated: 2013-06-25
|
// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12
|
||||||
const (
|
const (
|
||||||
DiffServCS0 = 0x0 // CS0
|
DiffServCS0 = 0x0 // CS0
|
||||||
DiffServCS1 = 0x20 // CS1
|
DiffServCS1 = 0x20 // CS1
|
||||||
|
@ -26,7 +26,7 @@ const (
|
||||||
DiffServAF41 = 0x88 // AF41
|
DiffServAF41 = 0x88 // AF41
|
||||||
DiffServAF42 = 0x90 // AF42
|
DiffServAF42 = 0x90 // AF42
|
||||||
DiffServAF43 = 0x98 // AF43
|
DiffServAF43 = 0x98 // AF43
|
||||||
DiffServEFPHB = 0xb8 // EF PHB
|
DiffServEF = 0xb8 // EF
|
||||||
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ const (
|
||||||
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Protocol Numbers, Updated: 2015-10-06
|
// Protocol Numbers, Updated: 2016-06-22
|
||||||
const (
|
const (
|
||||||
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
||||||
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||||
|
|
37
vendor/golang.org/x/net/internal/netreflect/socket.go
generated
vendored
37
vendor/golang.org/x/net/internal/netreflect/socket.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package netreflect implements run-time reflection for the
|
|
||||||
// facilities of net package.
|
|
||||||
package netreflect
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errInvalidType = errors.New("invalid type")
|
|
||||||
errOpNoSupport = errors.New("operation not supported")
|
|
||||||
)
|
|
||||||
|
|
||||||
// SocketOf returns the socket descriptor of c.
|
|
||||||
func SocketOf(c net.Conn) (uintptr, error) {
|
|
||||||
switch c.(type) {
|
|
||||||
case *net.TCPConn, *net.UDPConn, *net.IPConn, *net.UnixConn:
|
|
||||||
return socketOf(c)
|
|
||||||
default:
|
|
||||||
return 0, errInvalidType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PacketSocketOf returns the socket descriptor of c.
|
|
||||||
func PacketSocketOf(c net.PacketConn) (uintptr, error) {
|
|
||||||
switch c.(type) {
|
|
||||||
case *net.UDPConn, *net.IPConn, *net.UnixConn:
|
|
||||||
return socketOf(c.(net.Conn))
|
|
||||||
default:
|
|
||||||
return 0, errInvalidType
|
|
||||||
}
|
|
||||||
}
|
|
30
vendor/golang.org/x/net/internal/netreflect/socket_posix.go
generated
vendored
30
vendor/golang.org/x/net/internal/netreflect/socket_posix.go
generated
vendored
|
@ -1,30 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
|
||||||
|
|
||||||
package netreflect
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func socketOf(c net.Conn) (uintptr, error) {
|
|
||||||
v := reflect.ValueOf(c)
|
|
||||||
switch e := v.Elem(); e.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
fd := e.FieldByName("conn").FieldByName("fd")
|
|
||||||
switch e := fd.Elem(); e.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
sysfd := e.FieldByName("sysfd")
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
return uintptr(sysfd.Uint()), nil
|
|
||||||
}
|
|
||||||
return uintptr(sysfd.Int()), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, errInvalidType
|
|
||||||
}
|
|
11
vendor/golang.org/x/net/internal/netreflect/socket_stub.go
generated
vendored
11
vendor/golang.org/x/net/internal/netreflect/socket_stub.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
|
|
||||||
|
|
||||||
package netreflect
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
func socketOf(c net.Conn) (uintptr, error) { return 0, errOpNoSupport }
|
|
123
vendor/golang.org/x/net/internal/netreflect/socket_test.go
generated
vendored
123
vendor/golang.org/x/net/internal/netreflect/socket_test.go
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package netreflect_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/internal/netreflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
func localPath() string {
|
|
||||||
f, err := ioutil.TempFile("", "netreflect")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
path := f.Name()
|
|
||||||
f.Close()
|
|
||||||
os.Remove(path)
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLocalListener(network string) (net.Listener, error) {
|
|
||||||
switch network {
|
|
||||||
case "tcp":
|
|
||||||
if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
|
|
||||||
return ln, nil
|
|
||||||
}
|
|
||||||
return net.Listen("tcp6", "[::1]:0")
|
|
||||||
case "tcp4":
|
|
||||||
return net.Listen("tcp4", "127.0.0.1:0")
|
|
||||||
case "tcp6":
|
|
||||||
return net.Listen("tcp6", "[::1]:0")
|
|
||||||
case "unix", "unixpacket":
|
|
||||||
return net.Listen(network, localPath())
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("%s is not supported", network)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLocalPacketListener(network string) (net.PacketConn, error) {
|
|
||||||
switch network {
|
|
||||||
case "udp":
|
|
||||||
if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil {
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
return net.ListenPacket("udp6", "[::1]:0")
|
|
||||||
case "udp4":
|
|
||||||
return net.ListenPacket("udp4", "127.0.0.1:0")
|
|
||||||
case "udp6":
|
|
||||||
return net.ListenPacket("udp6", "[::1]:0")
|
|
||||||
case "unixgram":
|
|
||||||
return net.ListenPacket(network, localPath())
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("%s is not supported", network)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSocketOf(t *testing.T) {
|
|
||||||
for _, network := range []string{"tcp", "unix", "unixpacket"} {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin":
|
|
||||||
if network == "unixpacket" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "nacl", "plan9":
|
|
||||||
continue
|
|
||||||
case "windows":
|
|
||||||
if network == "unix" || network == "unixpacket" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ln, err := newLocalListener(network)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
path := ln.Addr().String()
|
|
||||||
ln.Close()
|
|
||||||
if network == "unix" || network == "unixpacket" {
|
|
||||||
os.Remove(path)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
if _, err := netreflect.SocketOf(c); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPacketSocketOf(t *testing.T) {
|
|
||||||
for _, network := range []string{"udp", "unixgram"} {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "nacl", "plan9":
|
|
||||||
continue
|
|
||||||
case "windows":
|
|
||||||
if network == "unixgram" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c, err := newLocalPacketListener(network)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
if _, err := netreflect.PacketSocketOf(c); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
137
vendor/golang.org/x/net/internal/nettest/stack.go
generated
vendored
137
vendor/golang.org/x/net/internal/nettest/stack.go
generated
vendored
|
@ -2,35 +2,40 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package nettest provides utilities for IP testing.
|
// Package nettest provides utilities for network testing.
|
||||||
package nettest // import "golang.org/x/net/internal/nettest"
|
package nettest // import "golang.org/x/net/internal/nettest"
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
supportsIPv4 bool
|
||||||
|
supportsIPv6 bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
|
||||||
|
ln.Close()
|
||||||
|
supportsIPv4 = true
|
||||||
|
}
|
||||||
|
if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
|
||||||
|
ln.Close()
|
||||||
|
supportsIPv6 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SupportsIPv4 reports whether the platform supports IPv4 networking
|
// SupportsIPv4 reports whether the platform supports IPv4 networking
|
||||||
// functionality.
|
// functionality.
|
||||||
func SupportsIPv4() bool {
|
func SupportsIPv4() bool { return supportsIPv4 }
|
||||||
ln, err := net.Listen("tcp4", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ln.Close()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportsIPv6 reports whether the platform supports IPv6 networking
|
// SupportsIPv6 reports whether the platform supports IPv6 networking
|
||||||
// functionality.
|
// functionality.
|
||||||
func SupportsIPv6() bool {
|
func SupportsIPv6() bool { return supportsIPv6 }
|
||||||
if causesIPv6Crash() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ln, err := net.Listen("tcp6", "[::1]:0")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ln.Close()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportsRawIPSocket reports whether the platform supports raw IP
|
// SupportsRawIPSocket reports whether the platform supports raw IP
|
||||||
// sockets.
|
// sockets.
|
||||||
|
@ -50,3 +55,93 @@ func SupportsIPv6MulticastDeliveryOnLoopback() bool {
|
||||||
func ProtocolNotSupported(err error) bool {
|
func ProtocolNotSupported(err error) bool {
|
||||||
return protocolNotSupported(err)
|
return protocolNotSupported(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestableNetwork reports whether network is testable on the current
|
||||||
|
// platform configuration.
|
||||||
|
func TestableNetwork(network string) bool {
|
||||||
|
// This is based on logic from standard library's
|
||||||
|
// net/platform_test.go.
|
||||||
|
switch network {
|
||||||
|
case "unix", "unixgram":
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "android", "nacl", "plan9", "windows":
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case "unixpacket":
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalListener returns a listener which listens to a loopback IP
|
||||||
|
// address or local file system path.
|
||||||
|
// Network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
|
||||||
|
func NewLocalListener(network string) (net.Listener, error) {
|
||||||
|
switch network {
|
||||||
|
case "tcp":
|
||||||
|
if supportsIPv4 {
|
||||||
|
if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
|
||||||
|
return ln, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if supportsIPv6 {
|
||||||
|
return net.Listen("tcp6", "[::1]:0")
|
||||||
|
}
|
||||||
|
case "tcp4":
|
||||||
|
if supportsIPv4 {
|
||||||
|
return net.Listen("tcp4", "127.0.0.1:0")
|
||||||
|
}
|
||||||
|
case "tcp6":
|
||||||
|
if supportsIPv6 {
|
||||||
|
return net.Listen("tcp6", "[::1]:0")
|
||||||
|
}
|
||||||
|
case "unix", "unixpacket":
|
||||||
|
return net.Listen(network, localPath())
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%s is not supported", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalPacketListener returns a packet listener which listens to a
|
||||||
|
// loopback IP address or local file system path.
|
||||||
|
// Network must be "udp", "udp4", "udp6" or "unixgram".
|
||||||
|
func NewLocalPacketListener(network string) (net.PacketConn, error) {
|
||||||
|
switch network {
|
||||||
|
case "udp":
|
||||||
|
if supportsIPv4 {
|
||||||
|
if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if supportsIPv6 {
|
||||||
|
return net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
}
|
||||||
|
case "udp4":
|
||||||
|
if supportsIPv4 {
|
||||||
|
return net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
}
|
||||||
|
case "udp6":
|
||||||
|
if supportsIPv6 {
|
||||||
|
return net.ListenPacket("udp6", "[::1]:0")
|
||||||
|
}
|
||||||
|
case "unixgram":
|
||||||
|
return net.ListenPacket(network, localPath())
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%s is not supported", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localPath() string {
|
||||||
|
f, err := ioutil.TempFile("", "nettest")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
path := f.Name()
|
||||||
|
f.Close()
|
||||||
|
os.Remove(path)
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return int(h.Len) }
|
||||||
|
func (h *cmsghdr) lvl() int { return int(h.Level) }
|
||||||
|
func (h *cmsghdr) typ() int { return int(h.Type) }
|
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// 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 arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// 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 arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint64(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// 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 amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct{}
|
||||||
|
|
||||||
|
const sizeofCmsghdr = 0
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return 0 }
|
||||||
|
func (h *cmsghdr) lvl() int { return 0 }
|
||||||
|
func (h *cmsghdr) typ() int { return 0 }
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {}
|
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/in6.h>
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <sys/socket.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errEAGAIN error = syscall.EAGAIN
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
errENOENT error = syscall.ENOENT
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.EAGAIN:
|
||||||
|
return errEAGAIN
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
case syscall.ENOENT:
|
||||||
|
return errENOENT
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// 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 socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.ERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
15
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
15
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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 arm mips mipsle 386
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint32(len(b))
|
||||||
|
}
|
15
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
15
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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 arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(len(b))
|
||||||
|
}
|
15
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
15
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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 amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
v.Base = (*int8)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(len(b))
|
||||||
|
}
|
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type iovec struct{}
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {}
|
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !linux,!netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdr struct{}
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
return nil
|
||||||
|
}
|
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// 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 linux netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
for i := range hs {
|
||||||
|
vs := make([]iovec, len(ms[i].Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if parseFn != nil {
|
||||||
|
sa = make([]byte, sizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
if marshalFn != nil {
|
||||||
|
sa = marshalFn(ms[i].Addr)
|
||||||
|
}
|
||||||
|
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
for i := range hs {
|
||||||
|
ms[i].N = int(hs[i].Len)
|
||||||
|
ms[i].NN = hs[i].Hdr.controllen()
|
||||||
|
ms[i].Flags = hs[i].Hdr.flags()
|
||||||
|
if parseFn != nil {
|
||||||
|
var err error
|
||||||
|
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.setIov(vs)
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||||
|
h.Controllen = uint32(len(oob))
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) name() []byte {
|
||||||
|
if h.Name != nil && h.Namelen > 0 {
|
||||||
|
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Controllen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(h.Flags)
|
||||||
|
}
|
12
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
Normal file
12
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = int32(len(vs))
|
||||||
|
}
|
36
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
Normal file
36
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.setIov(vs)
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.setControl(oob)
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) name() []byte {
|
||||||
|
if h.Name != nil && h.Namelen > 0 {
|
||||||
|
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Controllen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(h.Flags)
|
||||||
|
}
|
20
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
Normal file
20
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint32(len(vs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) setControl(b []byte) {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
h.Controllen = uint32(len(b))
|
||||||
|
}
|
20
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
Normal file
20
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint64(len(vs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) setControl(b []byte) {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
h.Controllen = uint64(len(b))
|
||||||
|
}
|
10
vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
generated
vendored
Normal file
10
vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint32(len(vs))
|
||||||
|
}
|
34
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
Normal file
34
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// 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 amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = int32(len(vs))
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
|
||||||
|
h.Accrightslen = int32(len(oob))
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Accrightslen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(NativeEndian.Uint32(h.Pad_cgo_2[:]))
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type msghdr struct{}
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {}
|
||||||
|
func (h *msghdr) name() []byte { return nil }
|
||||||
|
func (h *msghdr) controllen() int { return 0 }
|
||||||
|
func (h *msghdr) flags() int { return 0 }
|
66
vendor/golang.org/x/net/internal/socket/rawconn.go
generated
vendored
Normal file
66
vendor/golang.org/x/net/internal/socket/rawconn.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Conn represents a raw connection.
|
||||||
|
type Conn struct {
|
||||||
|
network string
|
||||||
|
c syscall.RawConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn returns a new raw connection.
|
||||||
|
func NewConn(c net.Conn) (*Conn, error) {
|
||||||
|
var err error
|
||||||
|
var cc Conn
|
||||||
|
switch c := c.(type) {
|
||||||
|
case *net.TCPConn:
|
||||||
|
cc.network = "tcp"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
case *net.UDPConn:
|
||||||
|
cc.network = "udp"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
case *net.IPConn:
|
||||||
|
cc.network = "ip"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown connection type")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) get(c *Conn, b []byte) (int, error) {
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) {
|
||||||
|
n, operr = getsockopt(s, o.Level, o.Name, b)
|
||||||
|
}
|
||||||
|
if err := c.c.Control(fn); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return n, os.NewSyscallError("getsockopt", operr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) set(c *Conn, b []byte) error {
|
||||||
|
var operr error
|
||||||
|
fn := func(s uintptr) {
|
||||||
|
operr = setsockopt(s, o.Level, o.Name, b)
|
||||||
|
}
|
||||||
|
if err := c.c.Control(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", operr)
|
||||||
|
}
|
74
vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
Normal file
74
vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
hs := make(mmsghdrs, len(ms))
|
||||||
|
var parseFn func([]byte, string) (net.Addr, error)
|
||||||
|
if c.network != "tcp" {
|
||||||
|
parseFn = parseInetAddr
|
||||||
|
}
|
||||||
|
if err := hs.pack(ms, parseFn, nil); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = recvmmsg(s, hs, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Read(fn); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return n, os.NewSyscallError("recvmmsg", operr)
|
||||||
|
}
|
||||||
|
if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
hs := make(mmsghdrs, len(ms))
|
||||||
|
var marshalFn func(net.Addr) []byte
|
||||||
|
if c.network != "tcp" {
|
||||||
|
marshalFn = marshalInetAddr
|
||||||
|
}
|
||||||
|
if err := hs.pack(ms, nil, marshalFn); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = sendmmsg(s, hs, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Write(fn); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return n, os.NewSyscallError("sendmmsg", operr)
|
||||||
|
}
|
||||||
|
if err := hs[:n].unpack(ms[:n], nil, ""); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
77
vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Conn) recvMsg(m *Message, flags int) error {
|
||||||
|
var h msghdr
|
||||||
|
vs := make([]iovec, len(m.Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if c.network != "tcp" {
|
||||||
|
sa = make([]byte, sizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
h.pack(vs, m.Buffers, m.OOB, sa)
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = recvmsg(s, &h, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Read(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return os.NewSyscallError("recvmsg", operr)
|
||||||
|
}
|
||||||
|
if c.network != "tcp" {
|
||||||
|
var err error
|
||||||
|
m.Addr, err = parseInetAddr(sa[:], c.network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.N = n
|
||||||
|
m.NN = h.controllen()
|
||||||
|
m.Flags = h.flags()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsg(m *Message, flags int) error {
|
||||||
|
var h msghdr
|
||||||
|
vs := make([]iovec, len(m.Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if m.Addr != nil {
|
||||||
|
sa = marshalInetAddr(m.Addr)
|
||||||
|
}
|
||||||
|
h.pack(vs, m.Buffers, m.OOB, sa)
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = sendmsg(s, &h, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Write(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return os.NewSyscallError("sendmsg", operr)
|
||||||
|
}
|
||||||
|
m.N = n
|
||||||
|
m.NN = len(m.OOB)
|
||||||
|
return nil
|
||||||
|
}
|
18
vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
Normal file
18
vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
18
vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
generated
vendored
Normal file
18
vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (c *Conn) recvMsg(m *Message, flags int) error {
|
||||||
|
return errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsg(m *Message, flags int) error {
|
||||||
|
return errors.New("not implemented")
|
||||||
|
}
|
25
vendor/golang.org/x/net/internal/socket/rawconn_stub.go
generated
vendored
Normal file
25
vendor/golang.org/x/net/internal/socket/rawconn_stub.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (c *Conn) recvMsg(m *Message, flags int) error {
|
||||||
|
return errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsg(m *Message, flags int) error {
|
||||||
|
return errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
62
vendor/golang.org/x/net/internal/socket/reflect.go
generated
vendored
Normal file
62
vendor/golang.org/x/net/internal/socket/reflect.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Conn represents a raw connection.
|
||||||
|
type Conn struct {
|
||||||
|
c net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn returns a new raw connection.
|
||||||
|
func NewConn(c net.Conn) (*Conn, error) {
|
||||||
|
return &Conn{c: c}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) get(c *Conn, b []byte) (int, error) {
|
||||||
|
s, err := socketOf(c.c)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
n, err := getsockopt(s, o.Level, o.Name, b)
|
||||||
|
return n, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) set(c *Conn, b []byte) error {
|
||||||
|
s, err := socketOf(c.c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func socketOf(c net.Conn) (uintptr, error) {
|
||||||
|
switch c.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||||
|
v := reflect.ValueOf(c)
|
||||||
|
switch e := v.Elem(); e.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := e.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch e := fd.Elem(); e.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
sysfd := e.FieldByName("sysfd")
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return uintptr(sysfd.Uint()), nil
|
||||||
|
}
|
||||||
|
return uintptr(sysfd.Int()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errors.New("invalid type")
|
||||||
|
}
|
282
vendor/golang.org/x/net/internal/socket/socket.go
generated
vendored
Normal file
282
vendor/golang.org/x/net/internal/socket/socket.go
generated
vendored
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// 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 socket provides a portable interface for socket system
|
||||||
|
// calls.
|
||||||
|
package socket // import "golang.org/x/net/internal/socket"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Option represents a sticky socket option.
|
||||||
|
type Option struct {
|
||||||
|
Level int // level
|
||||||
|
Name int // name; must be equal or greater than 1
|
||||||
|
Len int // length of value in bytes; must be equal or greater than 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get reads a value for the option from the kernel.
|
||||||
|
// It returns the number of bytes written into b.
|
||||||
|
func (o *Option) Get(c *Conn, b []byte) (int, error) {
|
||||||
|
if o.Name < 1 || o.Len < 1 {
|
||||||
|
return 0, errors.New("invalid option")
|
||||||
|
}
|
||||||
|
if len(b) < o.Len {
|
||||||
|
return 0, errors.New("short buffer")
|
||||||
|
}
|
||||||
|
return o.get(c, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInt returns an integer value for the option.
|
||||||
|
//
|
||||||
|
// The Len field of Option must be either 1 or 4.
|
||||||
|
func (o *Option) GetInt(c *Conn) (int, error) {
|
||||||
|
if o.Len != 1 && o.Len != 4 {
|
||||||
|
return 0, errors.New("invalid option")
|
||||||
|
}
|
||||||
|
var b []byte
|
||||||
|
var bb [4]byte
|
||||||
|
if o.Len == 1 {
|
||||||
|
b = bb[:1]
|
||||||
|
} else {
|
||||||
|
b = bb[:4]
|
||||||
|
}
|
||||||
|
n, err := o.get(c, b)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if n != o.Len {
|
||||||
|
return 0, errors.New("invalid option length")
|
||||||
|
}
|
||||||
|
if o.Len == 1 {
|
||||||
|
return int(b[0]), nil
|
||||||
|
}
|
||||||
|
return int(NativeEndian.Uint32(b[:4])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set writes the option and value to the kernel.
|
||||||
|
func (o *Option) Set(c *Conn, b []byte) error {
|
||||||
|
if o.Name < 1 || o.Len < 1 {
|
||||||
|
return errors.New("invalid option")
|
||||||
|
}
|
||||||
|
if len(b) < o.Len {
|
||||||
|
return errors.New("short buffer")
|
||||||
|
}
|
||||||
|
return o.set(c, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInt writes the option and value to the kernel.
|
||||||
|
//
|
||||||
|
// The Len field of Option must be either 1 or 4.
|
||||||
|
func (o *Option) SetInt(c *Conn, v int) error {
|
||||||
|
if o.Len != 1 && o.Len != 4 {
|
||||||
|
return errors.New("invalid option")
|
||||||
|
}
|
||||||
|
var b []byte
|
||||||
|
if o.Len == 1 {
|
||||||
|
b = []byte{byte(v)}
|
||||||
|
} else {
|
||||||
|
var bb [4]byte
|
||||||
|
NativeEndian.PutUint32(bb[:o.Len], uint32(v))
|
||||||
|
b = bb[:4]
|
||||||
|
}
|
||||||
|
return o.set(c, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func controlHeaderLen() int {
|
||||||
|
return roundup(sizeofCmsghdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func controlMessageLen(dataLen int) int {
|
||||||
|
return roundup(sizeofCmsghdr) + dataLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControlMessageSpace returns the whole length of control message.
|
||||||
|
func ControlMessageSpace(dataLen int) int {
|
||||||
|
return roundup(sizeofCmsghdr) + roundup(dataLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ControlMessage represents the head message in a stream of control
|
||||||
|
// messages.
|
||||||
|
//
|
||||||
|
// A control message comprises of a header, data and a few padding
|
||||||
|
// fields to conform to the interface to the kernel.
|
||||||
|
//
|
||||||
|
// See RFC 3542 for further information.
|
||||||
|
type ControlMessage []byte
|
||||||
|
|
||||||
|
// Data returns the data field of the control message at the head on
|
||||||
|
// w.
|
||||||
|
func (m ControlMessage) Data(dataLen int) []byte {
|
||||||
|
l := controlHeaderLen()
|
||||||
|
if len(m) < l || len(m) < l+dataLen {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m[l : l+dataLen]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the control message at the next on w.
|
||||||
|
//
|
||||||
|
// Next works only for standard control messages.
|
||||||
|
func (m ControlMessage) Next(dataLen int) ControlMessage {
|
||||||
|
l := ControlMessageSpace(dataLen)
|
||||||
|
if len(m) < l {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m[l:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalHeader marshals the header fields of the control message at
|
||||||
|
// the head on w.
|
||||||
|
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
|
||||||
|
if len(m) < controlHeaderLen() {
|
||||||
|
return errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
h.set(controlMessageLen(dataLen), lvl, typ)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseHeader parses and returns the header fields of the control
|
||||||
|
// message at the head on w.
|
||||||
|
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
|
||||||
|
l := controlHeaderLen()
|
||||||
|
if len(m) < l {
|
||||||
|
return 0, 0, 0, errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals the control message at the head on w, and returns
|
||||||
|
// the next control message.
|
||||||
|
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
|
||||||
|
l := len(data)
|
||||||
|
if len(m) < ControlMessageSpace(l) {
|
||||||
|
return nil, errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
h.set(controlMessageLen(l), lvl, typ)
|
||||||
|
if l > 0 {
|
||||||
|
copy(m.Data(l), data)
|
||||||
|
}
|
||||||
|
return m.Next(l), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses w as a single or multiple control messages.
|
||||||
|
//
|
||||||
|
// Parse works for both standard and compatible messages.
|
||||||
|
func (m ControlMessage) Parse() ([]ControlMessage, error) {
|
||||||
|
var ms []ControlMessage
|
||||||
|
for len(m) >= controlHeaderLen() {
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
l := h.len()
|
||||||
|
if uint64(l) < uint64(controlHeaderLen()) {
|
||||||
|
return nil, errors.New("invalid message length")
|
||||||
|
}
|
||||||
|
if uint64(l) > uint64(len(m)) {
|
||||||
|
return nil, errors.New("short buffer")
|
||||||
|
}
|
||||||
|
// On message reception:
|
||||||
|
//
|
||||||
|
// |<- ControlMessageSpace --------------->|
|
||||||
|
// |<- controlMessageLen ---------->| |
|
||||||
|
// |<- controlHeaderLen ->| | |
|
||||||
|
// +---------------+------+---------+------+
|
||||||
|
// | Header | PadH | Data | PadD |
|
||||||
|
// +---------------+------+---------+------+
|
||||||
|
//
|
||||||
|
// On compatible message reception:
|
||||||
|
//
|
||||||
|
// | ... |<- controlMessageLen ----------->|
|
||||||
|
// | ... |<- controlHeaderLen ->| |
|
||||||
|
// +-----+---------------+------+----------+
|
||||||
|
// | ... | Header | PadH | Data |
|
||||||
|
// +-----+---------------+------+----------+
|
||||||
|
ms = append(ms, ControlMessage(m[:l]))
|
||||||
|
ll := l - controlHeaderLen()
|
||||||
|
if len(m) >= ControlMessageSpace(ll) {
|
||||||
|
m = m[ControlMessageSpace(ll):]
|
||||||
|
} else {
|
||||||
|
m = m[controlMessageLen(ll):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewControlMessage returns a new stream of control messages.
|
||||||
|
func NewControlMessage(dataLen []int) ControlMessage {
|
||||||
|
var l int
|
||||||
|
for i := range dataLen {
|
||||||
|
l += ControlMessageSpace(dataLen[i])
|
||||||
|
}
|
||||||
|
return make([]byte, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Message represents an IO message.
|
||||||
|
type Message struct {
|
||||||
|
// When writing, the Buffers field must contain at least one
|
||||||
|
// byte to write.
|
||||||
|
// When reading, the Buffers field will always contain a byte
|
||||||
|
// to read.
|
||||||
|
Buffers [][]byte
|
||||||
|
|
||||||
|
// OOB contains protocol-specific control or miscellaneous
|
||||||
|
// ancillary data known as out-of-band data.
|
||||||
|
OOB []byte
|
||||||
|
|
||||||
|
// Addr specifies a destination address when writing.
|
||||||
|
// It can be nil when the underlying protocol of the raw
|
||||||
|
// connection uses connection-oriented communication.
|
||||||
|
// After a successful read, it may contain the source address
|
||||||
|
// on the received packet.
|
||||||
|
Addr net.Addr
|
||||||
|
|
||||||
|
N int // # of bytes read or written from/to Buffers
|
||||||
|
NN int // # of bytes read or written from/to OOB
|
||||||
|
Flags int // protocol-specific information on the received message
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecvMsg wraps recvmsg system call.
|
||||||
|
//
|
||||||
|
// The provided flags is a set of platform-dependent flags, such as
|
||||||
|
// syscall.MSG_PEEK.
|
||||||
|
func (c *Conn) RecvMsg(m *Message, flags int) error {
|
||||||
|
return c.recvMsg(m, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMsg wraps sendmsg system call.
|
||||||
|
//
|
||||||
|
// The provided flags is a set of platform-dependent flags, such as
|
||||||
|
// syscall.MSG_DONTROUTE.
|
||||||
|
func (c *Conn) SendMsg(m *Message, flags int) error {
|
||||||
|
return c.sendMsg(m, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecvMsgs wraps recvmmsg system call.
|
||||||
|
//
|
||||||
|
// It returns the number of processed messages.
|
||||||
|
//
|
||||||
|
// The provided flags is a set of platform-dependent flags, such as
|
||||||
|
// syscall.MSG_PEEK.
|
||||||
|
//
|
||||||
|
// Only Linux supports this.
|
||||||
|
func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return c.recvMsgs(ms, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMsgs wraps sendmmsg system call.
|
||||||
|
//
|
||||||
|
// It returns the number of processed messages.
|
||||||
|
//
|
||||||
|
// The provided flags is a set of platform-dependent flags, such as
|
||||||
|
// syscall.MSG_DONTROUTE.
|
||||||
|
//
|
||||||
|
// Only Linux supports this.
|
||||||
|
func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return c.sendMsgs(ms, flags)
|
||||||
|
}
|
256
vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
generated
vendored
Normal file
256
vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
generated
vendored
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/internal/socket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockControl struct {
|
||||||
|
Level int
|
||||||
|
Type int
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestControlMessage(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
cs []mockControl
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 1, Type: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
var w []byte
|
||||||
|
var tailPadLen int
|
||||||
|
mm := socket.NewControlMessage([]int{0})
|
||||||
|
for i, c := range tt.cs {
|
||||||
|
m := socket.NewControlMessage([]int{len(c.Data)})
|
||||||
|
l := len(m) - len(mm)
|
||||||
|
if i == len(tt.cs)-1 && l > len(c.Data) {
|
||||||
|
tailPadLen = l - len(c.Data)
|
||||||
|
}
|
||||||
|
w = append(w, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
ww := make([]byte, len(w))
|
||||||
|
copy(ww, w)
|
||||||
|
m := socket.ControlMessage(ww)
|
||||||
|
for _, c := range tt.cs {
|
||||||
|
if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
|
||||||
|
t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
copy(m.Data(len(c.Data)), c.Data)
|
||||||
|
m = m.Next(len(c.Data))
|
||||||
|
}
|
||||||
|
m = socket.ControlMessage(w)
|
||||||
|
for _, c := range tt.cs {
|
||||||
|
m, err = m.Marshal(c.Level, c.Type, c.Data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !bytes.Equal(ww, w) {
|
||||||
|
t.Fatalf("got %#v; want %#v", ww, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws := [][]byte{w}
|
||||||
|
if tailPadLen > 0 {
|
||||||
|
// Test a message with no tail padding.
|
||||||
|
nopad := w[:len(w)-tailPadLen]
|
||||||
|
ws = append(ws, [][]byte{nopad}...)
|
||||||
|
}
|
||||||
|
for _, w := range ws {
|
||||||
|
ms, err := socket.ControlMessage(w).Parse()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).Parse() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
for i, m := range ms {
|
||||||
|
lvl, typ, dataLen, err := m.ParseHeader()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
|
||||||
|
t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDP(t *testing.T) {
|
||||||
|
c, err := nettest.NewLocalPacketListener("udp")
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
t.Run("Message", func(t *testing.T) {
|
||||||
|
testUDPMessage(t, c.(net.Conn))
|
||||||
|
})
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
t.Run("Messages", func(t *testing.T) {
|
||||||
|
testUDPMessages(t, c.(net.Conn))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUDPMessage(t *testing.T, c net.Conn) {
|
||||||
|
cc, err := socket.NewConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
data := []byte("HELLO-R-U-THERE")
|
||||||
|
wm := socket.Message{
|
||||||
|
Buffers: bytes.SplitAfter(data, []byte("-")),
|
||||||
|
Addr: c.LocalAddr(),
|
||||||
|
}
|
||||||
|
if err := cc.SendMsg(&wm, 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b := make([]byte, 32)
|
||||||
|
rm := socket.Message{
|
||||||
|
Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
|
||||||
|
}
|
||||||
|
if err := cc.RecvMsg(&rm, 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b[:rm.N], data) {
|
||||||
|
t.Fatalf("got %#v; want %#v", b[:rm.N], data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUDPMessages(t *testing.T, c net.Conn) {
|
||||||
|
cc, err := socket.NewConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
data := []byte("HELLO-R-U-THERE")
|
||||||
|
wmbs := bytes.SplitAfter(data, []byte("-"))
|
||||||
|
wms := []socket.Message{
|
||||||
|
{Buffers: wmbs[:1], Addr: c.LocalAddr()},
|
||||||
|
{Buffers: wmbs[1:], Addr: c.LocalAddr()},
|
||||||
|
}
|
||||||
|
n, err := cc.SendMsgs(wms, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n != len(wms) {
|
||||||
|
t.Fatalf("got %d; want %d", n, len(wms))
|
||||||
|
}
|
||||||
|
b := make([]byte, 32)
|
||||||
|
rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
|
||||||
|
rms := []socket.Message{
|
||||||
|
{Buffers: rmbs[0]},
|
||||||
|
{Buffers: rmbs[1]},
|
||||||
|
}
|
||||||
|
n, err = cc.RecvMsgs(rms, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n != len(rms) {
|
||||||
|
t.Fatalf("got %d; want %d", n, len(rms))
|
||||||
|
}
|
||||||
|
nn := 0
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
nn += rms[i].N
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b[:nn], data) {
|
||||||
|
t.Fatalf("got %#v; want %#v", b[:nn], data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUDP(b *testing.B) {
|
||||||
|
c, err := nettest.NewLocalPacketListener("udp")
|
||||||
|
if err != nil {
|
||||||
|
b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
cc, err := socket.NewConn(c.(net.Conn))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
data := []byte("HELLO-R-U-THERE")
|
||||||
|
wm := socket.Message{
|
||||||
|
Buffers: [][]byte{data},
|
||||||
|
Addr: c.LocalAddr(),
|
||||||
|
}
|
||||||
|
rm := socket.Message{
|
||||||
|
Buffers: [][]byte{make([]byte, 128)},
|
||||||
|
OOB: make([]byte, 128),
|
||||||
|
}
|
||||||
|
|
||||||
|
for M := 1; M <= 1<<9; M = M << 1 {
|
||||||
|
b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for j := 0; j < M; j++ {
|
||||||
|
if err := cc.SendMsg(&wm, 0); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := cc.RecvMsg(&rm, 0); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
wms := make([]socket.Message, M)
|
||||||
|
for i := range wms {
|
||||||
|
wms[i].Buffers = [][]byte{data}
|
||||||
|
wms[i].Addr = c.LocalAddr()
|
||||||
|
}
|
||||||
|
rms := make([]socket.Message, M)
|
||||||
|
for i := range rms {
|
||||||
|
rms[i].Buffers = [][]byte{make([]byte, 128)}
|
||||||
|
rms[i].OOB = make([]byte, 128)
|
||||||
|
}
|
||||||
|
b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, err := cc.SendMsgs(wms, 0); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := cc.RecvMsgs(rms, 0); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
vendor/golang.org/x/net/internal/socket/socket_test.go
generated
vendored
Normal file
46
vendor/golang.org/x/net/internal/socket/socket_test.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||||
|
|
||||||
|
package socket_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/internal/socket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSocket(t *testing.T) {
|
||||||
|
t.Run("Option", func(t *testing.T) {
|
||||||
|
testSocketOption(t, &socket.Option{Level: syscall.SOL_SOCKET, Name: syscall.SO_RCVBUF, Len: 4})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSocketOption(t *testing.T, so *socket.Option) {
|
||||||
|
c, err := nettest.NewLocalPacketListener("udp")
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
cc, err := socket.NewConn(c.(net.Conn))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
const N = 2048
|
||||||
|
if err := so.SetInt(cc, N); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
n, err := so.GetInt(cc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n < N {
|
||||||
|
t.Fatalf("got %d; want greater than or equal to %d", n, N)
|
||||||
|
}
|
||||||
|
}
|
33
vendor/golang.org/x/net/internal/socket/sys.go
generated
vendored
Normal file
33
vendor/golang.org/x/net/internal/socket/sys.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// 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 socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NativeEndian is the machine native endian implementation of
|
||||||
|
// ByteOrder.
|
||||||
|
NativeEndian binary.ByteOrder
|
||||||
|
|
||||||
|
kernelAlign int
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
i := uint32(1)
|
||||||
|
b := (*[4]byte)(unsafe.Pointer(&i))
|
||||||
|
if b[0] == 1 {
|
||||||
|
NativeEndian = binary.LittleEndian
|
||||||
|
} else {
|
||||||
|
NativeEndian = binary.BigEndian
|
||||||
|
}
|
||||||
|
kernelAlign = probeProtocolStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
func roundup(l int) int {
|
||||||
|
return (l + kernelAlign - 1) & ^(kernelAlign - 1)
|
||||||
|
}
|
17
vendor/golang.org/x/net/internal/socket/sys_bsd.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/internal/socket/sys_bsd.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// 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 freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func probeProtocolStack() int {
|
||||||
|
var p uintptr
|
||||||
|
return int(unsafe.Sizeof(p))
|
||||||
|
}
|
7
vendor/golang.org/x/net/internal/socket/sys_darwin.go
generated
vendored
Normal file
7
vendor/golang.org/x/net/internal/socket/sys_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// 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 socket
|
||||||
|
|
||||||
|
func probeProtocolStack() int { return 4 }
|
7
vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
generated
vendored
Normal file
7
vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// 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 socket
|
||||||
|
|
||||||
|
func probeProtocolStack() int { return 4 }
|
27
vendor/golang.org/x/net/internal/socket/sys_linux.go
generated
vendored
Normal file
27
vendor/golang.org/x/net/internal/socket/sys_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// 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 linux,!s390x,!386
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func probeProtocolStack() int {
|
||||||
|
var p uintptr
|
||||||
|
return int(unsafe.Sizeof(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
|
||||||
|
n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
|
||||||
|
return int(n), errnoErr(errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
|
||||||
|
n, _, errno := syscall.Syscall6(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
|
||||||
|
return int(n), errnoErr(errno)
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue