diff --git a/glide.lock b/glide.lock index 3b031d24..d7e0deee 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 8b33b8abf5bca183ffa7108b03f4001f4d23f7f2e26f773f5bcb4bfefa51a26f -updated: 2016-07-22T23:25:33.173188655-07:00 +hash: 66d8717b42e620d52ceec62e7cb3f2bc23f21bfe35547587338d85564bd330c9 +updated: 2016-07-31T12:19:29.812965492-07:00 imports: - name: github.com/ericchiang/oidc version: 69fec81d167d815f4f455c741b2a94ffaf547ed2 @@ -7,6 +7,7 @@ imports: version: 874264fbbb43f4d91e999fecb4b40143ed611400 subpackages: - proto + - protoc-gen-go - name: github.com/gorilla/context version: aed02d124ae4a0e94fea4541c8effd05bf0c8296 - name: github.com/gorilla/mux @@ -31,12 +32,18 @@ imports: - bcrypt - blowfish - name: golang.org/x/net - version: d7bf3545bb0dacf009c535b3d3fbf53ac0a339ab + version: 6a513affb38dc9788b449d59ffed099b8de18fa0 subpackages: - context + - http2 + - http2/hpack + - trace + - lex/httplex + - internal/timeseries - name: golang.org/x/oauth2 version: 08c8d727d2392d18286f9f88ad775ad98f09ab33 subpackages: + - github - internal - name: google.golang.org/appengine version: 267c27e7492265b84fc6719503b14a1e17975d79 @@ -48,6 +55,17 @@ imports: - internal/datastore - internal/log - internal/remote_api +- name: google.golang.org/grpc + version: 13edeeffdea7a41d5aad96c28deb4c7bd01a9397 + subpackages: + - codes + - credentials + - grpclog + - internal + - metadata + - naming + - transport + - peer - name: gopkg.in/asn1-ber.v1 version: 4e86f4367175e39f69d9358a5f17b4dda270378d - name: gopkg.in/ldap.v2 diff --git a/vendor/golang.org/x/net/bpf/doc.go b/vendor/golang.org/x/net/bpf/doc.go index bf2564b7..ae62feb5 100644 --- a/vendor/golang.org/x/net/bpf/doc.go +++ b/vendor/golang.org/x/net/bpf/doc.go @@ -5,7 +5,8 @@ /* Package bpf implements marshaling and unmarshaling of programs for the -Berkeley Packet Filter virtual machine. +Berkeley Packet Filter virtual machine, and provides a Go implementation +of the virtual machine. BPF's main use is to specify a packet filter for network taps, so that the kernel doesn't have to expensively copy every packet it sees to diff --git a/vendor/golang.org/x/net/bpf/vm.go b/vendor/golang.org/x/net/bpf/vm.go new file mode 100644 index 00000000..4c656f1e --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm.go @@ -0,0 +1,140 @@ +// 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 bpf + +import ( + "errors" + "fmt" +) + +// A VM is an emulated BPF virtual machine. +type VM struct { + filter []Instruction +} + +// NewVM returns a new VM using the input BPF program. +func NewVM(filter []Instruction) (*VM, error) { + if len(filter) == 0 { + return nil, errors.New("one or more Instructions must be specified") + } + + for i, ins := range filter { + check := len(filter) - (i + 1) + switch ins := ins.(type) { + // Check for out-of-bounds jumps in instructions + case Jump: + if check <= int(ins.Skip) { + return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip) + } + case JumpIf: + if check <= int(ins.SkipTrue) { + return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue) + } + if check <= int(ins.SkipFalse) { + return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) + } + // Check for division or modulus by zero + case ALUOpConstant: + if ins.Val != 0 { + break + } + + switch ins.Op { + case ALUOpDiv, ALUOpMod: + return nil, errors.New("cannot divide by zero using ALUOpConstant") + } + // Check for unknown extensions + case LoadExtension: + switch ins.Num { + case ExtLen: + default: + return nil, fmt.Errorf("extension %d not implemented", ins.Num) + } + } + } + + // Make sure last instruction is a return instruction + switch filter[len(filter)-1].(type) { + case RetA, RetConstant: + default: + return nil, errors.New("BPF program must end with RetA or RetConstant") + } + + // Though our VM works using disassembled instructions, we + // attempt to assemble the input filter anyway to ensure it is compatible + // with an operating system VM. + _, err := Assemble(filter) + + return &VM{ + filter: filter, + }, err +} + +// Run runs the VM's BPF program against the input bytes. +// Run returns the number of bytes accepted by the BPF program, and any errors +// which occurred while processing the program. +func (v *VM) Run(in []byte) (int, error) { + var ( + // Registers of the virtual machine + regA uint32 + regX uint32 + regScratch [16]uint32 + + // OK is true if the program should continue processing the next + // instruction, or false if not, causing the loop to break + ok = true + ) + + // TODO(mdlayher): implement: + // - NegateA: + // - would require a change from uint32 registers to int32 + // registers + + // TODO(mdlayher): add interop tests that check signedness of ALU + // operations against kernel implementation, and make sure Go + // implementation matches behavior + + for i := 0; i < len(v.filter) && ok; i++ { + ins := v.filter[i] + + switch ins := ins.(type) { + case ALUOpConstant: + regA = aluOpConstant(ins, regA) + case ALUOpX: + regA, ok = aluOpX(ins, regA, regX) + case Jump: + i += int(ins.Skip) + case JumpIf: + jump := jumpIf(ins, regA) + i += jump + case LoadAbsolute: + regA, ok = loadAbsolute(ins, in) + case LoadConstant: + regA, regX = loadConstant(ins, regA, regX) + case LoadExtension: + regA = loadExtension(ins, in) + case LoadIndirect: + regA, ok = loadIndirect(ins, in, regX) + case LoadMemShift: + regX, ok = loadMemShift(ins, in) + case LoadScratch: + regA, regX = loadScratch(ins, regScratch, regA, regX) + case RetA: + return int(regA), nil + case RetConstant: + return int(ins.Val), nil + case StoreScratch: + regScratch = storeScratch(ins, regScratch, regA, regX) + case TAX: + regX = regA + case TXA: + regA = regX + default: + return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins) + } + } + + return 0, nil +} diff --git a/vendor/golang.org/x/net/bpf/vm_aluop_test.go b/vendor/golang.org/x/net/bpf/vm_aluop_test.go new file mode 100644 index 00000000..16678244 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_aluop_test.go @@ -0,0 +1,512 @@ +// 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 bpf_test + +import ( + "testing" + + "golang.org/x/net/bpf" +) + +func TestVMALUOpAdd(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpAdd, + Val: 3, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 8, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 3, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpSub(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.TAX{}, + bpf.ALUOpX{ + Op: bpf.ALUOpSub, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpMul(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpMul, + Val: 2, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 6, 2, 3, 4, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpDiv(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpDiv, + Val: 2, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 20, 2, 3, 4, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.ALUOpConstant{ + Op: bpf.ALUOpDiv, + Val: 0, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot divide by zero using ALUOpConstant" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMALUOpDivByZeroALUOpX(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + // Load byte 0 into X + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.TAX{}, + // Load byte 1 into A + bpf.LoadAbsolute{ + Off: 9, + Size: 1, + }, + // Attempt to perform 1/0 + bpf.ALUOpX{ + Op: bpf.ALUOpDiv, + }, + // Return 4 bytes if program does not terminate + bpf.LoadConstant{ + Val: 12, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 3, 4, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpOr(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpOr, + Val: 0x01, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x10, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0xff, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 9, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpAnd(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpAnd, + Val: 0x0019, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xaa, 0x09, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpShiftLeft(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpShiftLeft, + Val: 0x01, + }, + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 0x02, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x01, 0xaa, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpShiftRight(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpShiftRight, + Val: 0x01, + }, + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 0x04, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x08, 0xff, 0xff, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpMod(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpMod, + Val: 20, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 30, 0, 0, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpModByZeroALUOpConstant(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpMod, + Val: 0, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot divide by zero using ALUOpConstant" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMALUOpModByZeroALUOpX(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + // Load byte 0 into X + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.TAX{}, + // Load byte 1 into A + bpf.LoadAbsolute{ + Off: 9, + Size: 1, + }, + // Attempt to perform 1%0 + bpf.ALUOpX{ + Op: bpf.ALUOpMod, + }, + // Return 4 bytes if program does not terminate + bpf.LoadConstant{ + Val: 12, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 3, 4, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpXor(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpXor, + Val: 0x0a, + }, + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 0x01, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x0b, 0x00, 0x00, 0x00, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMALUOpUnknown(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.ALUOpConstant{ + Op: bpf.ALUOpAdd, + Val: 1, + }, + // Verify that an unknown operation is a no-op + bpf.ALUOpConstant{ + Op: 100, + }, + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 0x02, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} diff --git a/vendor/golang.org/x/net/bpf/vm_bpf_test.go b/vendor/golang.org/x/net/bpf/vm_bpf_test.go new file mode 100644 index 00000000..42636236 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_bpf_test.go @@ -0,0 +1,192 @@ +// 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 bpf_test + +import ( + "net" + "runtime" + "testing" + "time" + + "golang.org/x/net/bpf" + "golang.org/x/net/ipv4" +) + +// A virtualMachine is a BPF virtual machine which can process an +// input packet against a BPF program and render a verdict. +type virtualMachine interface { + Run(in []byte) (int, error) +} + +// canUseOSVM indicates if the OS BPF VM is available on this platform. +func canUseOSVM() bool { + // OS BPF VM can only be used on platforms where x/net/ipv4 supports + // attaching a BPF program to a socket. + switch runtime.GOOS { + case "linux": + return true + } + + return false +} + +// All BPF tests against both the Go VM and OS VM are assumed to +// be used with a UDP socket. As a result, the entire contents +// of a UDP datagram is sent through the BPF program, but only +// the body after the UDP header will ever be returned in output. + +// testVM sets up a Go BPF VM, and if available, a native OS BPF VM +// for integration testing. +func testVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func(), error) { + goVM, err := bpf.NewVM(filter) + if err != nil { + // Some tests expect an error, so this error must be returned + // instead of fatally exiting the test + return nil, nil, err + } + + mvm := &multiVirtualMachine{ + goVM: goVM, + + t: t, + } + + // If available, add the OS VM for tests which verify that both the Go + // VM and OS VM have exactly the same output for the same input program + // and packet. + done := func() {} + if canUseOSVM() { + osVM, osVMDone := testOSVM(t, filter) + done = func() { osVMDone() } + mvm.osVM = osVM + } + + return mvm, done, nil +} + +// udpHeaderLen is the length of a UDP header. +const udpHeaderLen = 8 + +// A multiVirtualMachine is a virtualMachine which can call out to both the Go VM +// and the native OS VM, if the OS VM is available. +type multiVirtualMachine struct { + goVM virtualMachine + osVM virtualMachine + + t *testing.T +} + +func (mvm *multiVirtualMachine) Run(in []byte) (int, error) { + if len(in) < udpHeaderLen { + mvm.t.Fatalf("input must be at least length of UDP header (%d), got: %d", + udpHeaderLen, len(in)) + } + + // All tests have a UDP header as part of input, because the OS VM + // packets always will. For the Go VM, this output is trimmed before + // being sent back to tests. + goOut, goErr := mvm.goVM.Run(in) + if goOut >= udpHeaderLen { + goOut -= udpHeaderLen + } + + // If Go output is larger than the size of the packet, packet filtering + // interop tests must trim the output bytes to the length of the packet. + // The BPF VM should not do this on its own, as other uses of it do + // not trim the output byte count. + trim := len(in) - udpHeaderLen + if goOut > trim { + goOut = trim + } + + // When the OS VM is not available, process using the Go VM alone + if mvm.osVM == nil { + return goOut, goErr + } + + // The OS VM will apply its own UDP header, so remove the pseudo header + // that the Go VM needs. + osOut, err := mvm.osVM.Run(in[udpHeaderLen:]) + if err != nil { + mvm.t.Fatalf("error while running OS VM: %v", err) + } + + // Verify both VMs return same number of bytes + var mismatch bool + if goOut != osOut { + mismatch = true + mvm.t.Logf("output byte count does not match:\n- go: %v\n- os: %v", goOut, osOut) + } + + if mismatch { + mvm.t.Fatal("Go BPF and OS BPF packet outputs do not match") + } + + return goOut, goErr +} + +// An osVirtualMachine is a virtualMachine which uses the OS's BPF VM for +// processing BPF programs. +type osVirtualMachine struct { + l net.PacketConn + s net.Conn +} + +// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting +// packets into a UDP listener with a BPF program attached to it. +func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) { + l, err := net.ListenPacket("udp4", "127.0.0.1:0") + if err != nil { + t.Fatalf("failed to open OS VM UDP listener: %v", err) + } + + prog, err := bpf.Assemble(filter) + if err != nil { + t.Fatalf("failed to compile BPF program: %v", err) + } + + p := ipv4.NewPacketConn(l) + if err = p.SetBPF(prog); err != nil { + t.Fatalf("failed to attach BPF program to listener: %v", err) + } + + s, err := net.Dial("udp4", l.LocalAddr().String()) + if err != nil { + t.Fatalf("failed to dial connection to listener: %v", err) + } + + done := func() { + _ = s.Close() + _ = l.Close() + } + + return &osVirtualMachine{ + l: l, + s: s, + }, done +} + +// Run sends the input bytes into the OS's BPF VM and returns its verdict. +func (vm *osVirtualMachine) Run(in []byte) (int, error) { + go func() { + _, _ = vm.s.Write(in) + }() + + vm.l.SetDeadline(time.Now().Add(50 * time.Millisecond)) + + var b [512]byte + n, _, err := vm.l.ReadFrom(b[:]) + if err != nil { + // A timeout indicates that BPF filtered out the packet, and thus, + // no input should be returned. + if nerr, ok := err.(net.Error); ok && nerr.Timeout() { + return n, nil + } + + return n, err + } + + return n, nil +} diff --git a/vendor/golang.org/x/net/bpf/vm_extension_test.go b/vendor/golang.org/x/net/bpf/vm_extension_test.go new file mode 100644 index 00000000..7a48c82f --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_extension_test.go @@ -0,0 +1,49 @@ +// 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 bpf_test + +import ( + "testing" + + "golang.org/x/net/bpf" +) + +func TestVMLoadExtensionNotImplemented(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadExtension{ + Num: 100, + }, + bpf.RetA{}, + }) + if errStr(err) != "extension 100 not implemented" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMLoadExtensionExtLen(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadExtension{ + Num: bpf.ExtLen, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} diff --git a/vendor/golang.org/x/net/bpf/vm_instructions.go b/vendor/golang.org/x/net/bpf/vm_instructions.go new file mode 100644 index 00000000..516f9462 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_instructions.go @@ -0,0 +1,174 @@ +// 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 bpf + +import ( + "encoding/binary" + "fmt" +) + +func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 { + return aluOpCommon(ins.Op, regA, ins.Val) +} + +func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) { + // Guard against division or modulus by zero by terminating + // the program, as the OS BPF VM does + if regX == 0 { + switch ins.Op { + case ALUOpDiv, ALUOpMod: + return 0, false + } + } + + return aluOpCommon(ins.Op, regA, regX), true +} + +func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 { + switch op { + case ALUOpAdd: + return regA + value + case ALUOpSub: + return regA - value + case ALUOpMul: + return regA * value + case ALUOpDiv: + // Division by zero not permitted by NewVM and aluOpX checks + return regA / value + case ALUOpOr: + return regA | value + case ALUOpAnd: + return regA & value + case ALUOpShiftLeft: + return regA << value + case ALUOpShiftRight: + return regA >> value + case ALUOpMod: + // Modulus by zero not permitted by NewVM and aluOpX checks + return regA % value + case ALUOpXor: + return regA ^ value + default: + return regA + } +} + +func jumpIf(ins JumpIf, value uint32) int { + var ok bool + inV := uint32(ins.Val) + + switch ins.Cond { + case JumpEqual: + ok = value == inV + case JumpNotEqual: + ok = value != inV + case JumpGreaterThan: + ok = value > inV + case JumpLessThan: + ok = value < inV + case JumpGreaterOrEqual: + ok = value >= inV + case JumpLessOrEqual: + ok = value <= inV + case JumpBitsSet: + ok = (value & inV) != 0 + case JumpBitsNotSet: + ok = (value & inV) == 0 + } + + if ok { + return int(ins.SkipTrue) + } + + return int(ins.SkipFalse) +} + +func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) { + offset := int(ins.Off) + size := int(ins.Size) + + return loadCommon(in, offset, size) +} + +func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) { + switch ins.Dst { + case RegA: + regA = ins.Val + case RegX: + regX = ins.Val + } + + return regA, regX +} + +func loadExtension(ins LoadExtension, in []byte) uint32 { + switch ins.Num { + case ExtLen: + return uint32(len(in)) + default: + panic(fmt.Sprintf("unimplemented extension: %d", ins.Num)) + } +} + +func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) { + offset := int(ins.Off) + int(regX) + size := int(ins.Size) + + return loadCommon(in, offset, size) +} + +func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) { + offset := int(ins.Off) + + if !inBounds(len(in), offset, 0) { + return 0, false + } + + // Mask off high 4 bits and multiply low 4 bits by 4 + return uint32(in[offset]&0x0f) * 4, true +} + +func inBounds(inLen int, offset int, size int) bool { + return offset+size <= inLen +} + +func loadCommon(in []byte, offset int, size int) (uint32, bool) { + if !inBounds(len(in), offset, size) { + return 0, false + } + + switch size { + case 1: + return uint32(in[offset]), true + case 2: + return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true + case 4: + return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true + default: + panic(fmt.Sprintf("invalid load size: %d", size)) + } +} + +func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) { + switch ins.Dst { + case RegA: + regA = regScratch[ins.N] + case RegX: + regX = regScratch[ins.N] + } + + return regA, regX +} + +func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 { + switch ins.Src { + case RegA: + regScratch[ins.N] = regA + case RegX: + regScratch[ins.N] = regX + } + + return regScratch +} diff --git a/vendor/golang.org/x/net/bpf/vm_jump_test.go b/vendor/golang.org/x/net/bpf/vm_jump_test.go new file mode 100644 index 00000000..e0a3a988 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_jump_test.go @@ -0,0 +1,380 @@ +// 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 bpf_test + +import ( + "testing" + + "golang.org/x/net/bpf" +) + +func TestVMJumpOne(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.Jump{ + Skip: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpOutOfProgram(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.Jump{ + Skip: 1, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot jump 1 instructions; jumping past program bounds" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMJumpIfTrueOutOfProgram(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.JumpIf{ + Cond: bpf.JumpEqual, + SkipTrue: 2, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMJumpIfFalseOutOfProgram(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.JumpIf{ + Cond: bpf.JumpEqual, + SkipFalse: 3, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMJumpIfEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 1, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfNotEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.JumpIf{ + Cond: bpf.JumpNotEqual, + Val: 1, + SkipFalse: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfGreaterThan(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.JumpIf{ + Cond: bpf.JumpGreaterThan, + Val: 0x00010202, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfLessThan(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.JumpIf{ + Cond: bpf.JumpLessThan, + Val: 0xff010203, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfGreaterOrEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.JumpIf{ + Cond: bpf.JumpGreaterOrEqual, + Val: 0x00010203, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfLessOrEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.JumpIf{ + Cond: bpf.JumpLessOrEqual, + Val: 0xff010203, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfBitsSet(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.JumpIf{ + Cond: bpf.JumpBitsSet, + Val: 0x1122, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 10, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x02, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfBitsNotSet(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.JumpIf{ + Cond: bpf.JumpBitsNotSet, + Val: 0x1221, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 10, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x02, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} diff --git a/vendor/golang.org/x/net/bpf/vm_load_test.go b/vendor/golang.org/x/net/bpf/vm_load_test.go new file mode 100644 index 00000000..04578b66 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_load_test.go @@ -0,0 +1,246 @@ +// 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 bpf_test + +import ( + "net" + "testing" + + "golang.org/x/net/bpf" + "golang.org/x/net/ipv4" +) + +func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 100, + Size: 2, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Size: 5, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid load byte length 0" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMLoadConstantOK(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 9, + }, + bpf.TXA{}, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMLoadIndirectOutOfBounds(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadIndirect{ + Off: 100, + Size: 1, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMLoadMemShiftOutOfBounds(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadMemShift{ + Off: 100, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +const ( + dhcp4Port = 53 +) + +func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) { + vm, in, done := testDHCPv4(t) + defer done() + + // Append mostly empty UDP header with incorrect DHCPv4 port + in = append(in, []byte{ + 0, 0, + 0, dhcp4Port + 1, + 0, 0, + 0, 0, + }...) + + out, err := vm.Run(in) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 0, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) { + vm, in, done := testDHCPv4(t) + defer done() + + // Append mostly empty UDP header with correct DHCPv4 port + in = append(in, []byte{ + 0, 0, + 0, dhcp4Port, + 0, 0, + 0, 0, + }...) + + out, err := vm.Run(in) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := len(in)-8, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) { + // DHCPv4 test data courtesy of David Anderson: + // https://github.com/google/netboot/blob/master/dhcp4/conn_linux.go#L59-L70 + vm, done, err := testVM(t, []bpf.Instruction{ + // Load IPv4 packet length + bpf.LoadMemShift{Off: 8}, + // Get UDP dport + bpf.LoadIndirect{Off: 8 + 2, Size: 2}, + // Correct dport? + bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1}, + // Accept + bpf.RetConstant{Val: 1500}, + // Ignore + bpf.RetConstant{Val: 0}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + + // Minimal requirements to make a valid IPv4 header + h := &ipv4.Header{ + Len: ipv4.HeaderLen, + Src: net.IPv4(192, 168, 1, 1), + Dst: net.IPv4(192, 168, 1, 2), + } + hb, err := h.Marshal() + if err != nil { + t.Fatalf("failed to marshal IPv4 header: %v", err) + } + + hb = append([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + }, hb...) + + return vm, hb, done +} diff --git a/vendor/golang.org/x/net/bpf/vm_ret_test.go b/vendor/golang.org/x/net/bpf/vm_ret_test.go new file mode 100644 index 00000000..2d86eae3 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_ret_test.go @@ -0,0 +1,115 @@ +// 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 bpf_test + +import ( + "testing" + + "golang.org/x/net/bpf" +) + +func TestVMRetA(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 9, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMRetALargerThanInput(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 255, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMRetConstant(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMRetConstantLargerThanInput(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.RetConstant{ + Val: 16, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} diff --git a/vendor/golang.org/x/net/bpf/vm_scratch_test.go b/vendor/golang.org/x/net/bpf/vm_scratch_test.go new file mode 100644 index 00000000..e600e3c2 --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_scratch_test.go @@ -0,0 +1,247 @@ +// 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 bpf_test + +import ( + "testing" + + "golang.org/x/net/bpf" +) + +func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.StoreScratch{ + Src: bpf.RegA, + N: -1, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid scratch slot -1" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.StoreScratch{ + Src: bpf.RegA, + N: 16, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid scratch slot 16" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMStoreScratchUnknownSourceRegister(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.StoreScratch{ + Src: 100, + N: 0, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid source register 100" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadScratch{ + Dst: bpf.RegX, + N: -1, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid scratch slot -1" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadScratch{ + Dst: bpf.RegX, + N: 16, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid scratch slot 16" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadScratch{ + Dst: 100, + N: 0, + }, + bpf.RetA{}, + }) + if errStr(err) != "assembling instruction 1: invalid target register 100" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMStoreScratchLoadScratchOneValue(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + // Load byte 255 + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + // Copy to X and store in scratch[0] + bpf.TAX{}, + bpf.StoreScratch{ + Src: bpf.RegX, + N: 0, + }, + // Load byte 1 + bpf.LoadAbsolute{ + Off: 9, + Size: 1, + }, + // Overwrite 1 with 255 from scratch[0] + bpf.LoadScratch{ + Dst: bpf.RegA, + N: 0, + }, + // Return 255 + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 255, 1, 2, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 3, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + // Load byte 10 + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + // Store in scratch[0] + bpf.StoreScratch{ + Src: bpf.RegA, + N: 0, + }, + // Load byte 20 + bpf.LoadAbsolute{ + Off: 9, + Size: 1, + }, + // Store in scratch[1] + bpf.StoreScratch{ + Src: bpf.RegA, + N: 1, + }, + // Load byte 30 + bpf.LoadAbsolute{ + Off: 10, + Size: 1, + }, + // Store in scratch[2] + bpf.StoreScratch{ + Src: bpf.RegA, + N: 2, + }, + // Load byte 1 + bpf.LoadAbsolute{ + Off: 11, + Size: 1, + }, + // Store in scratch[3] + bpf.StoreScratch{ + Src: bpf.RegA, + N: 3, + }, + // Load in byte 10 to X + bpf.LoadScratch{ + Dst: bpf.RegX, + N: 0, + }, + // Copy X -> A + bpf.TXA{}, + // Verify value is 10 + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 10, + SkipTrue: 1, + }, + // Fail test if incorrect + bpf.RetConstant{ + Val: 0, + }, + // Load in byte 20 to A + bpf.LoadScratch{ + Dst: bpf.RegA, + N: 1, + }, + // Verify value is 20 + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 20, + SkipTrue: 1, + }, + // Fail test if incorrect + bpf.RetConstant{ + Val: 0, + }, + // Load in byte 30 to A + bpf.LoadScratch{ + Dst: bpf.RegA, + N: 2, + }, + // Verify value is 30 + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: 30, + SkipTrue: 1, + }, + // Fail test if incorrect + bpf.RetConstant{ + Val: 0, + }, + // Return first two bytes on success + bpf.RetConstant{ + Val: 10, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 10, 20, 30, 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} diff --git a/vendor/golang.org/x/net/bpf/vm_test.go b/vendor/golang.org/x/net/bpf/vm_test.go new file mode 100644 index 00000000..6bd4dd5c --- /dev/null +++ b/vendor/golang.org/x/net/bpf/vm_test.go @@ -0,0 +1,144 @@ +// 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 bpf_test + +import ( + "fmt" + "testing" + + "golang.org/x/net/bpf" +) + +var _ bpf.Instruction = unknown{} + +type unknown struct{} + +func (unknown) Assemble() (bpf.RawInstruction, error) { + return bpf.RawInstruction{}, nil +} + +func TestVMUnknownInstruction(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadConstant{ + Dst: bpf.RegA, + Val: 100, + }, + // Should terminate the program with an error immediately + unknown{}, + bpf.RetA{}, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer done() + + _, err = vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, + }) + if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" { + t.Fatalf("unexpected error while running program: %v", err) + } +} + +func TestVMNoReturnInstruction(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.LoadConstant{ + Dst: bpf.RegA, + Val: 1, + }, + }) + if errStr(err) != "BPF program must end with RetA or RetConstant" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMNoInputInstructions(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{}) + if errStr(err) != "one or more Instructions must be specified" { + t.Fatalf("unexpected error: %v", err) + } +} + +// ExampleNewVM demonstrates usage of a VM, using an Ethernet frame +// as input and checking its EtherType to determine if it should be accepted. +func ExampleNewVM() { + // Offset | Length | Comment + // ------------------------- + // 00 | 06 | Ethernet destination MAC address + // 06 | 06 | Ethernet source MAC address + // 12 | 02 | Ethernet EtherType + const ( + etOff = 12 + etLen = 2 + + etARP = 0x0806 + ) + + // Set up a VM to filter traffic based on if its EtherType + // matches the ARP EtherType. + vm, err := bpf.NewVM([]bpf.Instruction{ + // Load EtherType value from Ethernet header + bpf.LoadAbsolute{ + Off: etOff, + Size: etLen, + }, + // If EtherType is equal to the ARP EtherType, jump to allow + // packet to be accepted + bpf.JumpIf{ + Cond: bpf.JumpEqual, + Val: etARP, + SkipTrue: 1, + }, + // EtherType does not match the ARP EtherType + bpf.RetConstant{ + Val: 0, + }, + // EtherType matches the ARP EtherType, accept up to 1500 + // bytes of packet + bpf.RetConstant{ + Val: 1500, + }, + }) + if err != nil { + panic(fmt.Sprintf("failed to load BPF program: %v", err)) + } + + // Create an Ethernet frame with the ARP EtherType for testing + frame := []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x08, 0x06, + // Payload omitted for brevity + } + + // Run our VM's BPF program using the Ethernet frame as input + out, err := vm.Run(frame) + if err != nil { + panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err)) + } + + // BPF VM can return a byte count greater than the number of input + // bytes, so trim the output to match the input byte length + if out > len(frame) { + out = len(frame) + } + + fmt.Printf("out: %d bytes", out) + + // Output: + // out: 14 bytes +} + +// errStr returns the string representation of an error, or +// "" if it is nil. +func errStr(err error) string { + if err == nil { + return "" + } + + return err.Error() +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go index e45feec4..606cf1f9 100644 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -1,7 +1,9 @@ -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build go1.7 + // Package ctxhttp provides helper functions for performing context-aware HTTP requests. package ctxhttp // import "golang.org/x/net/context/ctxhttp" @@ -14,77 +16,28 @@ import ( "golang.org/x/net/context" ) -func nop() {} - -var ( - testHookContextDoneBeforeHeaders = nop - testHookDoReturned = nop - testHookDidBodyClose = nop -) - -// Do sends an HTTP request with the provided http.Client and returns an HTTP response. +// Do sends an HTTP request with the provided http.Client and returns +// an HTTP response. +// // If the client is nil, http.DefaultClient is used. -// If the context is canceled or times out, ctx.Err() will be returned. +// +// The provided ctx must be non-nil. If it is canceled or times out, +// ctx.Err() will be returned. func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { if client == nil { client = http.DefaultClient } - - // TODO(djd): Respect any existing value of req.Cancel. - cancel := make(chan struct{}) - req.Cancel = cancel - - type responseAndError struct { - resp *http.Response - err error - } - result := make(chan responseAndError, 1) - - // Make local copies of test hooks closed over by goroutines below. - // Prevents data races in tests. - testHookDoReturned := testHookDoReturned - testHookDidBodyClose := testHookDidBodyClose - - go func() { - resp, err := client.Do(req) - testHookDoReturned() - result <- responseAndError{resp, err} - }() - - var resp *http.Response - - select { - case <-ctx.Done(): - testHookContextDoneBeforeHeaders() - close(cancel) - // Clean up after the goroutine calling client.Do: - go func() { - if r := <-result; r.resp != nil { - testHookDidBodyClose() - r.resp.Body.Close() - } - }() - return nil, ctx.Err() - case r := <-result: - var err error - resp, err = r.resp, r.err - if err != nil { - return resp, err - } - } - - c := make(chan struct{}) - go func() { + resp, err := client.Do(req.WithContext(ctx)) + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + if err != nil { select { case <-ctx.Done(): - close(cancel) - case <-c: - // The response's Body is closed. + err = ctx.Err() + default: } - }() - resp.Body = ¬ifyingReader{resp.Body, c} - - return resp, nil + } + return resp, err } // Get issues a GET request via the Do function. @@ -119,28 +72,3 @@ func Post(ctx context.Context, client *http.Client, url string, bodyType string, func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) } - -// notifyingReader is an io.ReadCloser that closes the notify channel after -// Close is called or a Read fails on the underlying ReadCloser. -type notifyingReader struct { - io.ReadCloser - notify chan<- struct{} -} - -func (r *notifyingReader) Read(p []byte) (int, error) { - n, err := r.ReadCloser.Read(p) - if err != nil && r.notify != nil { - close(r.notify) - r.notify = nil - } - return n, err -} - -func (r *notifyingReader) Close() error { - err := r.ReadCloser.Close() - if r.notify != nil { - close(r.notify) - r.notify = nil - } - return err -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go new file mode 100644 index 00000000..9f0f90f1 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go @@ -0,0 +1,28 @@ +// 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 !plan9,go1.7 + +package ctxhttp + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + + "context" +) + +func TestGo17Context(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "ok") + })) + ctx := context.Background() + resp, err := Get(ctx, http.DefaultClient, ts.URL) + if resp == nil || err != nil { + t.Fatalf("error received from client: %v %v", err, resp) + } + resp.Body.Close() +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go new file mode 100644 index 00000000..926870cc --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go @@ -0,0 +1,147 @@ +// 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.7 + +package ctxhttp // import "golang.org/x/net/context/ctxhttp" + +import ( + "io" + "net/http" + "net/url" + "strings" + + "golang.org/x/net/context" +) + +func nop() {} + +var ( + testHookContextDoneBeforeHeaders = nop + testHookDoReturned = nop + testHookDidBodyClose = nop +) + +// Do sends an HTTP request with the provided http.Client and returns an HTTP response. +// If the client is nil, http.DefaultClient is used. +// If the context is canceled or times out, ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + + // TODO(djd): Respect any existing value of req.Cancel. + cancel := make(chan struct{}) + req.Cancel = cancel + + type responseAndError struct { + resp *http.Response + err error + } + result := make(chan responseAndError, 1) + + // Make local copies of test hooks closed over by goroutines below. + // Prevents data races in tests. + testHookDoReturned := testHookDoReturned + testHookDidBodyClose := testHookDidBodyClose + + go func() { + resp, err := client.Do(req) + testHookDoReturned() + result <- responseAndError{resp, err} + }() + + var resp *http.Response + + select { + case <-ctx.Done(): + testHookContextDoneBeforeHeaders() + close(cancel) + // Clean up after the goroutine calling client.Do: + go func() { + if r := <-result; r.resp != nil { + testHookDidBodyClose() + r.resp.Body.Close() + } + }() + return nil, ctx.Err() + case r := <-result: + var err error + resp, err = r.resp, r.err + if err != nil { + return resp, err + } + } + + c := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + close(cancel) + case <-c: + // The response's Body is closed. + } + }() + resp.Body = ¬ifyingReader{resp.Body, c} + + return resp, nil +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} + +// notifyingReader is an io.ReadCloser that closes the notify channel after +// Close is called or a Read fails on the underlying ReadCloser. +type notifyingReader struct { + io.ReadCloser + notify chan<- struct{} +} + +func (r *notifyingReader) Read(p []byte) (int, error) { + n, err := r.ReadCloser.Read(p) + if err != nil && r.notify != nil { + close(r.notify) + r.notify = nil + } + return n, err +} + +func (r *notifyingReader) Close() error { + err := r.ReadCloser.Close() + if r.notify != nil { + close(r.notify) + r.notify = nil + } + return err +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go new file mode 100644 index 00000000..9159cf02 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go @@ -0,0 +1,79 @@ +// 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 !plan9,!go1.7 + +package ctxhttp + +import ( + "net" + "net/http" + "net/http/httptest" + "sync" + "testing" + "time" + + "golang.org/x/net/context" +) + +// golang.org/issue/14065 +func TestClosesResponseBodyOnCancel(t *testing.T) { + defer func() { testHookContextDoneBeforeHeaders = nop }() + defer func() { testHookDoReturned = nop }() + defer func() { testHookDidBodyClose = nop }() + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + defer ts.Close() + + ctx, cancel := context.WithCancel(context.Background()) + + // closed when Do enters select case <-ctx.Done() + enteredDonePath := make(chan struct{}) + + testHookContextDoneBeforeHeaders = func() { + close(enteredDonePath) + } + + testHookDoReturned = func() { + // We now have the result (the Flush'd headers) at least, + // so we can cancel the request. + cancel() + + // But block the client.Do goroutine from sending + // until Do enters into the <-ctx.Done() path, since + // otherwise if both channels are readable, select + // picks a random one. + <-enteredDonePath + } + + sawBodyClose := make(chan struct{}) + testHookDidBodyClose = func() { close(sawBodyClose) } + + tr := &http.Transport{} + defer tr.CloseIdleConnections() + c := &http.Client{Transport: tr} + req, _ := http.NewRequest("GET", ts.URL, nil) + _, doErr := Do(ctx, c, req) + + select { + case <-sawBodyClose: + case <-time.After(5 * time.Second): + t.Fatal("timeout waiting for body to close") + } + + if doErr != ctx.Err() { + t.Errorf("Do error = %v; want %v", doErr, ctx.Err()) + } +} + +type noteCloseConn struct { + net.Conn + onceClose sync.Once + closefn func() +} + +func (c *noteCloseConn) Close() error { + c.onceClose.Do(c.closefn) + return c.Conn.Close() +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go index 77c25ba7..1e415518 100644 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go @@ -7,11 +7,10 @@ package ctxhttp import ( + "io" "io/ioutil" - "net" "net/http" "net/http/httptest" - "sync" "testing" "time" @@ -23,59 +22,62 @@ const ( requestBody = "ok" ) +func okHandler(w http.ResponseWriter, r *http.Request) { + time.Sleep(requestDuration) + io.WriteString(w, requestBody) +} + func TestNoTimeout(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(okHandler)) + defer ts.Close() + ctx := context.Background() - resp, err := doRequest(ctx) - - if resp == nil || err != nil { - t.Fatalf("error received from client: %v %v", err, resp) + res, err := Get(ctx, nil, ts.URL) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + slurp, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if string(slurp) != requestBody { + t.Errorf("body = %q; want %q", slurp, requestBody) } } -func TestCancel(t *testing.T) { +func TestCancelBeforeHeaders(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(requestDuration / 2) + + blockServer := make(chan struct{}) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cancel() - }() + <-blockServer + io.WriteString(w, requestBody) + })) + defer ts.Close() + defer close(blockServer) - resp, err := doRequest(ctx) - - if resp != nil || err == nil { - t.Fatalf("expected error, didn't get one. resp: %v", resp) + res, err := Get(ctx, nil, ts.URL) + if err == nil { + res.Body.Close() + t.Fatal("Get returned unexpected nil error") } - if err != ctx.Err() { - t.Fatalf("expected error from context but got: %v", err) - } -} - -func TestCancelAfterRequest(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - - resp, err := doRequest(ctx) - - // Cancel before reading the body. - // Request.Body should still be readable after the context is canceled. - cancel() - - b, err := ioutil.ReadAll(resp.Body) - if err != nil || string(b) != requestBody { - t.Fatalf("could not read body: %q %v", b, err) + if err != context.Canceled { + t.Errorf("err = %v; want %v", err, context.Canceled) } } func TestCancelAfterHangingRequest(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.(http.Flusher).Flush() <-w.(http.CloseNotifier).CloseNotify() - }) - - serv := httptest.NewServer(handler) - defer serv.Close() + })) + defer ts.Close() ctx, cancel := context.WithCancel(context.Background()) - resp, err := Get(ctx, nil, serv.URL) + resp, err := Get(ctx, nil, ts.URL) if err != nil { t.Fatalf("unexpected error in Get: %v", err) } @@ -101,76 +103,3 @@ func TestCancelAfterHangingRequest(t *testing.T) { case <-done: } } - -func doRequest(ctx context.Context) (*http.Response, error) { - var okHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - time.Sleep(requestDuration) - w.Write([]byte(requestBody)) - }) - - serv := httptest.NewServer(okHandler) - defer serv.Close() - - return Get(ctx, nil, serv.URL) -} - -// golang.org/issue/14065 -func TestClosesResponseBodyOnCancel(t *testing.T) { - defer func() { testHookContextDoneBeforeHeaders = nop }() - defer func() { testHookDoReturned = nop }() - defer func() { testHookDidBodyClose = nop }() - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - defer ts.Close() - - ctx, cancel := context.WithCancel(context.Background()) - - // closed when Do enters select case <-ctx.Done() - enteredDonePath := make(chan struct{}) - - testHookContextDoneBeforeHeaders = func() { - close(enteredDonePath) - } - - testHookDoReturned = func() { - // We now have the result (the Flush'd headers) at least, - // so we can cancel the request. - cancel() - - // But block the client.Do goroutine from sending - // until Do enters into the <-ctx.Done() path, since - // otherwise if both channels are readable, select - // picks a random one. - <-enteredDonePath - } - - sawBodyClose := make(chan struct{}) - testHookDidBodyClose = func() { close(sawBodyClose) } - - tr := &http.Transport{} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - req, _ := http.NewRequest("GET", ts.URL, nil) - _, doErr := Do(ctx, c, req) - - select { - case <-sawBodyClose: - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for body to close") - } - - if doErr != ctx.Err() { - t.Errorf("Do error = %v; want %v", doErr, ctx.Err()) - } -} - -type noteCloseConn struct { - net.Conn - onceClose sync.Once - closefn func() -} - -func (c *noteCloseConn) Close() error { - c.onceClose.Do(c.closefn) - return c.Conn.Close() -} diff --git a/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/golang.org/x/net/http2/client_conn_pool.go index 8cb3eaa6..b1394125 100644 --- a/vendor/golang.org/x/net/http2/client_conn_pool.go +++ b/vendor/golang.org/x/net/http2/client_conn_pool.go @@ -52,7 +52,16 @@ const ( noDialOnMiss = false ) -func (p *clientConnPool) getClientConn(_ *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) { +func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) { + if isConnectionCloseRequest(req) && dialOnMiss { + // It gets its own connection. + const singleUse = true + cc, err := p.t.dialClientConn(addr, singleUse) + if err != nil { + return nil, err + } + return cc, nil + } p.mu.Lock() for _, cc := range p.conns[addr] { if cc.CanTakeNewRequest() { @@ -95,7 +104,8 @@ func (p *clientConnPool) getStartDialLocked(addr string) *dialCall { // run in its own goroutine. func (c *dialCall) dial(addr string) { - c.res, c.err = c.p.t.dialClientConn(addr) + const singleUse = false // shared conn + c.res, c.err = c.p.t.dialClientConn(addr, singleUse) close(c.done) c.p.mu.Lock() diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go index 88067dca..981d407a 100644 --- a/vendor/golang.org/x/net/http2/frame.go +++ b/vendor/golang.org/x/net/http2/frame.go @@ -454,7 +454,7 @@ func terminalReadFrameError(err error) bool { // // If the frame is larger than previously set with SetMaxReadFrameSize, the // returned error is ErrFrameTooLarge. Other errors may be of type -// ConnectionError, StreamError, or anything else from from the underlying +// ConnectionError, StreamError, or anything else from the underlying // reader. func (fr *Framer) ReadFrame() (Frame, error) { fr.errDetail = nil diff --git a/vendor/golang.org/x/net/http2/go16.go b/vendor/golang.org/x/net/http2/go16.go index 00b2e9e3..2b72855f 100644 --- a/vendor/golang.org/x/net/http2/go16.go +++ b/vendor/golang.org/x/net/http2/go16.go @@ -7,6 +7,7 @@ package http2 import ( + "crypto/tls" "net/http" "time" ) @@ -14,3 +15,29 @@ import ( func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { 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 + } +} diff --git a/vendor/golang.org/x/net/http2/not_go16.go b/vendor/golang.org/x/net/http2/not_go16.go index 51a7f19d..efd2e128 100644 --- a/vendor/golang.org/x/net/http2/not_go16.go +++ b/vendor/golang.org/x/net/http2/not_go16.go @@ -7,6 +7,7 @@ package http2 import ( + "crypto/tls" "net/http" "time" ) @@ -17,4 +18,29 @@ func configureTransport(t1 *http.Transport) (*Transport, error) { func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { 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 + } } diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 1de81461..dbe6c87c 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -339,30 +339,6 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { sc.serve() } -// 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 - } -} - func (sc *serverConn) rejectConn(err ErrCode, debug string) { sc.vlogf("http2: server rejecting conn: %v, %s", err, debug) // ignoring errors. hanging up anyway. @@ -1200,6 +1176,10 @@ func (sc *serverConn) closeStream(st *stream, err error) { } delete(sc.streams, st.id) if p := st.body; p != nil { + // Return any buffered unread bytes worth of conn-level flow control. + // See golang.org/issue/16481 + sc.sendWindowUpdate(nil, p.Len()) + p.CloseWithError(err) } st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc @@ -1301,6 +1281,8 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error { func (sc *serverConn) processData(f *DataFrame) error { sc.serveG.check() + data := f.Data() + // "If a DATA frame is received whose stream is not in "open" // or "half closed (local)" state, the recipient MUST respond // with a stream error (Section 5.4.2) of type STREAM_CLOSED." @@ -1312,12 +1294,25 @@ func (sc *serverConn) processData(f *DataFrame) error { // the http.Handler returned, so it's done reading & // done writing). Try to stop the client from sending // more DATA. + + // But still enforce their connection-level flow control, + // and return any flow control bytes since we're not going + // to consume them. + if int(sc.inflow.available()) < len(data) { + return StreamError{id, ErrCodeFlowControl} + } + // Deduct the flow control from inflow, since we're + // going to immediately add it back in + // sendWindowUpdate, which also schedules sending the + // frames. + sc.inflow.take(int32(len(data))) + sc.sendWindowUpdate(nil, len(data)) // conn-level + return StreamError{id, ErrCodeStreamClosed} } if st.body == nil { panic("internal error: should have a body in this state") } - data := f.Data() // Sender sending more than they'd declared? if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes { diff --git a/vendor/golang.org/x/net/http2/server_test.go b/vendor/golang.org/x/net/http2/server_test.go index 61a7f9dc..ac4d351e 100644 --- a/vendor/golang.org/x/net/http2/server_test.go +++ b/vendor/golang.org/x/net/http2/server_test.go @@ -104,6 +104,8 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{} case optQuiet: quiet = true } + case func(net.Conn, http.ConnState): + ts.Config.ConnState = v default: t.Fatalf("unknown newServerTester option type %T", v) } @@ -2165,6 +2167,9 @@ func TestServer_NoCrash_HandlerClose_Then_ClientClose(t *testing.T) { // it did before. st.writeData(1, true, []byte("foo")) + // Get our flow control bytes back, since the handler didn't get them. + st.wantWindowUpdate(0, uint32(len("foo"))) + // Sent after a peer sends data anyway (admittedly the // previous RST_STREAM might've still been in-flight), // but they'll get the more friendly 'cancel' code @@ -3299,3 +3304,43 @@ func TestExpect100ContinueAfterHandlerWrites(t *testing.T) { t.Fatalf("second msg = %q; want %q", buf, msg2) } } + +type funcReader func([]byte) (n int, err error) + +func (f funcReader) Read(p []byte) (n int, err error) { return f(p) } + +// golang.org/issue/16481 -- return flow control when streams close with unread data. +// (The Server version of the bug. See also TestUnreadFlowControlReturned_Transport) +func TestUnreadFlowControlReturned_Server(t *testing.T) { + unblock := make(chan bool, 1) + defer close(unblock) + + st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { + // Don't read the 16KB request body. Wait until the client's + // done sending it and then return. This should cause the Server + // to then return those 16KB of flow control to the client. + <-unblock + }, optOnlyServer) + defer st.Close() + + tr := &Transport{TLSClientConfig: tlsConfigInsecure} + defer tr.CloseIdleConnections() + + // This previously hung on the 4th iteration. + for i := 0; i < 6; i++ { + body := io.MultiReader( + io.LimitReader(neverEnding('A'), 16<<10), + funcReader(func([]byte) (n int, err error) { + unblock <- true + return 0, io.EOF + }), + ) + req, _ := http.NewRequest("POST", st.ts.URL, body) + res, err := tr.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + res.Body.Close() + } + +} diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 060471ed..b6f6f952 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -139,9 +139,10 @@ func (t *Transport) initConnPool() { // ClientConn is the state of a single HTTP/2 client connection to an // HTTP/2 server. type ClientConn struct { - t *Transport - tconn net.Conn // usually *tls.Conn, except specialized impls - tlsState *tls.ConnectionState // nil only for specialized impls + t *Transport + tconn net.Conn // usually *tls.Conn, except specialized impls + tlsState *tls.ConnectionState // nil only for specialized impls + singleUse bool // whether being used for a single http.Request // readLoop goroutine fields: readerDone chan struct{} // closed on error @@ -153,6 +154,7 @@ type ClientConn struct { inflow flow // peer's conn-level flow control closed bool goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received + goAwayDebug string // goAway frame's debug data, retained as a string streams map[uint32]*clientStream // client-initiated nextStreamID uint32 bw *bufio.Writer @@ -337,7 +339,7 @@ func shouldRetryRequest(req *http.Request, err error) bool { return err == errClientConnUnusable } -func (t *Transport) dialClientConn(addr string) (*ClientConn, error) { +func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) { host, _, err := net.SplitHostPort(addr) if err != nil { return nil, err @@ -346,7 +348,7 @@ func (t *Transport) dialClientConn(addr string) (*ClientConn, error) { if err != nil { return nil, err } - return t.NewClientConn(tconn) + return t.newClientConn(tconn, singleUse) } func (t *Transport) newTLSConfig(host string) *tls.Config { @@ -407,6 +409,10 @@ func (t *Transport) expectContinueTimeout() time.Duration { } func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { + return t.newClientConn(c, false) +} + +func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { if VerboseLogs { t.vlogf("http2: Transport creating client conn to %v", c.RemoteAddr()) } @@ -424,6 +430,7 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { initialWindowSize: 65535, // spec default maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough. streams: make(map[uint32]*clientStream), + singleUse: singleUse, } cc.cond = sync.NewCond(&cc.mu) cc.flow.add(int32(initialWindowSize)) @@ -494,7 +501,17 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { func (cc *ClientConn) setGoAway(f *GoAwayFrame) { cc.mu.Lock() defer cc.mu.Unlock() + + old := cc.goAway cc.goAway = f + + // Merge the previous and current GoAway error frames. + if cc.goAwayDebug == "" { + cc.goAwayDebug = string(f.DebugData()) + } + if old != nil && old.ErrCode != ErrCodeNo { + cc.goAway.ErrCode = old.ErrCode + } } func (cc *ClientConn) CanTakeNewRequest() bool { @@ -504,6 +521,9 @@ func (cc *ClientConn) CanTakeNewRequest() bool { } func (cc *ClientConn) canTakeNewRequestLocked() bool { + if cc.singleUse && cc.nextStreamID > 1 { + return false + } return cc.goAway == nil && !cc.closed && int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) && cc.nextStreamID < 2147483647 @@ -732,30 +752,34 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { bodyWritten := false ctx := reqContext(req) + handleReadLoopResponse := func(re resAndError) (*http.Response, error) { + res := re.res + if re.err != nil || res.StatusCode > 299 { + // On error or status code 3xx, 4xx, 5xx, etc abort any + // ongoing write, assuming that the server doesn't care + // about our request body. If the server replied with 1xx or + // 2xx, however, then assume the server DOES potentially + // want our body (e.g. full-duplex streaming: + // golang.org/issue/13444). If it turns out the server + // doesn't, they'll RST_STREAM us soon enough. This is a + // heuristic to avoid adding knobs to Transport. Hopefully + // we can keep it. + bodyWriter.cancel() + cs.abortRequestBodyWrite(errStopReqBodyWrite) + } + if re.err != nil { + cc.forgetStreamID(cs.ID) + return nil, re.err + } + res.Request = req + res.TLS = cc.tlsState + return res, nil + } + for { select { case re := <-readLoopResCh: - res := re.res - if re.err != nil || res.StatusCode > 299 { - // On error or status code 3xx, 4xx, 5xx, etc abort any - // ongoing write, assuming that the server doesn't care - // about our request body. If the server replied with 1xx or - // 2xx, however, then assume the server DOES potentially - // want our body (e.g. full-duplex streaming: - // golang.org/issue/13444). If it turns out the server - // doesn't, they'll RST_STREAM us soon enough. This is a - // heuristic to avoid adding knobs to Transport. Hopefully - // we can keep it. - bodyWriter.cancel() - cs.abortRequestBodyWrite(errStopReqBodyWrite) - } - if re.err != nil { - cc.forgetStreamID(cs.ID) - return nil, re.err - } - res.Request = req - res.TLS = cc.tlsState - return res, nil + return handleReadLoopResponse(re) case <-respHeaderTimer: cc.forgetStreamID(cs.ID) if !hasBody || bodyWritten { @@ -789,6 +813,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { // forgetStreamID. return nil, cs.resetErr case err := <-bodyWriter.resc: + // Prefer the read loop's response, if available. Issue 16102. + select { + case re := <-readLoopResCh: + return handleReadLoopResponse(re) + default: + } if err != nil { return nil, err } @@ -1160,6 +1190,19 @@ func (cc *ClientConn) readLoop() { } } +// GoAwayError is returned by the Transport when the server closes the +// TCP connection after sending a GOAWAY frame. +type GoAwayError struct { + LastStreamID uint32 + ErrCode ErrCode + DebugData string +} + +func (e GoAwayError) Error() string { + return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q", + e.LastStreamID, e.ErrCode, e.DebugData) +} + func (rl *clientConnReadLoop) cleanup() { cc := rl.cc defer cc.tconn.Close() @@ -1170,10 +1213,18 @@ func (rl *clientConnReadLoop) cleanup() { // TODO: also do this if we've written the headers but not // gotten a response yet. err := cc.readerErr - if err == io.EOF { - err = io.ErrUnexpectedEOF - } cc.mu.Lock() + if err == io.EOF { + if cc.goAway != nil { + err = GoAwayError{ + LastStreamID: cc.goAway.LastStreamID, + ErrCode: cc.goAway.ErrCode, + DebugData: cc.goAwayDebug, + } + } else { + err = io.ErrUnexpectedEOF + } + } for _, cs := range rl.activeRes { cs.bufPipe.CloseWithError(err) } @@ -1191,7 +1242,7 @@ func (rl *clientConnReadLoop) cleanup() { func (rl *clientConnReadLoop) run() error { cc := rl.cc - rl.closeWhenIdle = cc.t.disableKeepAlives() + rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse gotReply := false // ever saw a reply for { f, err := cc.fr.ReadFrame() @@ -1486,10 +1537,27 @@ var errClosedResponseBody = errors.New("http2: response body closed") func (b transportResponseBody) Close() error { cs := b.cs - if cs.bufPipe.Err() != io.EOF { - // TODO: write test for this - cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) + cc := cs.cc + + serverSentStreamEnd := cs.bufPipe.Err() == io.EOF + unread := cs.bufPipe.Len() + + if unread > 0 || !serverSentStreamEnd { + cc.mu.Lock() + cc.wmu.Lock() + if !serverSentStreamEnd { + cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel) + } + // Return connection-level flow control. + if unread > 0 { + cc.inflow.add(int32(unread)) + cc.fr.WriteWindowUpdate(0, uint32(unread)) + } + cc.bw.Flush() + cc.wmu.Unlock() + cc.mu.Unlock() } + cs.bufPipe.BreakWithError(errClosedResponseBody) return nil } @@ -1497,6 +1565,7 @@ func (b transportResponseBody) Close() error { func (rl *clientConnReadLoop) processData(f *DataFrame) error { cc := rl.cc cs := cc.streamByID(f.StreamID, f.StreamEnded()) + data := f.Data() if cs == nil { cc.mu.Lock() neverSent := cc.nextStreamID @@ -1510,9 +1579,17 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error { // TODO: be stricter here? only silently ignore things which // we canceled, but not things which were closed normally // by the peer? Tough without accumulating too much state. + + // But at least return their flow control: + if len(data) > 0 { + cc.wmu.Lock() + cc.fr.WriteWindowUpdate(0, uint32(len(data))) + cc.bw.Flush() + cc.wmu.Unlock() + } return nil } - if data := f.Data(); len(data) > 0 { + if len(data) > 0 { if cs.bufPipe.b == nil { // Data frame after it's already closed? cc.logf("http2: Transport received DATA frame for closed stream; closing connection") @@ -1557,7 +1634,7 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) { } cs.bufPipe.closeWithErrorAndCode(err, code) delete(rl.activeRes, cs.ID) - if cs.req.Close || cs.req.Header.Get("Connection") == "close" { + if isConnectionCloseRequest(cs.req) { rl.closeWhenIdle = true } } @@ -1679,8 +1756,10 @@ func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error { } func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error) { - // TODO: do something with err? send it as a debug frame to the peer? - // But that's only in GOAWAY. Invent a new frame type? Is there one already? + // TODO: map err to more interesting error codes, once the + // HTTP community comes up with some. But currently for + // RST_STREAM there's no equivalent to GOAWAY frame's debug + // data, and the error codes are all pretty vague ("cancel"). cc.wmu.Lock() cc.fr.WriteRSTStream(streamID, code) cc.bw.Flush() @@ -1830,3 +1909,9 @@ func (s bodyWriterState) scheduleBodyWrite() { s.timer.Reset(s.delay) } } + +// isConnectionCloseRequest reports whether req should use its own +// connection for a single request and then close the connection. +func isConnectionCloseRequest(req *http.Request) bool { + return req.Close || httplex.HeaderValuesContainsToken(req.Header["Connection"], "close") +} diff --git a/vendor/golang.org/x/net/http2/transport_test.go b/vendor/golang.org/x/net/http2/transport_test.go index 631a04be..f22eecae 100644 --- a/vendor/golang.org/x/net/http2/transport_test.go +++ b/vendor/golang.org/x/net/http2/transport_test.go @@ -150,7 +150,9 @@ func TestTransport(t *testing.T) { func onSameConn(t *testing.T, modReq func(*http.Request)) bool { st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, r.RemoteAddr) - }, optOnlyServer) + }, optOnlyServer, func(c net.Conn, st http.ConnState) { + t.Logf("conn %v is now state %v", c.RemoteAddr(), st) + }) defer st.Close() tr := &Transport{TLSClientConfig: tlsConfigInsecure} defer tr.CloseIdleConnections() @@ -755,18 +757,18 @@ func testTransportReqBodyAfterResponse(t *testing.T, status int) { if f.StreamEnded() { return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f) } - time.Sleep(50 * time.Millisecond) // let client send body - enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) case *DataFrame: dataLen := len(f.Data()) - dataRecv += int64(dataLen) if dataLen > 0 { + if dataRecv == 0 { + enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)}) + ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: f.StreamID, + EndHeaders: true, + EndStream: false, + BlockFragment: buf.Bytes(), + }) + } if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil { return err } @@ -774,6 +776,8 @@ func testTransportReqBodyAfterResponse(t *testing.T, status int) { return err } } + dataRecv += int64(dataLen) + if !closed && ((status != 200 && dataRecv > 0) || (status == 200 && dataRecv == bodySize)) { closed = true @@ -1013,41 +1017,38 @@ func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerTy if err != nil { return err } + endStream := false + send := func(mode headerType) { + hbf := buf.Bytes() + switch mode { + case oneHeader: + ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: f.Header().StreamID, + EndHeaders: true, + EndStream: endStream, + BlockFragment: hbf, + }) + case splitHeader: + if len(hbf) < 2 { + panic("too small") + } + ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: f.Header().StreamID, + EndHeaders: false, + EndStream: endStream, + BlockFragment: hbf[:1], + }) + ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:]) + default: + panic("bogus mode") + } + } switch f := f.(type) { case *WindowUpdateFrame, *SettingsFrame: case *DataFrame: - // ignore for now. - case *HeadersFrame: - endStream := false - send := func(mode headerType) { - hbf := buf.Bytes() - switch mode { - case oneHeader: - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: endStream, - BlockFragment: hbf, - }) - case splitHeader: - if len(hbf) < 2 { - panic("too small") - } - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: false, - EndStream: endStream, - BlockFragment: hbf[:1], - }) - ct.fr.WriteContinuation(f.StreamID, true, hbf[1:]) - default: - panic("bogus mode") - } - } - if expect100Continue != noHeader { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"}) - send(expect100Continue) + if !f.StreamEnded() { + // No need to send flow control tokens. The test request body is tiny. + continue } // Response headers (1+ frames; 1 or 2 in this test, but never 0) { @@ -1071,7 +1072,15 @@ func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerTy enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"}) send(trailers) } - return nil + if endStream { + return nil + } + case *HeadersFrame: + if expect100Continue != noHeader { + buf.Reset() + enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"}) + send(expect100Continue) + } } } } @@ -2011,3 +2020,160 @@ func TestTransportFlowControl(t *testing.T) { time.Sleep(1 * time.Millisecond) } } + +// golang.org/issue/14627 -- if the server sends a GOAWAY frame, make +// the Transport remember it and return it back to users (via +// RoundTrip or request body reads) if needed (e.g. if the server +// proceeds to close the TCP connection before the client gets its +// response) +func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) { + testTransportUsesGoAwayDebugError(t, false) +} + +func TestTransportUsesGoAwayDebugError_Body(t *testing.T) { + testTransportUsesGoAwayDebugError(t, true) +} + +func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) { + ct := newClientTester(t) + clientDone := make(chan struct{}) + + const goAwayErrCode = ErrCodeHTTP11Required // arbitrary + const goAwayDebugData = "some debug data" + + ct.client = func() error { + defer close(clientDone) + req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) + res, err := ct.tr.RoundTrip(req) + if failMidBody { + if err != nil { + return fmt.Errorf("unexpected client RoundTrip error: %v", err) + } + _, err = io.Copy(ioutil.Discard, res.Body) + res.Body.Close() + } + want := GoAwayError{ + LastStreamID: 5, + ErrCode: goAwayErrCode, + DebugData: goAwayDebugData, + } + if !reflect.DeepEqual(err, want) { + t.Errorf("RoundTrip error = %T: %#v, want %T (%#T)", err, err, want, want) + } + return nil + } + ct.server = func() error { + ct.greet() + for { + f, err := ct.fr.ReadFrame() + if err != nil { + t.Logf("ReadFrame: %v", err) + return nil + } + hf, ok := f.(*HeadersFrame) + if !ok { + continue + } + if failMidBody { + var buf bytes.Buffer + enc := hpack.NewEncoder(&buf) + enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"}) + ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: hf.StreamID, + EndHeaders: true, + EndStream: false, + BlockFragment: buf.Bytes(), + }) + } + // Write two GOAWAY frames, to test that the Transport takes + // the interesting parts of both. + ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData)) + ct.fr.WriteGoAway(5, goAwayErrCode, nil) + ct.sc.Close() + <-clientDone + return nil + } + } + ct.run() +} + +// See golang.org/issue/16481 +func TestTransportReturnsUnusedFlowControl(t *testing.T) { + ct := newClientTester(t) + + clientClosed := make(chan bool, 1) + serverWroteBody := make(chan bool, 1) + + ct.client = func() error { + req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) + res, err := ct.tr.RoundTrip(req) + if err != nil { + return err + } + <-serverWroteBody + + if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 { + return fmt.Errorf("body read = %v, %v; want 1, nil", n, err) + } + res.Body.Close() // leaving 4999 bytes unread + clientClosed <- true + + return nil + } + ct.server = func() error { + ct.greet() + + var hf *HeadersFrame + for { + f, err := ct.fr.ReadFrame() + if err != nil { + return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) + } + switch f.(type) { + case *WindowUpdateFrame, *SettingsFrame: + continue + } + var ok bool + hf, ok = f.(*HeadersFrame) + if !ok { + return fmt.Errorf("Got %T; want HeadersFrame", f) + } + break + } + + var buf bytes.Buffer + enc := hpack.NewEncoder(&buf) + enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"}) + ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: hf.StreamID, + EndHeaders: true, + EndStream: false, + BlockFragment: buf.Bytes(), + }) + ct.fr.WriteData(hf.StreamID, false, make([]byte, 5000)) // without ending stream + serverWroteBody <- true + + <-clientClosed + + f, err := ct.fr.ReadFrame() + if err != nil { + return fmt.Errorf("ReadFrame while waiting for RSTStreamFrame: %v", err) + } + if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel { + return fmt.Errorf("Expected a WindowUpdateFrame with code cancel; got %v", summarizeFrame(f)) + } + + // And wait for our flow control tokens back: + f, err = ct.fr.ReadFrame() + if err != nil { + return fmt.Errorf("ReadFrame while waiting for WindowUpdateFrame: %v", err) + } + if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 { + return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f)) + } + return nil + } + ct.run() +} diff --git a/vendor/golang.org/x/net/ipv4/gen.go b/vendor/golang.org/x/net/ipv4/gen.go index fb72cdc3..cbe70327 100644 --- a/vendor/golang.org/x/net/ipv4/gen.go +++ b/vendor/golang.org/x/net/ipv4/gen.go @@ -58,7 +58,7 @@ func genzsys() error { switch { case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris": b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv4\n"), 1) - case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"): + case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"): b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv4\n"), 1) } b, err = format.Source(b) diff --git a/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go b/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go new file mode 100644 index 00000000..15426bee --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go @@ -0,0 +1,148 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs defs_linux.go + +// +build linux,ppc + +package ipv4 + +const ( + sysIP_TOS = 0x1 + sysIP_TTL = 0x2 + sysIP_HDRINCL = 0x3 + sysIP_OPTIONS = 0x4 + sysIP_ROUTER_ALERT = 0x5 + sysIP_RECVOPTS = 0x6 + sysIP_RETOPTS = 0x7 + sysIP_PKTINFO = 0x8 + sysIP_PKTOPTIONS = 0x9 + sysIP_MTU_DISCOVER = 0xa + sysIP_RECVERR = 0xb + sysIP_RECVTTL = 0xc + sysIP_RECVTOS = 0xd + sysIP_MTU = 0xe + sysIP_FREEBIND = 0xf + sysIP_TRANSPARENT = 0x13 + sysIP_RECVRETOPTS = 0x7 + sysIP_ORIGDSTADDR = 0x14 + sysIP_RECVORIGDSTADDR = 0x14 + sysIP_MINTTL = 0x15 + sysIP_NODEFRAG = 0x16 + sysIP_UNICAST_IF = 0x32 + + sysIP_MULTICAST_IF = 0x20 + sysIP_MULTICAST_TTL = 0x21 + sysIP_MULTICAST_LOOP = 0x22 + sysIP_ADD_MEMBERSHIP = 0x23 + sysIP_DROP_MEMBERSHIP = 0x24 + sysIP_UNBLOCK_SOURCE = 0x25 + sysIP_BLOCK_SOURCE = 0x26 + sysIP_ADD_SOURCE_MEMBERSHIP = 0x27 + sysIP_DROP_SOURCE_MEMBERSHIP = 0x28 + sysIP_MSFILTER = 0x29 + sysMCAST_JOIN_GROUP = 0x2a + sysMCAST_LEAVE_GROUP = 0x2d + sysMCAST_JOIN_SOURCE_GROUP = 0x2e + sysMCAST_LEAVE_SOURCE_GROUP = 0x2f + sysMCAST_BLOCK_SOURCE = 0x2b + sysMCAST_UNBLOCK_SOURCE = 0x2c + sysMCAST_MSFILTER = 0x30 + sysIP_MULTICAST_ALL = 0x31 + + sysICMP_FILTER = 0x1 + + sysSO_EE_ORIGIN_NONE = 0x0 + sysSO_EE_ORIGIN_LOCAL = 0x1 + sysSO_EE_ORIGIN_ICMP = 0x2 + sysSO_EE_ORIGIN_ICMP6 = 0x3 + sysSO_EE_ORIGIN_TXSTATUS = 0x4 + sysSO_EE_ORIGIN_TIMESTAMPING = 0x4 + + sysSOL_SOCKET = 0x1 + sysSO_ATTACH_FILTER = 0x1a + + sysSizeofKernelSockaddrStorage = 0x80 + sysSizeofSockaddrInet = 0x10 + sysSizeofInetPktinfo = 0xc + sysSizeofSockExtendedErr = 0x10 + + sysSizeofIPMreq = 0x8 + sysSizeofIPMreqn = 0xc + sysSizeofIPMreqSource = 0xc + sysSizeofGroupReq = 0x84 + sysSizeofGroupSourceReq = 0x104 + + sysSizeofICMPFilter = 0x4 +) + +type sysKernelSockaddrStorage struct { + Family uint16 + X__data [126]uint8 +} + +type sysSockaddrInet struct { + Family uint16 + Port uint16 + Addr [4]byte /* in_addr */ + X__pad [8]uint8 +} + +type sysInetPktinfo struct { + Ifindex int32 + Spec_dst [4]byte /* in_addr */ + Addr [4]byte /* in_addr */ +} + +type sysSockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} + +type sysIPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type sysIPMreqn struct { + Multiaddr [4]byte /* in_addr */ + Address [4]byte /* in_addr */ + Ifindex int32 +} + +type sysIPMreqSource struct { + Multiaddr uint32 + Interface uint32 + Sourceaddr uint32 +} + +type sysGroupReq struct { + Interface uint32 + Group sysKernelSockaddrStorage +} + +type sysGroupSourceReq struct { + Interface uint32 + Group sysKernelSockaddrStorage + Source sysKernelSockaddrStorage +} + +type sysICMPFilter struct { + Data uint32 +} + +type sysSockFProg struct { + Len uint16 + Pad_cgo_0 [2]byte + Filter *sysSockFilter +} + +type sysSockFilter struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} diff --git a/vendor/golang.org/x/net/ipv6/gen.go b/vendor/golang.org/x/net/ipv6/gen.go index 4e7ca785..826e3ae2 100644 --- a/vendor/golang.org/x/net/ipv6/gen.go +++ b/vendor/golang.org/x/net/ipv6/gen.go @@ -58,7 +58,7 @@ func genzsys() error { switch { case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris": b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv6\n"), 1) - case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"): + case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"): b = bytes.Replace(b, []byte("package ipv6\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv6\n"), 1) } b, err = format.Source(b) diff --git a/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go b/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go new file mode 100644 index 00000000..4c58ea67 --- /dev/null +++ b/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go @@ -0,0 +1,170 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs defs_linux.go + +// +build linux,ppc + +package ipv6 + +const ( + sysIPV6_ADDRFORM = 0x1 + sysIPV6_2292PKTINFO = 0x2 + sysIPV6_2292HOPOPTS = 0x3 + sysIPV6_2292DSTOPTS = 0x4 + sysIPV6_2292RTHDR = 0x5 + sysIPV6_2292PKTOPTIONS = 0x6 + sysIPV6_CHECKSUM = 0x7 + sysIPV6_2292HOPLIMIT = 0x8 + sysIPV6_NEXTHOP = 0x9 + sysIPV6_FLOWINFO = 0xb + + sysIPV6_UNICAST_HOPS = 0x10 + sysIPV6_MULTICAST_IF = 0x11 + sysIPV6_MULTICAST_HOPS = 0x12 + sysIPV6_MULTICAST_LOOP = 0x13 + sysIPV6_ADD_MEMBERSHIP = 0x14 + sysIPV6_DROP_MEMBERSHIP = 0x15 + sysMCAST_JOIN_GROUP = 0x2a + sysMCAST_LEAVE_GROUP = 0x2d + sysMCAST_JOIN_SOURCE_GROUP = 0x2e + sysMCAST_LEAVE_SOURCE_GROUP = 0x2f + sysMCAST_BLOCK_SOURCE = 0x2b + sysMCAST_UNBLOCK_SOURCE = 0x2c + sysMCAST_MSFILTER = 0x30 + sysIPV6_ROUTER_ALERT = 0x16 + sysIPV6_MTU_DISCOVER = 0x17 + sysIPV6_MTU = 0x18 + sysIPV6_RECVERR = 0x19 + sysIPV6_V6ONLY = 0x1a + sysIPV6_JOIN_ANYCAST = 0x1b + sysIPV6_LEAVE_ANYCAST = 0x1c + + sysIPV6_FLOWLABEL_MGR = 0x20 + sysIPV6_FLOWINFO_SEND = 0x21 + + sysIPV6_IPSEC_POLICY = 0x22 + sysIPV6_XFRM_POLICY = 0x23 + + sysIPV6_RECVPKTINFO = 0x31 + sysIPV6_PKTINFO = 0x32 + sysIPV6_RECVHOPLIMIT = 0x33 + sysIPV6_HOPLIMIT = 0x34 + sysIPV6_RECVHOPOPTS = 0x35 + sysIPV6_HOPOPTS = 0x36 + sysIPV6_RTHDRDSTOPTS = 0x37 + sysIPV6_RECVRTHDR = 0x38 + sysIPV6_RTHDR = 0x39 + sysIPV6_RECVDSTOPTS = 0x3a + sysIPV6_DSTOPTS = 0x3b + sysIPV6_RECVPATHMTU = 0x3c + sysIPV6_PATHMTU = 0x3d + sysIPV6_DONTFRAG = 0x3e + + sysIPV6_RECVTCLASS = 0x42 + sysIPV6_TCLASS = 0x43 + + sysIPV6_ADDR_PREFERENCES = 0x48 + + sysIPV6_PREFER_SRC_TMP = 0x1 + sysIPV6_PREFER_SRC_PUBLIC = 0x2 + sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100 + sysIPV6_PREFER_SRC_COA = 0x4 + sysIPV6_PREFER_SRC_HOME = 0x400 + sysIPV6_PREFER_SRC_CGA = 0x8 + sysIPV6_PREFER_SRC_NONCGA = 0x800 + + sysIPV6_MINHOPCOUNT = 0x49 + + sysIPV6_ORIGDSTADDR = 0x4a + sysIPV6_RECVORIGDSTADDR = 0x4a + sysIPV6_TRANSPARENT = 0x4b + sysIPV6_UNICAST_IF = 0x4c + + sysICMPV6_FILTER = 0x1 + + sysICMPV6_FILTER_BLOCK = 0x1 + sysICMPV6_FILTER_PASS = 0x2 + sysICMPV6_FILTER_BLOCKOTHERS = 0x3 + sysICMPV6_FILTER_PASSONLY = 0x4 + + sysSOL_SOCKET = 0x1 + sysSO_ATTACH_FILTER = 0x1a + + sysSizeofKernelSockaddrStorage = 0x80 + sysSizeofSockaddrInet6 = 0x1c + sysSizeofInet6Pktinfo = 0x14 + sysSizeofIPv6Mtuinfo = 0x20 + sysSizeofIPv6FlowlabelReq = 0x20 + + sysSizeofIPv6Mreq = 0x14 + sysSizeofGroupReq = 0x84 + sysSizeofGroupSourceReq = 0x104 + + sysSizeofICMPv6Filter = 0x20 +) + +type sysKernelSockaddrStorage struct { + Family uint16 + X__data [126]uint8 +} + +type sysSockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type sysInet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type sysIPv6Mtuinfo struct { + Addr sysSockaddrInet6 + Mtu uint32 +} + +type sysIPv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type sysIPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type sysGroupReq struct { + Interface uint32 + Group sysKernelSockaddrStorage +} + +type sysGroupSourceReq struct { + Interface uint32 + Group sysKernelSockaddrStorage + Source sysKernelSockaddrStorage +} + +type sysICMPv6Filter struct { + Data [8]uint32 +} + +type sysSockFProg struct { + Len uint16 + Pad_cgo_0 [2]byte + Filter *sysSockFilter +} + +type sysSockFilter struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} diff --git a/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/golang.org/x/net/publicsuffix/gen.go index add1c2e4..a2d49952 100644 --- a/vendor/golang.org/x/net/publicsuffix/gen.go +++ b/vendor/golang.org/x/net/publicsuffix/gen.go @@ -420,7 +420,7 @@ var children=[...]uint32{ fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n", c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType)) } else { - fmt.Fprintf(w, "0x%08x,\n", c) + fmt.Fprintf(w, "0x%x,\n", c) } } fmt.Fprintf(w, "}\n\n") @@ -560,7 +560,7 @@ func printNode(w io.Writer, n *node) error { nodeTypeStr(c.nodeType), icannStr(c.icann), c.label, ) } else { - fmt.Fprintf(w, "0x%08x,\n", encoding) + fmt.Fprintf(w, "0x%x,\n", encoding) } } return nil diff --git a/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/golang.org/x/net/publicsuffix/table.go index 7649b28f..00fa1ef5 100644 --- a/vendor/golang.org/x/net/publicsuffix/table.go +++ b/vendor/golang.org/x/net/publicsuffix/table.go @@ -2,7 +2,7 @@ package publicsuffix -const version = "publicsuffix.org's public_suffix_list.dat, git revision ea9f4f9c51f5bfc5c85a41a5637ab671c07c542a (2016-05-31T18:30:56Z)" +const version = "publicsuffix.org's public_suffix_list.dat, git revision fb4a6bce72a86feaf6c38f0a43cd05baf97a9258 (2016-07-07T00:50:50Z)" const ( nodesBitsChildren = 9 @@ -26,439 +26,441 @@ const ( const numTLD = 1552 // Text is the combined text of all labels. -const text = "bievatmallorcadaquesamsunglassassinationalheritagematsubarakawag" + - "oebifukagawalmartatsunomutashinainuyamanouchikuhokuryugasakitash" + - "iobarabihorologyusuisservecounterstrikebikedagestangeorgeorgiabi" + - "lbaogakievenesandvikcoromantovalle-d-aostatoilomzansimagicasadel" + - "amonedavvenjargapartmentsanfranciscofreakunemurorangeiseiyoichir" + - "opracticaseihichisobetsuitaipeiheijinvestmentsangobillustrationi" + - "nohekinannestadrangedalorenskogliwicebiobirdartcenterprisesakiko" + - "naircraftraeumtgeradealstahaugesundrivelandrobaknoluoktagajoboji" + - "s-a-candidatebirkenesoddtangenovaravennagatorogersvpalanakhodkan" + - "anporovnobirthplacebjarkoyuuconnectattoolsztynsettlersanjotaxihu" + - "aninomiyakonojoshkar-olayangroupaleobjerkreimdbalatinorddalimano" + - "warudastronomydissentargets-itargi234bjugnieznordlandunloppacifi" + - "casertairablockbusternidunsagaeroclubmedecincinnationwidealerblo" + - "ombergbauernrtgoryuzawabloxcmsannanirasakis-a-catererbluedaplier" + - "neuesannohelplfinancialotenkawabmoattachmentsanokasumigaurawa-ma" + - "zowszexboxenapponazure-mobilebmsantabarbarabmwegroweibolzanordre" + - "-landupontariobnpparibaselburglobalashovhachinohedmarkhangelskas" + - "uyakutiabomloansantacruzsantafedextraspace-to-rentalstomakomaiba" + - "rabondurbanamexhibitionishiazais-a-celticsfanishigotsukisofukush" + - "imarnardalottebonnishiharabookinglobodoes-itverranzanquannefrank" + - "furtjeldsundurhamburglogoweirbootsanukis-a-chefarmsteadvrcambrid" + - "gestonewyorkshiredumbrellajollamericanexpressexyzgorzeleccologne" + - "wportlligatewayuzhno-sakhalinskaszubyboschaefflerdalottokorozawa" + - "bostikatowicebostonakijinsekikogentingloppenzaogashimadachicagob" + - "oatsaotomeloyalistockholmestrandvrdnsfor-better-thandabotanicalg" + - "ardenishiizunazukis-a-conservativefsncfdwgmbhartiffanynysafetysf" + - "jordyndns-ipalermomasvuotnakatombetsupplybotanicgardenishikataka" + - "zakis-a-cpadoval-daostavalleybotanybouncemerckatsushikabeeldenge" + - "luidyndns-mailouvrepairbusantiquest-a-la-maisondre-landebusiness" + - "ebyklefrakkestadyndns-office-on-the-webcampobassociatesapodhalew" + - "ismillerbounty-fullensakerrypropertiesapporoboutiquebecngminakam" + - "ichigangwonishikatsuragithubusercontentjmaxxxfinitybozentsujiieb" + - "radescorporationishikawazukaneyamaxunjargabrandywinevalleybrasil" + - "iabresciabrindisibenikebristolgamvikatsuyamasfjordenishimerabrit" + - "ishcolumbialowiezaganishinomiyashironobroadcastleclercasinordrei" + - "sa-geekaufenishinoomotegotvalleaostavernishinoshimatteledatabase" + - "ballooningmodenakanotoddenishiokoppegardyndns-picsaratovalled-ao" + - "stavropolitiendabroadwaybroke-itjomebrokerbronnoysundyndns-remot" + - "egildeskalmykiabrothermesaverdedyn-o-saurechtrainingmxjaworznowt" + - "valledaostakkofuelowiczest-le-patrondheimperiabrumunddalucaniabr" + - "unelblagdenesnaaseralingenkainanaejrietisalatinabenoboribetsucks" + - "ardegnamsosnowiecateringebudejjuedischesapeakebayernurembergreta" + - "kamatsukawabrusselsardiniabruxellesarluccapitalonewjerseybryansk" + - "jervoyagebryneustarhubalestrandabergamoarekehimejibestadiscovery" + - "okamikawanehonbetsurutaharaugustowadaegubs3-ap-southeast-2busker" + - "udinewhampshirecipesaro-urbino-pesarourbinopesaromamurogawalterb" + - "uzenishitosashimizunaminamiashigarabuzzgradyndns-servercellikes-" + - "piedmontblancomeeresarpsborgrimstadyndns-weberlincolnishiwakis-a" + - "-cubicle-slavellinotteroybwfarsundyndns-wikinderoybzhitomirkutsk" + - "leppalmspringsakercompute-1computerhistoryofscience-fictioncomse" + - "curitytacticsbschokoladencondoshichinohealthcareerscholarshipsch" + - "ooluzernconferenceconstructionconsuladoharuhrconsultanthropology" + - "consultingvollvivano-frankivskharkivgucciprianiigataitogojomedio" + - "-campidano-mediocampidanomediocontactoyosatoyokawacontemporaryar" + - "teducationalchikugokaseljeffersoncontractorskenconventureshinode" + - "sashibetsuikimobetsuliguriacookingchannelveruminamidaitomangotem" + - "baixadacoolkuszippodlasiellakasamatsudovre-eikercooperaunitelevi" + - "sioncopenhagencyclopedichelyabinskodjeepilepsydneycorsicagliarid" + - "agawarszawashingtondclkharkovallee-aosteroycorvettemasekhersonco" + - "senzakopanerairforcecostumedizinhistorischeschulezajskhmelnitski" + - "yamashikecouchpotatofrieschwarzgwangjuifminamiechizencouncilcoup" + - "onschweizjcbnlcoursesciencecentersciencehistorycq-acranbrookuwan" + - "alyticscientistor-elvdalcreditcardcreditunioncremonashorokanaiec" + - "rewiiheyaizuwakamatsubushikusakadogawacricketrzyncrimeacrotonews" + - "papercrownprovidercrscjohnsoncruisescotlandcuisinellahppiacenzam" + - "amibuilderscrapper-siteculturalcentertainmentoyotaris-a-doctoray" + - "cuneocupcakecxn--1ctwolominamatamayukis-a-financialadvisor-aurda" + - "lcymruovatoyotomiyazakis-a-geekgalaxycyonabarussiacyouthdfcbankz" + - "lgujolsterfiguerestaurantoyourafilateliafilminamifuranofinalfina" + - "ncefineartservegame-serverisignfinlandfinnoyfirebaseapparaglidin" + - "guovdageaidnudmurtiafirenzefirestonexuscultureggio-calabriafirmd" + - "aleirfjordfishingolffanservehalflifestylefitjarqhachiojiyahikobe" + - "atservehttparisor-fronfitnessettlementoystre-slidrettozawafjaler" + - "flesbergushikamifuranosegawaflickragerotikamakurazakinkobayashik" + - "shacknetnedalflightservehumourflirumannorthwesternmutualfloginto" + - "hmansionserveirchernihivanovosibirskydivingripefloraflorenceflor" + - "idafloristanohatakahamanxn--1lqs71dfloromskoguchikuzenflowerserv" + - "eminecraftozsdeflsmidthruhereggio-emilia-romagnakanojohanamakino" + - "haraflynnhubalsfjordishakotankarmoyomitanobiraurskog-holandrover" + - "halla-speziaeroportalabamagasakishimabarackmaze12fndfoodnetworks" + - "hoppingxn--1qqw23afor-ourfor-someetranbyfor-theaterforexrothachi" + - "rogatakamoriokamikitayamatotakadaforgotdnservemp3utilitiesquarez" + - "zoologicalvinklein-addrammenuernbergdyniabcn-north-1kappleaseati" + - "ng-organicbcg12000emmafanconagawakayamadridvagsoyericsson-aptibl" + - "eangaviikadenaamesjevuemielno-ip6forli-cesena-forlicesenaforlike" + - "scandyndns-at-workinggrouparliamentrani-andria-barletta-trani-an" + - "driaforsaleirvikhvanylveniceforsandasuoloftraniandriabarlettatra" + - "niandriafortmissoulan-udegreefortworthadanoshiroomuraforuminamii" + - "selectranoyfosneservep2parmafotransportrapaniimimatakatsukis-a-g" + - "reenfoxn--2m4a15efreeboxostrowiechernivtsiciliafreemasonryfreibu" + - "rgzparocherkasyzrankoshigayaltaikis-a-gurufcfanfreightcmwildlife" + - "djejuegoshikiminokamoenairlinedre-eikerfreseniusdecorativeartser" + - "vepicservequakefribourgfriuli-v-giuliafriuli-ve-giuliafriuli-veg" + - "iuliafriuli-venezia-giuliafriuli-veneziagiuliafriuli-vgiuliafriu" + - "liv-giuliafriulive-giuliafriulivegiuliafriulivenezia-giuliafriul" + - "iveneziagiuliafriulivgiuliafrlfroganservesarcasmatartanddesignfr" + - "ognfrolandfrom-akrehamnfrom-alfrom-arfrom-azwilliamhillfrom-cape" + - "townnews-stagingfrom-collectionfrom-ctravelchannelfrom-dchernovt" + - "sykkylvenetogitsuldalukowhalingriwataraidyndns-workisboringronda" + - "rfrom-dell-ogliastrakhanawawinbaltimore-og-romsdalimoliserniaust" + - "evollavangenativeamericanantiques3-eu-central-1from-flanderservi" + - "cesettsurfastlyfrom-gausdalfrom-higashiagatsumagoiparsevastopole" + - "from-iafrom-idfrom-ilfrom-incheonfrom-ksevenassisicilyfrom-kyoto" + - "betsumidatlantichiryukyuragifudaigodoesntexistanbullensvanguardy" + - "nnsarufutsunomiyawakasaikaitakoelnissedaluroyfrom-lanbibaidarfro" + - "m-maorivnefrom-mdfrom-megurorostrowwlkpmgfrom-microsoftbanklabud" + - "habikinokawabarthadselfipartis-a-hard-workerfrom-mnfrom-mochizuk" + - "irafrom-msewindmillfrom-mtnfrom-nchitachinakagawatchandclockazim" + - "ierz-dolnyfrom-ndfrom-nefrom-nhktravelersinsurancefrom-njcpartne" + - "rsfranziskanerdpolicefrom-nminamiizukamitsuefrom-nvaolbia-tempio" + - "-olbiatempioolbialystokkemerovodkagoshimakeupowiathletajimabaria" + - "kepnoipirangalsacefrom-nyfrom-ohkurafrom-oketohnoshoooshikamaish" + - "imofusartshangrilangevagrarboretumbriamallamaintenancechirealtor" + - "landfrom-orfrom-paderbornfrom-pratohobby-sitexasdaburyatiaarpart" + - "sharis-a-hunterfrom-ris-a-knightrdfrom-schoenbrunnfrom-sdniprope" + - "trovskypescaravantaafrom-tnfrom-txn--30rr7yfrom-utazuerichardlil" + - "lehammerfest-mon-blogueurovisionfrom-vaksdalfrom-vtrentino-a-adi" + - "gefrom-wafrom-wielunnerfrom-wvareservebeerfrom-wyfrosinonefrosta" + - "lowa-wolawafroyahabaghdadultrentino-aadigefstcgroupartyfujiidera" + - "fujikawaguchikonefujiminohtawaramotoineppugliafujinomiyadafujiok" + - "ayamarburgfujisatoshonairportland-4-salernogatachikawakuyabukick" + - "s-assedichitosetogliattiresasayamafujisawafujishiroishidakabirat" + - "oridellogliastraderfujitsurugashimamateramodalenfujixeroxn--32vp" + - "30haebaruminamimakis-a-landscaperugiafujiyoshidafukayabeardubaid" + - "uckdnsdojoburgfukuchiyamadafukudominichloefukuis-a-lawyerfukumit" + - "subishigakirkenesharpasadenaklodzkodairafukuokazakirovogradoyfuk" + - "uroishikarikaturindalfukusakiryuohagakhanamigawafukuyamagatakaha" + - "rulsandoyfunabashiriuchinadafunagatakahashimamakisarazurewebsite" + - "shikagamiishibukawafunahashikamiamakusatsumasendaisennangonoheji" + - "s-a-liberalfundaciofuoiskujukuriyamarcheapassagenshawaiijimarumo" + - "rimachidafuosskoczowindowshellaspeziafurnitureggiocalabriafurubi" + - "raquarellebesbyglandfurudonostiafurukawairtelecityeatshimokawafu" + - "sodegaurafussaikishiwadafutabayamaguchinomigawafutboldlygoingnow" + - "here-for-moregontrailroadfuttsurugiminamiminowafvgfyis-a-liberta" + - "rianfylkesbiblackfridayfyresdalhannovarggatrentino-alto-adigehan" + - "yuzenhapmirhappoumuenchenhareidsbergenharstadharvestcelebrationh" + - "asamarahasaminami-alpssells-for-ulvikmshimonosekikawahashbanghas" + - "udahasvikokonoehatogayahoohatoyamazakitahatakanabeautydalhatsuka" + - "ichiharahattfjelldalhayashimamotobuildinghazuminobusells-itrenti" + - "no-altoadigehboehringerikehelsinkitahiroshimarshallstatebankolob" + - "rzegersundhembygdsforbundhemneshimosuwalkis-a-musicianhemsedalhe" + - "rokussldheroyhgtvaroyhigashichichibungotakadatinghigashihiroshim" + - "anehigashiizumozakitakamiizumisanofidelityumenhigashikagawahigas" + - "hikagurasoedahigashikawakitaaikitakatakanezawahigashikurumeiwama" + - "rugame-hostinghigashimatsushimarinehigashimatsuyamakitaakitadait" + - "oigawahigashimurayamalatvuopmidoris-a-nascarfanhigashinarusellsy" + - "ourhomeipaviancarbonia-iglesias-carboniaiglesiascarboniahigashin" + - "ehigashiomihachimanchesterhigashiosakasayamamotorcycleshimotsuke" + - "higashishirakawamatakaokamikoaniikappulawyhigashisumiyoshikawami" + - "namiaikitakyushuaiahigashitsunotogawahigashiurausukitamidsundhig" + - "ashiyamatokoriyamanakakogawahigashiyodogawahigashiyoshinogaris-a" + - "-nurseoulminamisanrikubetsupplieshimotsumahiraizumisatokamachipp" + - "ubetsubetsugarunusualpersonhirakatashinagawahiranais-a-painterac" + - "tivegarsheis-a-patsfanhirarahiratsukagawahirayaitakarazukamimine" + - "rshinichinanhistorichouseshinjournalismailillesandefjordhitachio" + - "miyaginankokubunjis-a-personaltrainerhitachiotagooglecodespotren" + - "tino-s-tirollagrigentomologyhitoyoshimifunehitradinghjartdalhjel" + - "melandholeckobierzyceholidayhomelinuxn--3bst00minamitanehomesecu" + - "ritymaceratakasagopocznortonsberghomesecuritypccwinnershinjukuma" + - "nohomesensembokukitamotosumitakaginowaniihamatamakawajimaritimod" + - "ellinghomeunixn--3ds443ghondahonefosshinkamigotoyohashimotottori" + - "s-a-photographerokuappfizerhoneywellhongorgehonjyoitakasakitanak" + - "agusukumoduminamiuonumatsumaebashimodatehornindalhorseminehorten" + - "dofinternetrentino-stirolhoteleshinshinotsurgeonshalloffamemerge" + - "ncyberlevagangaviikanonjis-a-playerhotmailhoyangerhoylandetroits" + - "komaganehumanitieshinshirohurdalhurumajis-a-republicancerresearc" + - "haeologicaliforniahyllestadhyogoris-a-rockstarachowicehyugawarah" + - "yundaiwafunehzchonanbugattipschmidtre-gauldaluxembourgrongaiwcho" + - "seirouterjgorajlchoshibuyachiyodavvesiidazaifuefukihaborokunohea" + - "lth-carereformitakeharajlljmpgfoggiajnjelenia-gorajoyokaichibahc" + - "avuotnagaraholtalenjpmorganjpnchoyodobashichikashukujitawarajprs" + - "hioyamemorialjuniperjurkristiansundkrodsheradkrokstadelvaldaosta" + - "rostwodzislawioshirakoenigkryminamiyamashirokawanabellevuelosang" + - "elesjaguarchitecturebungoonomichinomiyakekumatorinokumejimasudak" + - "umenanyokkaichirurgiens-dentistes-en-francekunisakis-an-accounta" + - "ntshintokushimakunitachiarailwaykunitomigusukumamotoyamassa-carr" + - "ara-massacarraramassabunkyonanaoshimageandsoundandvisionkunneppu" + - "pharmacyshiranukanmakiwakunigamihamadakunstsammlungkunstunddesig" + - "nkuokgrouphiladelphiaareadmyblogsitekureitrentinoa-adigekurganku" + - "robelgorodeokurogimilitarykuroisoftwarendalenugkuromatsunais-an-" + - "actorkurotakikawasakis-an-actresshintomikasaharakurskommunekushi" + - "rogawakustanais-an-anarchistoricalsocietykusupersportrentinoaadi" + - "gekutchanelkutnokuzbassnillfjordkuzumakis-an-artistjohnkvafjordk" + - "valsundkvamfamberkeleykvanangenkvinesdalkvinnheradkviteseidskogk" + - "vitsoykwpspiegelkyowariasahikawamisugitokuyamatsusakahoginozawao" + - "nsenmitourismolanciamitoyoakemiuramiyazumiyotamanomjondalenmlbfa" + - "nmonmouthaibarakisosakitagawamonstermonticellombardiamondshiraoi" + - "zumizakis-bymontrealestatefarmequipmentrentinoalto-adigemonza-br" + - "ianzaporizhzheguris-certifiedekakegawamonza-e-della-brianzaporiz" + - "hzhiamonzabrianzapposhiraokannamiharumonzaebrianzaptokyotangotpa" + - "ntheonsitextileitungsenmonzaedellabrianzaramoparachutingmordovia" + - "jessheiminanomoriyamatsushigemoriyoshiokamogawamormoneymoroyamat" + - "suuramortgagemoscowitdkomorotsukamisunagawamoseushistorymosjoenm" + - "oskeneshiratakahagivingmosshishikuis-foundationmosvikomvuxn--3e0" + - "b707emoviemovistargardmtpchristmasakikuchikuseikarugaulardaluxur" + - "ymtranakatsugawamuenstermugithubcloudusercontentrentinoaltoadige" + - "muikanagawamukochikushinonsenergymulhouservebbshisognemultichoic" + - "emunakatanemuncieszynmuosattemuphilatelymurmanskongsbergmurotorc" + - "raftrentinos-tirolmusashimurayamatsuzakis-gonemusashinoharamusee" + - "trentinostirolmuseumverenigingmutsuzawamutuellevangermydshisuifu" + - "ettertdasnetzmyeffectrentinosud-tirolmyfritzmyftphilipsymykolaiv" + - "barclaycardstvedestrandiskstationatuurwetenschappenaumburgjovika" + - "rpaczeladz-2mymediapchromedicaltanissettaishinomakikugawatchesas" + - "katchewanggouvicenzamyokohamamatsudamypepostfoldnavyatkakudamats" + - "uemypetshitaramamyphotoshibahccavuotnagareyamalopolskanlandmypsx" + - "n--3oq18vl8pn36amysecuritycamerakermytis-a-bookkeepermincommbank" + - "omonomyvnchryslerpiagetmyiphoenixn--3pxu8kongsvingerpictetrentin" + - "osudtirolpictureshizukuishimogosenpiemontepilotshizuokanoyakagep" + - "inkoninjamisonpioneerpippupiszpittsburghofauskedsmokorsetagayase" + - "lls-for-lesscrappingulenpiwatepizzapkonskowolancashirehabmerplan" + - "etariuminnesotaketakayamatsumotofukeplantationplantshoujis-into-" + - "animelbourneplatformintelligenceplaystationplazaplchungbukchrist" + - "iansburgrossetouchijiwadeloittenrightathomegoodsassaris-a-democr" + - "atkmaxxn--11b4c3dynv6plombardyndns-blogdnsiskinkyknethnologyplum" + - "bingovtrentinosued-tirolplusterpmnpodzonepohlpointtoshimapokerpo" + - "krovskonsulatrobelaudibleborkdalpharmaciensnasaarlandpolkowicepo" + - "ltavalle-aostathellexuslivinghistorypomorzeszowithgoogleapisa-ho" + - "ckeynutrentinosuedtirolpordenonepornporsangerporsanguideltaiwana" + - "irguardporsgrunnanpoznanpraxis-a-bruinsfanprdpreservationpresidi" + - "oprgmrprimelhustkamitondabayashiogamagoriziaprincipeprivatizehea" + - "lthinsuranceprochowiceproductionshowaprofbsbxn--1lqs03nprogressi" + - "vegaskimitsubatamicable-modembetsukuis-into-carshinyoshitomiokan" + - "iepceprojectrentoyonakagyokutoyakokamishihoronobeokaminoyamatsur" + - "is-into-cartoonshiojirishirifujiedapromombetsupportrevisohughesh" + - "owtimetlifeinsurancepropertyprotectionprudentialpruszkowithyoutu" + - "bentleyprzeworskogptzpvtroandinosaurlandeshriramlidlugolekagamin" + - "ogiessengerdalcesienaplesigdalpwchungnamdalseidfjordyroyrvikingr" + - "oundhandlingroznypzqldqponqslgbtrogstadquicksytesilkonyvelolqvch" + - "urchasejnysowaspjelkavikosakaerodromegallupinbananarepublicartie" + - "reviewskrakoweddingjesdalindasiaustinnaturalhistorymuseumcentere" + - "pbodyndns-freebox-oskolegnicanonoichikawamisatogakushimotoganewh" + - "ollanddnskingjerdrumckinseyekaterinburgjerstadotsuruokamchatkame" + - "okameyamashinatsukigatakahatakaishimoichinosekigaharaetnagaivuot" + - "nagaokakyotambabydgoszczecinemailavagiske164spreadbettingspydebe" + - "rgsrlsrtromsojavald-aostarnbergsrvdonskoseis-a-teacherkassymante" + - "chnologystoragestordalstorenburgstorfjordstpetersburgstreamsterd" + - "amnserverbaniastudiostudyndns-homeftpaccessimple-urlstuff-4-sale" + - "stufftoread-booksnesirdalstuttgartrusteesurnadalsurreysusakis-lo" + - "stre-toteneis-a-soxfansusonosuzakanumazurysuzukanzakiwiensuzukis" + - "-not-certifiedogawarabikomaezakirunorilskomakiyosatokigawasvalba" + - "rdudinkakamigaharasveiosvelvikosherbrookegawasvizzeraswedenswidn" + - "icargodaddyndns-at-homednshomebuiltrvenneslaskerrylogisticslings" + - "wiebodzindianmarketingswiftcoveronaritakurashikis-saveducatorahi" + - "meshimakanegasakindleikangerswinoujscienceandhistoryswisshikis-s" + - "lickomatsushimashikiyosemitevestnesnzvestre-slidreamhostersokanr" + - "avestre-totennishiawakuravestvagoyvevelstadvibo-valentiavibovale" + - "ntiavideovillaskoyabearalvahkihokumakogenglandvinnicarriervinnyt" + - "siavipsinaapphotographysiovirginiavirtualvirtuelvisakatakinouevi" + - "staprinternationalfirearmsokndalviterboltrysiljan-mayenvivoldavl" + - "adikavkazanvladimirvladivostokaizukarasuyamazoevlogvolkenkunders" + - "eaportulanslupskopervikomitamamuravolkswagentsolarssonvologdansk" + - "ostromahachijorpelandvolvolgogradvolyngdalvoronezhytomyrvossevan" + - "genvotevotingvotoyonezawavrnworse-thangglidingwowiwatsukiyonowru" + - "zhgorodoywritesthisblogsytewroclawloclawekosugewtchuvashiawtfbx-" + - "oslodingenwuozuwwworldwzmiuwajimaxn--4it168dxn--4it797kotohirado" + - "mainsureisenxn--4pvxsolognexn--54b7fta0ccitadeliveryggeelvinckdd" + - "ielddanuorrikuzentakatajimicrolightingrpamperedchefashionisshing" + - "ugexn--55qw42gxn--55qx5dxn--5js045dxn--5rtp49citicatholicdn77-ss" + - "lattuminamibosogndalucernexn--5rtq34kotouraxn--5su34j936bgsgxn--" + - "5tzm5gxn--6btw5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264ci" + - "vilaviationiyodogawaxn--80adxhksolundbeckosaigawaxn--80ao21axn--" + - "80aqecdr1axn--80asehdbarclays3-us-west-2xn--80aswgxn--80audnedal" + - "nxn--8ltr62kouhokutamakizunokunimilanoxn--8pvr4uxn--8y0a063axn--" + - "90a3academyactivedirectoryazannakadomari-elasticbeanstalkounosun" + - "ndalxn--90aishobaraomoriguchiharagusabaerobaticketsaritsynologye" + - "ongnamegawakeisenbahnxn--90azhair-surveillancexn--9dbhblg6dietci" + - "mmobilienxn--9dbq2axn--9et52uxn--9krt00axn--andy-iraxn--aroport-" + - "byanagawaxn--asky-iraxn--aurskog-hland-jnbarefootballangenoamish" + - "irasatochigiftsakuraibigawaustraliaisondriodejaneirochestereport" + - "arnobrzegyptianaturalsciencesnaturelles3-eu-west-1xn--avery-yuas" + - "akegawaxn--b-5gaxn--b4w605ferdxn--bck1b9a5dre4civilisationrwhosw" + - "hokksundxn--bdddj-mrabdxn--bearalvhki-y4axn--berlevg-jxaxn--bhca" + - "vuotna-s4axn--bhccavuotna-k7axn--bidr-5nachikatsuuraxn--bievt-0q" + - "a2xn--bjarky-fyanaizuxn--bjddar-ptamboversaillesnoasaitamatsukur" + - "is-into-gamessinashikitaurayasudaxn--blt-elaborxn--bmlo-grainger" + - "xn--bod-2naroyxn--brnny-wuaccident-investigationjukudoyamagadanc" + - "ebetsukubabia-goracleaningatlantabusebastopologyeonggiehtavuoatn" + - "adexeterimo-i-ranagahamaroygardendoftheinternetflixilovecollegef" + - "antasyleaguernseyxn--brnnysund-m8accident-preventionlineat-urlxn" + - "--brum-voagatunesmolenskoryolasitexn--btsfjord-9zaxn--c1avgxn--c" + - "2br7gxn--c3s14misasaguris-an-entertainerxn--cck2b3bargainstitute" + - "lefonicafederationaustdalinkaruizawaustrheimatunduhrennesoyokosu" + - "kareliancebinorfolkebiblegoldpoint2thisayamanashiibadajozorahkke" + - "ravjudygarlandds3-external-1xn--cg4bkis-uberleetrentino-sudtirol" + - "xn--ciqpnxn--clchc0ea0b2g2a9gcdn77-securecreationxn--comunicaes-" + - "v6a2oxn--correios-e-telecomunicaes-ghc29axn--czr694barreauctiona" + - "val-d-aosta-valleyonagoyauthordalandroidgcahcesuolocalhistorybni" + - "kahokutoeigersundigitalaziobihirosakikamijimagroks-thisamitsukem" + - "buchikumagayagawakkanaibetsubamericanfamilydscloudappspotenzachp" + - "omorskienebakkeshibechambagriculturennebudapest-a-la-masionthewi" + - "fiat-band-campaniabogadocscbggfareastcoastaldefence-burgjemnes3-" + - "ap-northeast-1xn--czrs0tunkoshimizumakiyosumydrobofagexn--czru2d" + - "xn--czrw28barrel-of-knowledgeologyonaguniversityoriikarumaifarme" + - "rseinextdirectarumizusawautomotivecodynaliascoli-picenord-aurdal" + - "ipayufuchukotkafjordiscountysvardolls3-external-2xn--d1acj3barre" + - "ll-of-knowledgeometre-experts-comptablesakyotanabeneventodayukuh" + - "ashimojibmditchyouripagefrontappagespeedmobilizerobninskasaokami" + - "satokashikitchenavigationavuotnakayamatta-varjjatatamotorsalange" + - "nayoroceanographicsalondonetskashibatakashimaseratiinetatarstanf" + - "lfanfshostrodawarautoscanadaejeonbukariyakumoldevents3-fips-us-g" + - "ov-west-1xn--d1alfaromeoxn--d1aturystykarasjokoshunantokonamegat" + - "akatoris-a-techietis-a-socialistmeindianapolis-a-bloggerxn--d5qv" + - "7z876civilizationxn--davvenjrga-y4axn--djrs72d6uyxn--djty4kouyam" + - "ashikokuchuoxn--dnna-grajewolterskluwerxn--drbak-wuaxn--dyry-ira" + - "xn--e1a4civilwarmanagementmpanamaxn--eckvdtc9dxn--efvn9solutions" + - "imbirskooris-a-studentalxn--efvy88hakatanotaireshimokitayamaxn--" + - "ehqz56nxn--elqq16hakodatexn--estv75gxn--eveni-0qa01gaxn--f6qx53a" + - "xn--fct429kouzushimasoyxn--fhbeiarnxn--finny-yuaxn--fiq228c5hsom" + - "axn--fiq64bashkiriaveroykeniwaizumiotsukumiyamazonawsadodgemolog" + - "icallyngenvironmentalconservationaturbruksgymnaturhistorisches3-" + - "sa-east-1xn--fiqs8somnarashinoxn--fiqz9sooxn--fjord-lraxn--fjq72" + - "0axn--fl-ziaxn--flor-jraxn--flw351exn--fpcrj9c3dxn--frde-grandra" + - "pidsopotromsakakinokiaxn--frna-woaraisaijosoyrovigorlicexn--frya" + - "-hraxn--fzc2c9e2claimsaudaxn--fzys8d69uvgmailxn--g2xx48clickfhsk" + - "habarovskhakassiaxn--gckr3f0fbxostrolekaluganskhmelnytskyivallee" + - "aosteigenxn--gecrj9clinicheltenham-radio-openair-traffic-control" + - "leyxn--ggaviika-8ya47hakonexn--gildeskl-g0axn--givuotna-8yandexn" + - "--42c2d9axn--gjvik-wuaxn--gk3at1exn--gls-elacaixaxn--gmq050is-ve" + - "ry-badaddjamalborkangerxn--gmqw5axn--h-2failxn--h1aeghakubankmps" + - "pacekitagatakasugais-a-linux-useranishiaritabashikaoirminamiogun" + - "icomcastresistancexn--h2brj9cliniquenoharaxn--hbmer-xqaxn--hcesu" + - "olo-7ya35basilicataniavocatanzarowebhoppdalillyokotebizenakamura" + - "tajirissagamiharamusementarantours3-ap-northeast-2xn--hery-iraxn" + - "--hgebostad-g3axn--hmmrfeasta-s4acctuscanyxn--hnefoss-q1axn--hob" + - "l-iraxn--holtlen-hxaxn--hpmir-xqaxn--hxt814exn--hyanger-q1axn--h" + - "ylandet-54axn--i1b6b1a6a2exn--imr513nxn--indery-fyaotsurgutsirac" + - "usaitotalxn--io0a7is-very-evillagexn--j1aefermobilyxn--j1amhakui" + - "s-a-llamarylhursteinkjerusalembroideryxn--j6w193gxn--jlq61u9w7ba" + - "sketballfinanzgoravoues3-us-gov-west-1xn--jlster-byaroslavlaande" + - "renxn--jrpeland-54axn--jvr189misawaxn--k7yn95exn--karmy-yuaxn--k" + - "brq7oxn--kcrx77d1x4axn--kfjord-iuaxn--klbu-woaxn--klt787dxn--klt" + - "p7dxn--kltx9axn--klty5xn--45brj9circlegallocus-east-1xn--koluokt" + - "a-7ya57hakusandiegoodyearthagebostadxn--kprw13dxn--kpry57dxn--kp" + - "u716ferraraxn--kput3is-very-goodhandsonxn--krager-gyasakaiminato" + - "yonoxn--kranghke-b0axn--krdsherad-m8axn--krehamn-dxaxn--krjohka-" + - "hwab49jetztrentino-suedtirolxn--ksnes-uuaxn--kvfjord-nxaxn--kvit" + - "sy-fyasugis-very-nicexn--kvnangen-k0axn--l-1fairwindsor-odalxn--" + - "l1accentureklamborghiniizaxn--laheadju-7yasuokaratexn--langevg-j" + - "xaxn--lcvr32dxn--ldingen-q1axn--leagaviika-52batochiokinoshimalv" + - "ikashiharaxasnesoddenmarkets3-ap-southeast-1xn--lesund-huaxn--lg" + - "bbat1ad8jevnakershusgardenxn--lgrd-poacoachampionshiphoptobamaga" + - "zinebraskaunbieidsvollxn--lhppi-xqaxn--linds-pramericanartushuis" + - "sier-justicexn--lns-qlanxessor-varangerxn--loabt-0qaxn--lrdal-sr" + - "axn--lrenskog-54axn--lt-liaclintonoshoesauheradxn--lten-granexn-" + - "-lury-iraxn--mely-iraxn--merker-kuaxn--mgb2ddesorfoldxn--mgb9awb" + - "ferrarittoguraxn--mgba3a3ejtuvalle-daostavangerxn--mgba3a4f16axn" + - "--mgba3a4franamizuholdingsmileksvikozagawaxn--mgba7c0bbn0axn--mg" + - "baakc7dvferreroticapebretonamiasakuchinotsuchiurakawassamukawata" + - "ricohdatsunanjoetsuwanouchikujogaszkoladbrokeserveexchangexn--mg" + - "baam7a8haldenxn--mgbab2bdxn--mgbai9a5eva00batsfjordivtasvuodnaha" + - "rimaniwakuratevadsoccertificationhlfanhsaltdalinzaiitatebayashij" + - "onawatemrhcloudcontrolledivttasvuotnakaiwamizawaxn--mgbai9azgqp6" + - "jewelryxn--mgbayh7gpaduaxn--mgbb9fbpobanazawaxn--mgbbh1a71exn--m" + - "gbc0a9azcgxn--mgbca7dzdoxn--mgberp4a5d4a87gxn--mgberp4a5d4arxn--" + - "mgbi4ecexposedxn--mgbpl2fhvalerxn--mgbqly7c0a67fbclothingruexn--" + - "mgbqly7cvafredrikstadtvsorreisahayakawakamiichikaiseis-leetrenti" + - "no-sud-tirolxn--mgbt3dhdxn--mgbtf8flatangerxn--mgbtx2bauhauspost" + - "s-and-telecommunicationsupdatelekommunikationikiiyamanobeauxarts" + - "andcraftsalvadordalibabaikaliszczytnord-odalvdalaskanittedallasa" + - "lleasinglesalzburgladelmenhorstalbansamegawaxn--mgbx4cd0abbottxn" + - "--mix082fetsundxn--mix891fgunmarriottoyotsukaidownloadxn--mjndal" + - "en-64axn--mk0axindustriesteambulancexn--mk1bu44cloudfrontdoorxn-" + - "-mkru45is-very-sweetrentino-sued-tirolxn--mlatvuopmi-s4axn--mli-" + - "tlapyatigorskozakis-a-therapistoiaxn--mlselv-iuaxn--moreke-juaxn" + - "--mori-qsakuhokkaidontexisteingeekpnxn--mosjen-eyatominamiawajik" + - "is-with-thebandoomdnsaliascolipicenord-frontierxn--mot-tlaquilan" + - "casterxn--mre-og-romsdal-qqbbcartoonartdecoffeedbackashiwaraxn--" + - "msy-ula0halsaintlouis-a-anarchistoireggioemiliaromagnakasatsunai" + - "rtraffichocolatelemarkazoxn--mtta-vrjjat-k7afamilycompanycloudfu" + - "nctionsavannahgaxn--muost-0qaxn--mxtq1misconfusedxn--ngbc5azdxn-" + - "-ngbe9e0axn--ngbrxn--45q11circuscountryestateofdelawaredstonewme" + - "xicoldwarmiamiastaplesatxn--1ck2e1balsanagochihayaakasakawaharau" + - "malselvendrellimitedunetbankarlsoyokozemersongdalenviknakaniikaw" + - "atanaguraukraanghkebinagisochildrensgardenasushiobarabruzzoology" + - "eongbuk-uralsk12xn--nit225kppspbarcelonagasakijobserverdalindesn" + - "es3-us-west-1xn--nmesjevuemie-tcbajddarchaeologyxn--nnx388axn--n" + - "odessakuragawaxn--nqv7fs00emaxn--nry-yla5gxn--ntso0iqx3axn--ntsq" + - "17gxn--nttery-byaeserveblogspotxn--nvuotna-hwaxn--nyqy26axn--o1a" + - "chattanooganore-og-uvdalxn--o3cw4hammarfeastafricamagichofunator" + - "ientexpressaseboknowsitallutskazunoxn--od0algxn--od0aq3bbtateshi" + - "nanomachintaijinfinitinfolldalipetskashiwazakiyokawaraxn--ogbpf8" + - "flekkefjordxn--oppegrd-ixaxn--ostery-fyatsukaratsuginamikatagami" + - "hoboleslawiecntoyookarasjohkamiokaminokawanishiaizubangexn--osyr" + - "o-wuaxn--p1acfidonnakamagayachtserveftpanasonichernigovernmentjx" + - "n--0trq7p7nnissandnessjoenissayokoshibahikariwanumataketomisatom" + - "skautokeinoxn--p1aisleofmandalxn--pbt977colonialwilliamsburguita" + - "rsaves-the-whalessandria-trani-barletta-andriatranibarlettaandri" + - "axn--pgbs0dhlxn--porsgu-sta26fieldxn--pssu33lxn--pssy2uxn--q9jyb" + - "4coloradoplateaudioxn--qcka1pmcdonaldsortlandxn--qqqt11mishimats" + - "unoxn--qxamurskiptveterinairealtychyattorneyagawalbrzycharternop" + - "ilawalesundxn--rady-iraxn--rdal-poaxn--rde-ularvikrasnodarxn--rd" + - "y-0nabarissmarterthanyounzenxn--rennesy-v1axn--rhkkervju-01aflak" + - "stadaokagakibichuoxn--rholt-mragowoodsidexn--rhqv96gxn--rht27zxn" + - "--rht3dxn--rht61exn--risa-5narusawaxn--risr-iraxn--rland-uuaxn--" + - "rlingen-mxaxn--rmskog-byatsushiroxn--rny31hamurakamigoriginshimo" + - "nitayanagivestbytomaritimekeepingxn--rovu88bbvacationswatch-and-" + - "clockerxn--rros-granvindafjordxn--rskog-uuaxn--rst-0narutomobell" + - "unordkappgafanpachigasakidsmynasperschlesischesorumisakis-an-eng" + - "ineeringxn--rsta-francaiseharaxn--ryken-vuaxn--ryrvik-byawaraxn-" + - "-s-1faitheguardianxn--s9brj9columbusheyxn--sandnessjen-ogbizhevs" + - "krasnoyarskommunalforbundxn--sandy-yuaxn--seral-lraxn--ses554gxn" + - "--sgne-gratangenxn--skierv-utazaskvolloabathsbcommunitysnesavona" + - "msskoganeis-a-designerimarylandxn--skjervy-v1axn--skjk-soaxn--sk" + - "nit-yqaxn--sknland-fxaxn--slat-5narviikanazawaxn--slt-elabourxn-" + - "-smla-hraxn--smna-gratis-a-bulls-fanxn--snase-nraxn--sndre-land-" + - "0cbremangerxn--snes-poaxn--snsa-roaxn--sr-aurdal-l8axn--sr-fron-" + - "q1axn--sr-odal-q1axn--sr-varanger-ggbeppubolognagasukepsonyoursi" + - "defenseljordiyurihonjournalistjordalshalsenikkoebenhavnikolaever" + - "bankasukabedzin-the-bandaikawachinaganoharamcoalaheadjudaicaaarb" + - "orteaches-yogasawaracingroks-theatreevje-og-hornnesamnangerxn--s" + - "rfold-byawatahamaxn--srreisa-q1axn--srum-grazxn--stfold-9xaxn--s" + - "tjrdal-s1axn--stjrdalshalsen-sqberndnpalacexn--stre-toten-zcbsou" + - "thcarolinazawaxn--t60b56axn--tckweatherchannelxn--tiq49xqyjewish" + - "artgalleryxn--tjme-hraxn--tn0agrinet-freaksouthwestfalenxn--tnsb" + - "erg-q1axn--tor131oxn--trany-yuaxn--trgstad-r1axn--trna-woaxn--tr" + - "oms-zuaxn--tysvr-vraxn--uc0atversicherungxn--uc0ay4axn--uist22ha" + - "ngoutsystemscloudcontrolappassenger-associationxn--uisz3gxn--unj" + - "rga-rtaobaokinawashirosatobishimaizurubtsovskjakdnepropetrovskie" + - "rvaapsteiermarkredirectmeldalxn--unup4yxn--uuwu58axn--vads-jraxn" + - "--vard-jraxn--vegrshei-c0axn--vermgensberater-ctbeskidynathomede" + - "potaruintuitateyamaxn--vermgensberatung-pwbestbuyshousesamsclubi" + - "ndalivornoceanographiquexn--vestvgy-ixa6oxn--vg-yiabbvieeexn--vg" + - "an-qoaxn--vgsy-qoa0jfkomforbamblebtimnetz-1xn--vgu402comobaraxn-" + - "-vhquvestfoldxn--vler-qoaxn--vre-eiker-k8axn--vrggt-xqadxn--vry-" + - "yla5gxn--vuq861betainaboxfordeatnuorockartuzyusuharaxn--w4r85el8" + - "fhu5dnraxn--w4rs40lxn--wcvs22dxn--wgbh1comparemarkerryhotelsaxox" + - "n--wgbl6axn--xhq521bielawallonieruchomoscienceandindustrynikonan" + - "tanangerxn--xkc2al3hye2axn--xkc2dl3a5ee0hannanmokuizumodernxn--y" + - "9a3aquariumissilelxn--yer-znarvikristiansandcatshirahamatonbetsu" + - "rgeryxn--yfro4i67oxn--ygarden-p1axn--ygbi2ammxn--4gbriminingxn--" + - "ystre-slidre-ujbiellaakesvuemieleccexn--zbx025dxn--zf0ao64axn--z" + - "f0avxn--4gq48lf9jeonnamerikawauexn--zfr164bieszczadygeyachimatai" + - "naioiraseeklogesuranceoddaxperiaxz" +const text = "biellaakesvuemieleccebieszczadygeyachimataipeigersundrangedalivo" + + "rnoddabievatmallorcafederationikonantanangerbifukagawalmartatesh" + + "inanomachintaijinfolldalomzansimagicasadelamonedatsunanjoetsuwan" + + "ouchikujogaszkoladbrokesamsclubindalorenskogliwicebihorologyusui" + + "sserveexchangebikedagestangeorgeorgiabilbaogakievenesamsunglobal" + + "ashovhachinohedmarkhangelskatowicebillustrationinohekinannestadr" + + "ivelandrobaknoluoktainaikawachinaganoharamcoalaheadjudaicable-mo" + + "dembetsukuintuitateyamabiomutashinainuyamanouchikuhokuryugasakit" + + "ashiobarabirdartcenterprisesakikonaircraftraeumtgeradealstahauge" + + "sundunloppacificaseihichisobetsuitairabirkenesoddtangenovaravenn" + + "agatorockartuzyuudmurtiabirthplacebjarkoyuzawabjerkreimdbalatino" + + "rdkappgafanpachigasakidsmynasperschlesisches3-sa-east-1bjugniezn" + + "ordre-landunsandvikcoromantovalle-d-aostatoilotenkawablockbuster" + + "nidupontariobloombergbauernrtatsunobloxcmsanfranciscofreakunemur" + + "orangeiseiyoichiropracticasertaishinomakikuchikuseikarugaulardal" + + "ottebluedaplierneuesangobmoattachmentsanjotattoolsztynsettlersan" + + "naninomiyakonojoshkar-olayangroupaleobmsannohelplfinancialottoko" + + "namegatakatorinvestmentsanokatsushikabeeldengeluidurbanamexhibit" + + "ionirasakis-a-candidatebmweirbnpparibaselburglobodoes-itverranza" + + "nquannefrankfurtaxihuanishiazais-a-catererbomloansantabarbarabon" + + "durhamburglogowfarmsteadvrcambridgestonewspaperbonnishigotsukiso" + + "fukushimaritimodenakanojohanamakinoharabookingloppenzaogashimada" + + "chicagoboatsantacruzsantafedextraspace-to-rentalstomakomaibarabo" + + "otsanukis-a-celticsfanishiharaboschaefflerdalouvreitgoryuzhno-sa" + + "khalinskatsuyamaseratis-a-chefarsundvrdnsfor-better-thandabostik" + + "aufenishiizunazukis-a-conservativefsncfdwgmbhartiffanybostonakij" + + "insekikogentingminakamichiharabotanicalgardenishikatakazakis-a-c" + + "padoval-daostavalleybotanicgardenishikatsuragithubusercontentjel" + + "dsundyndns-ipalermomasvuotnakatombetsupplybotanybouncemerckautok" + + "einobounty-fullensakerrypropertiesaotomeloyalistockholmestrandyn" + + "dns-mailowiczest-le-patrondheimperiaboutiquebecngmodellingmxfini" + + "tybozentsujiiebradescorporationishikawazukanazawabrandywinevalle" + + "ybrasiliabresciabrindisibenikebristolgapartmentsapodhalewismille" + + "rbritishcolumbialowiezaganishimerabroadcastleclercasinore-og-uvd" + + "alucaniabroadwaybroke-itjmaxxxjaworznobrokerbronnoysundyndns-off" + + "ice-on-the-webcampobassociatesapporobrothermesaverdeatnuorogersv" + + "palmspringsakerbrumunddaluccapitalonewhollandyndns-picsaratovall" + + "eaostavernishinomiyashironobrunelblagdenesnaaseralingenkainanaej" + + "rietisalatinabenoboribetsucksardegnamsosnowiecateringebudejjuedi" + + "schesapeakebayernurembergrimstadyndns-remotegildeskalmykiabrusse" + + "lsardiniabruxellesarlucernebryanskjervoyagebryneustarhubalestran" + + "dabergamoarekemrbuskerudinewhampshirechtrainingripebuzenishinoom" + + "otegotvalled-aostavropolitiendabuzzgorzeleccolognewmexicoldwarmi" + + "amiastaplesarpsborgriwataraidyndns-servercellikes-piedmontblanco" + + "meeresarufutsunomiyawakasaikaitakoenigrondarbwhalingrongabzhitom" + + "irkutskleppamperedchefashionishinoshimatta-varjjatjometlifeinsur" + + "ancecomputerhistoryofscience-fictioncomsecuritytacticsavonamssko" + + "ganeis-a-designerimarumorimachidacondoshichinohealthcareersaxoco" + + "nferenceconstructionconsuladoharuhrconsultanthropologyconsulting" + + "volluzerncontactoyosatoyokawacontemporaryarteducationalchikugojo" + + "medio-campidano-mediocampidanomediocontractorskenconventureshino" + + "desashibetsuikimobetsuliguriacookingchannelveruminamibosogndalvi" + + "vano-frankivskfhappoumuenchencoolkuszgradcooperaunitemasekhabaro" + + "vskhakassiacopenhagencyclopedichernihivanovosibirskydivingrosset" + + "ouchijiwadeloittevadsoccertificationissandnessjoenissayokoshibah" + + "ikariwanumataketomisatomobellevuelosangelesjaguarchitecturealtyc" + + "hyattorneyagawalbrzycharternopilawalesundyndns-wikinderoycorsica" + + "hcesuolocalhistorybnikahokutoeiheijis-a-doctoraycorvettenrightat" + + "homegoodsbschokoladencosenzakopanerairguardcostumedizinhistorisc" + + "hescholarshipschoolcouchpotatofrieschulezajskharkivgucciprianiig" + + "ataiwanairforcertmgretachikawakuyabukicks-assedichernivtsiciliac" + + "ouncilcouponschwarzgwangjuifminamidaitomangotembaixadacourseschw" + + "eizippodlasiellakasamatsudovre-eikercq-acranbrookuwanalyticscien" + + "cecentersciencehistorycreditcardcreditunioncremonashorokanaiecre" + + "wildlifedjejuegoshikiminokamoenairlinedre-eikercricketrzyncrimea" + + "crotonewportlligatewaycrownprovidercrscientistor-elvdalcruisescj" + + "ohnsoncryptonomichigangwoncuisinellahppiacenzamamibuilderscotlan" + + "dculturalcentertainmentoyotaris-a-financialadvisor-aurdalcuneocu" + + "pcakecxn--1ctwolominamatambovalledaostamayukis-a-geekgalaxycymru" + + "ovatoyotomiyazakis-a-greencyonabarussiacyouthdfcbankzjcbnlfieldf" + + "iguerestaurantoyotsukaidownloadfilateliafilminamiechizenfinalfin" + + "ancefineartscrappinguovdageaidnulsandoyfinlandfinnoyfirebaseappa" + + "raglidingushikamifuranoshiroomurafirenzefirestonextdirectoyouraf" + + "irmdaleirfjordfishingolffanserveftparisor-fronfitjarqhachiojiyah" + + "ikobeatservegame-serverisignfitnessettlementoystre-slidrettozawa" + + "fjalerflesbergxn--1lqs71dflickragerotikamakurazakinkobayashiksha" + + "cknetnedalflightservehalflifestyleflirumannortonsbergzlgfloginto" + + "gurafloraflorencefloridafloristanohatakaharulvikhmelnitskiyamasf" + + "jordenfloromskoguchikuzenflowerservehttparliamentozsdeflsmidthru" + + "heredstonexus-east-1flynnhubalsfjordishakotankarumaifarmerseinew" + + "yorkshirecreationaturbruksgymnaturhistorisches3-us-gov-west-1fnd" + + "foodnetworkshoppingfor-ourfor-someetranbyfor-theaterforexrothach" + + "irogatakamoriokamikitayamatotakadaforgotdnservehumourforli-cesen" + + "a-forlicesenaforlikescandyndns-at-workinggrouparmaforsaleirvikhm" + + "elnytskyivalleeaosteigenforsandasuoloftrani-andria-barletta-tran" + + "i-andriafortmissoulan-udefenseljordfortworthadanotaireserveirche" + + "rnovtsykkylvenetogakushimotoganewjerseyforuminamifuranofosneserv" + + "eminecraftraniandriabarlettatraniandriafotaruis-a-gurunzenfoxfor" + + "degreefreeboxostrowiechiryukyuragifudaigodoesntexistanbullensvan" + + "guardyndns-workisboringroundhandlingroznyfreemasonryfreiburgfrei" + + "ghtcmwilliamhillfreseniuscountryestateofdelawaredumbrellajollame" + + "ricanexpressexyzparocherkasyzrankoshigayaltaikis-a-hard-workerfr" + + "ibourgfriuli-v-giuliafriuli-ve-giuliafriuli-vegiuliafriuli-venez" + + "ia-giuliafriuli-veneziagiuliafriuli-vgiuliafriuliv-giuliafriuliv" + + "e-giuliafriulivegiuliafriulivenezia-giuliafriuliveneziagiuliafri" + + "ulivgiuliafrlfroganservemp3utilitiesquarezzoologicalvinklein-add" + + "rammenuernbergdyniabcn-north-1kappleaseating-organicbcg12000emma" + + "fanconagawakayamadridvagsoyericsson-aptibleangaviikadenaamesjevu" + + "emielno-ip6frognfrolandfrom-akrehamnfrom-alfrom-arfrom-azwinbalt" + + "imore-og-romsdalimitedunetbankasaokamisatokamachippubetsubetsuga" + + "ruconnectarumizusawaukraanghkebinagisochildrensgardenasushiobara" + + "bruzzoologyeongbuk-uralsk12from-capetownnews-stagingfrom-collect" + + "ionfrom-ctranoyfrom-dchitachinakagawassamukawataricohdavvenjarga" + + "usdalukowhoswhokksundynnsasayamafrom-dell-ogliastrakhanawatchese" + + "rvep2parservepicservequakefrom-flanderservesarcasmatartanddesign" + + "from-gafrom-higashiagatsumagoirminamiiselectransportrapaniimimat" + + "akatsukis-a-hunterfrom-iafrom-idfrom-ilfrom-incheonfrom-kservice" + + "settsurfastlyfrom-kyotobetsumidatlantichitosetogitsuldaluroyfrom" + + "-lanbibaidarfrom-mansionsevastopolefrom-mdfrom-megurorostrowwlkp" + + "mgfrom-microsoftbankhvanylvenicefrom-mnfrom-mochizukirafrom-msev" + + "enassisicilyfrom-mtnfrom-nchloefrom-ndfrom-nefrom-nhktravelchann" + + "elfrom-njcpartis-a-knightravelersinsurancefrom-nminamiizukamiton" + + "dabayashiogamagoriziafrom-nvaolbia-tempio-olbiatempioolbialystok" + + "kemerovodkagoshimaizurubtsovskjakdnepropetrovskiervaapsteiermark" + + "labudhabikinokawabarthadselfipartnersewindmillfrom-nyfrom-ohkura" + + "from-oketohmanxn--1qqw23afrom-orfrom-paderbornfrom-pratohnoshooo" + + "shikamaishimofusartsfranziskanerdpolicefrom-rivnefrom-schoenbrun" + + "nfrom-sdnipropetrovskypescaravantaafrom-tnfrom-txn--2m4a15efrom-" + + "utazuerichardlillehammerfest-mon-blogueurovisionfrom-vaksdalfrom" + + "-vtrdfrom-wafrom-wielunnerfrom-wvareserveblogspotrentino-a-adige" + + "from-wyfrosinonefrostalowa-wolawafroyahabaghdadultrentino-aadige" + + "fstcgroupartshangrilangevagrarboretumbriamallamagentositelefonic" + + "aaarborteaches-yogasawaracingroks-theatreefujiiderafujikawaguchi" + + "konefujiminohtawaramotoineppugliafujinomiyadafujiokayamaoris-a-l" + + "andscaperugiafujisatoshonairportland-4-salernogatagajobojis-a-la" + + "wyerfujisawafujishiroishidakabiratoridellogliastraderfujitsuruga" + + "shimamateramodalenfujixeroxn--30rr7yfujiyoshidafukayabeardubaidu" + + "ckdnsdojoburgfukuchiyamadafukudominichocolatelevisionissedalutsk" + + "azimierz-dolnyfukuis-a-liberalfukumitsubishigakirkenesharis-a-li" + + "bertarianfukuokazakirovogradoyfukuroishikarikaturindalfukusakiry" + + "uohaebaruminamimakis-a-linux-useranishiaritabashikaoizumizakitau" + + "rayasudafukuyamagatakahashimamakisarazurewebsiteshikagamiishibuk" + + "awafunabashiriuchinadafunagatakahatakaishimoichinosekigaharafuna" + + "hashikamiamakusatsumasendaisennangonohejis-a-llamarylandfundacio" + + "fuoiskujukuriyamarburgfuosskoczowindowsharpartyfurnitureggio-cal" + + "abriafurubiraquarellebesbyglandfurudonostiafurukawairtelecityeat" + + "shawaiijimarugame-hostingfusodegaurafussaikishiwadafutabayamaguc" + + "hinomigawafutboldlygoingnowhere-for-moregontrailroadfuttsurugimi" + + "namiminowafvgfyis-a-musicianfylkesbiblackfridayfyresdalhannovarg" + + "gatrentino-alto-adigehanyuzenhapmirhareidsbergenharstadharvestce" + + "lebrationhasamarahasaminami-alpssells-itrentino-altoadigehashban" + + "ghasudahasura-appassagenshimokitayamahasvikmshimonitayanagivestb" + + "ytomaritimekeepinghatogayahoohatoyamazakitahatakanabeautydalhats" + + "ukaichikaiseis-a-painteractivegarsheis-a-patsfanhattfjelldalhaya" + + "shimamotobuildinghazuminobusellsyourhomeipassenger-associationhb" + + "oehringerikehelsinkitahiroshimarriottrentino-s-tirollagrigentomo" + + "logyhembygdsforbundhemneshimonosekikawahemsedalhepforgeherokussl" + + "dheroyhgtvaroyhigashichichibungotakadatinghigashihiroshimanehiga" + + "shiizumozakitakamiizumisanofidelityumenhigashikagawahigashikagur" + + "asoedahigashikawakitaaikitakatakanezawahigashikurumeiwamarshalls" + + "tatebankokonoehigashimatsushimarinehigashimatsuyamakitaakitadait" + + "oigawahigashimurayamalatvuopmidoris-a-personaltrainerhigashinaru" + + "sembokukitakyushuaiahigashinehigashiomihachimanchesterhigashiosa" + + "kasayamamotorcycleshimosuwalkis-a-photographerokuappaviancarboni" + + "a-iglesias-carboniaiglesiascarboniahigashishirakawamatakaokamiko" + + "aniikappulawyhigashisumiyoshikawaminamiaikitamidsundhigashitsuno" + + "tteroyhigashiurausukitamotosumitakaginankokubunjis-a-playerhigas" + + "hiyamatokoriyamanakakogawahigashiyodogawahigashiyoshinogaris-a-r" + + "epublicancerresearchaeologicaliforniahiraizumisatohobby-sitehira" + + "katashinagawahiranairtraffichonanbugattipschmidtre-gauldaluxuryh" + + "irarahiratsukagawahirayaitakarazukamiminershimotsukehistorichous" + + "eshimotsumahitachiomiyaginowaniihamatamakawajimarcheapfizerhitac" + + "hiotagooglecodespotrentino-stirolhitoyoshimifunehitradinghjartda" + + "lhjelmelandholeckobierzyceholidayhomelinuxn--32vp30hagebostadhom" + + "esecuritymaceratakasagopocznosegawahomesecuritypccwinnershinichi" + + "nanhomesenseminehomeunixn--3bst00minamiogunicomcastresistancehon" + + "dahonefosshinjournalismailillesandefjordhoneywellhongorgehonjyoi" + + "takasakitanakagusukumoduminamisanrikubetsupplieshinjukumanohorni" + + "ndalhorseoulminamitanehortendofinternetrentino-sud-tirolhotelesh" + + "inkamigotoyohashimototalhotmailhoyangerhoylandetroitskolobrzeger" + + "sundhumanitieshinshinotsurgeonshalloffamemergencyberlevagangavii" + + "kanonjis-a-rockstarachowicehurdalhurumajis-a-socialistmeindianap" + + "olis-a-bloggerhyllestadhyogoris-a-soxfanhyugawarahyundaiwafunehz" + + "choseirouterjgorajlchoyodobashichikashukujitawarajlljmpgfoggiajn" + + "jelenia-gorajoyokaichibahcavuotnagaraholtaleniwaizumiotsukumiyam" + + "azonawsadodgemologicallyngenvironmentalconservationjpmorganjpnch" + + "ristmasakikugawatchandclockazojprshioyamemorialjuniperjurkristia" + + "nsundkrodsheradkrokstadelvaldaostarostwodzislawioshirakofuelkrym" + + "inamiyamashirokawanabelgorodeokumatorinokumejimassa-carrara-mass" + + "acarraramassabunkyonanaoshimageandsoundandvisionkumenanyokkaichi" + + "rurgiens-dentistes-en-francekunisakis-an-anarchistoricalsocietyk" + + "unitachiarailwaykunitomigusukumamotoyamasoykunneppupharmacyshira" + + "nukaniepcekunstsammlungkunstunddesignkuokgrouphiladelphiaareadmy" + + "blogsitekureisenkurgankurobelaudibleborkdalvdalaskanittedallasal" + + "leasingleshiraois-an-artisteinkjerusalembroiderykurogimilitaryku" + + "roisoftwarendalenugkuromatsunais-an-engineeringkurotakikawasakis" + + "-an-entertainerkurskomitamamurakushirogawakustanais-bykusuperspo" + + "rtrentinoaadigekutchanelkutnokuzbassnillfjordkuzumakis-certified" + + "ekakudamatsuekvafjordkvalsundkvamfamberkeleykvanangenkvinesdalkv" + + "innheradkviteseidskogkvitsoykwpspiegelkyowariasahikawamitourismo" + + "lanciamitoyoakemiuramiyazustkarasjokommunemiyotamanomjondalenmlb" + + "fanmonmouthaibarakisosakitagawamonstermonticellombardiamondshira" + + "okanmakiwakunigamihamadamontrealestatefarmequipmentrentinoalto-a" + + "digemonza-brianzaporizhzheguris-into-animelbournemonza-e-della-b" + + "rianzaporizhzhiamonzabrianzapposhiratakahagivingmonzaebrianzapto" + + "kuyamatsunomonzaedellabrianzaramoparachutingmordoviajessheiminan" + + "omoriyamatsusakahoginozawaonsenmoriyoshiokamitsuemormoneymoroyam" + + "atsushigemortgagemoscowitdkomonomoseushistorymosjoenmoskeneshish" + + "ikuis-into-carshintomikasaharamosshisognemosvikomorotsukamisunag" + + "awamoviemovistargardmtpchromedicaltanissettaitogliattiresaskatch" + + "ewanggouvicenzamtranakatsugawamuenstermugithubcloudusercontentre" + + "ntinoaltoadigemuikamogawamukochikushinonsenergymulhouservebeermu" + + "ltichoicemunakatanemuncieszynmuosattemuphilatelymurmanskomvuxn--" + + "3ds443gmurotorcraftrentinos-tirolmusashimurayamatsuuramusashinoh" + + "aramuseetrentinostirolmuseumverenigingmutsuzawamutuellevangermyd" + + "robofagemydshisuifuettertdasnetzmyeffectrentinosud-tirolmyfritzm" + + "yftphilipsymykolaivbarcelonagasakijobserverdalimoliserniaurskog-" + + "holandroverhalla-speziaeroportalabamagasakishimabarackmaze12myme" + + "diapchryslermyokohamamatsudamypepsonyoursidedyn-o-saurecipesaro-" + + "urbino-pesarourbinopesaromalvikongsbergmypetshitaramamyphotoshib" + + "ahccavuotnagareyamakeupowiathletajimabariakepnord-odalpharmacien" + + "snasaarlandmypsxn--3e0b707emysecuritycamerakermyshopblockshizuku" + + "ishimogosenmytis-a-bookkeepermincommbankommunalforbundmyvnchungb" + + "ukazunopictureshizuokannamiharupiemontepilotshoujis-into-cartoon" + + "shinyoshitomiokaneyamaxunusualpersonpimientakinouepinkongsvinger" + + "pioneerpippupiszpittsburghofauskedsmokorsetagayasells-for-ufcfan" + + "piwatepizzapkoninjamisonplanetariuminnesotaketakayamatsumaebashi" + + "modateplantationplantshowaplatformintelligenceplaystationplazapl" + + "chungnamdalseidfjordynv6plombardyndns-blogdnsiskinkyknethnologyp" + + "lumbingovtrentinosued-tirolplusterpmnpodzonepohlpointtomskonskow" + + "olancashireggioemiliaromagnakasatsunais-a-techietis-a-studentalp" + + "oivronpokerpokrovskonsulatrobeepilepsydneypolkowicepoltavalle-ao" + + "stathellexusdecorativeartshowtimeteorapphotographysiopomorzeszow" + + "ithgoogleapisa-hockeynutrentinosuedtirolpordenonepornporsangerpo" + + "rsanguideltajimicrolightingporsgrunnanpoznanpraxis-a-bruinsfanpr" + + "dpreservationpresidioprgmrprimelhusgardenprincipeprivatizehealth" + + "insuranceprochowiceproductionshriramlidlugolekagaminogiessenebak" + + "keshibechambagriculturennebudapest-a-la-masionthewifiat-band-cam" + + "paniaprofbsbxn--1lqs03nprogressivegaskimitsubatamicadaquesienapl" + + "esigdalprojectrentoyonakagyokutoyakokamishihoronobeokaminoyamats" + + "uris-into-gamessinashikitchenpromombetsupportrevisohughesilkonyv" + + "elolpropertyprotectionprudentialpruszkowithyoutubeneventodayprze" + + "worskogptzpvtroandinosaurlandesimbirskooris-a-therapistoiapwchur" + + "chaseljeepostfoldnavyatkakamigaharapzqldqponqslgbtrogstadquicksy" + + "tesimple-urlqvchuvashiaspreadbettingspydebergsrlsrtromsojavald-a" + + "ostarnbergsrvdonskoseis-an-accountantshinshirostoragestordalstor" + + "enburgstorfjordstpetersburgstreamsterdamnserverbaniastudiostudyn" + + "dns-homeftpaccesslingstuff-4-salestufftoread-booksneslupskopervi" + + "komatsushimashikestuttgartrusteesurnadalsurreysusakis-not-certif" + + "iedogawarabikomaezakirunorthwesternmutualsusonosuzakanrasuzukanu" + + "mazurysuzukis-saveducatorahimeshimakanegasakindleikangersvalbard" + + "udinkakegawasveiosvelvikosherbrookegawasvizzeraswedenswidnicargo" + + "daddyndns-at-homednshomebuiltrvenneslaskerrylogisticsmolenskoryo" + + "lasiteswiebodzindianmarketingswiftcoveronaritakurashikis-slickom" + + "aganeswinoujscienceandhistoryswisshikis-uberleetrentino-sued-tir" + + "olvestnesokndalvestre-slidreamhostersolarssonvestre-totennishiaw" + + "akuravestvagoyvevelstadvibo-valentiavibovalentiavideovillaskoyab" + + "earalvahkihokumakogengerdalipayufuchukotkafjordvinnicarriervinny" + + "tsiavipsinaappiagetmyiphoenixn--3oq18vl8pn36avirginiavirtualvirt" + + "ueeldomeindustriesteambulancevirtuelvisakatakkoelnvistaprinterna" + + "tionalfirearmsologneviterboltrysiljan-mayenvivoldavladikavkazanv" + + "ladimirvladivostokaizukarasuyamazoevlogoipictetrentinosudtirolvo" + + "lkenkunderseaportulansnoasaitamatsukuris-leetrentino-sudtirolvol" + + "kswagentsolundbeckosaigawavologdanskoshunantokigawavolvolgogradv" + + "olyngdalvoronezhytomyrvossevangenvotevotingvotoyonezawavrnworse-" + + "thangglidingwowiwatsukiyonowtversaillesokanoyakagewritesthisblog" + + "sytewroclawloclawekostromahachijorpelandwtcirclegnicagliaridagaw" + + "alterwtfbx-oslodingenwuozuwwworldwzmiuwajimaxn--4gq48lf9jeonname" + + "rikawauexn--4it168dxn--4it797kotohiradomainsurehabmerxn--4pvxsol" + + "utionsirdalxn--54b7fta0cciticatholicheltenham-radio-openair-traf" + + "fic-controlleyxn--55qw42gxn--55qx5dxn--5js045dxn--5rtp49civilavi" + + "ationisshingugexn--5rtq34kotouraxn--5su34j936bgsgxn--5tzm5gxn--6" + + "btw5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264civilisationi" + + "yodogawaxn--80adxhksomaxn--80ao21axn--80aqecdr1axn--80asehdbarcl" + + "aycardstvedestrandiskstationatuurwetenschappenaumburgladelmenhor" + + "stalbans3-us-west-1xn--80aswgxn--80audnedalnxn--8ltr62kouhokutam" + + "akizunokunimilanoxn--8pvr4uxn--8y0a063axn--90a3academyactivedire" + + "ctoryazannakadomari-elasticbeanstalkounosunndalxn--90aishobaraom" + + "origuchiharagusabaerobaticketsaritsynologyeongnamegawakeisenbahn" + + "xn--90azhair-surveillancexn--9dbhblg6dietcimmobilienxn--9dbq2axn" + + "--9et52uxn--9krt00axn--andy-iraxn--aroport-byanagawaxn--asky-ira" + + "xn--aurskog-hland-jnbarclays3-us-west-2xn--avery-yuasakegawaxn--" + + "b-5gaxn--b4w605ferdxn--bck1b9a5dre4civilizationrwiiheyaizuwakama" + + "tsubushikusakadogawaxn--bdddj-mrabdxn--bearalvhki-y4axn--berlevg" + + "-jxaxn--bhcavuotna-s4axn--bhccavuotna-k7axn--bidr-5nachikatsuura" + + "xn--bievt-0qa2xn--bjarky-fyanaizuxn--bjddar-ptaobaokinawashirosa" + + "tobishimaintenancexn--blt-elaborxn--bmlo-graingerxn--bod-2naroyx" + + "n--brnny-wuaccident-investigationjukudoyamagadancebetsukubabia-g" + + "oracleaningatlantabusebastopologyeonggiehtavuoatnadexeterimo-i-r" + + "anagahamaroygardendoftheinternetflixilovecollegefantasyleaguerns" + + "eyxn--brnnysund-m8accident-preventionlineat-urlxn--brum-voagatun" + + "esnzxn--btsfjord-9zaxn--c1avgxn--c2br7gxn--c3s14misasaguris-gone" + + "xn--cck2b3barefootballangenoamishirasatochigiftsakuragawaustevol" + + "lavangenativeamericanantiques3-eu-central-1xn--cg4bkis-very-bada" + + "ddjamalborkangerxn--ciqpnxn--clchc0ea0b2g2a9gcdn77-sslattumisawa" + + "xn--comunicaes-v6a2oxn--correios-e-telecomunicaes-ghc29axn--czr6" + + "94bargainstitutelekommunikationaustdalindasiaustinnaturalhistory" + + "museumcentereportarnobrzegyptianaturalsciencesnaturelles3-eu-wes" + + "t-1xn--czrs0tunkoshimizumakiyosumydissentrentinoa-adigexn--czru2" + + "dxn--czrw28barreauctionaval-d-aosta-valleyonagoyaustraliaisondri" + + "odejaneirochestereviewskrakowebhoppdalaziobihirosakikamijimattel" + + "edatabaseballooningjesdalillyokosukareliancebinorilskariyakumold" + + "evennodessagaeroclubmedecincinnationwidealerhcloudcontrolledds3-" + + "external-1xn--d1acj3barrel-of-knowledgeologyonaguniversityoriika" + + "shibatakashimarylhurstjordalshalsenavigationavuotnakayamatsuzaki" + + "bigawaustrheimatunduhrennesoyokotebizenakamuratakahamaniwakurate" + + "xasdaburyatiaarpagefrontappagespeedmobilizerobiraetnagaivuotnaga" + + "okakyotambabydgoszczecinemailavagiske164xn--d1alfaromeoxn--d1atu" + + "rystykarasjohkamiokaminokawanishiaizubangexn--d5qv7z876civilwarm" + + "anagementkmaxxn--11b4c3dyroyrvikinguitarsassaris-a-democratmpana" + + "sonichelyabinskodjeffersonishiokoppegardyndns-weberlincolnishito" + + "sashimizunaminamiashigaraxn--davvenjrga-y4axn--djrs72d6uyxn--djt" + + "y4kouyamashikis-an-actorxn--dnna-grajewolterskluwerxn--drbak-wua" + + "xn--dyry-iraxn--e1a4claimsatxn--1ck2e1balsanagochihayaakasakawah" + + "araumalopolskanlandiscoveryokamikawanehonbetsurutaharaugustowada" + + "egubs3-ap-southeast-2xn--eckvdtc9dxn--efvn9somnarashinoxn--efvy8" + + "8hakatanotogawaxn--ehqz56nxn--elqq16hakodatexn--estv75gxn--eveni" + + "-0qa01gaxn--f6qx53axn--fct429kouzushimashikokuchuoxn--fhbeiarnxn" + + "--finny-yuaxn--fiq228c5hsooxn--fiq64barrell-of-knowledgeometre-e" + + "xperts-comptablesakuraibmditchyouripalaceu-1xn--fiqs8sopotromsak" + + "akinokiaxn--fiqz9sor-odalxn--fjord-lraxn--fjq720axn--fl-ziaxn--f" + + "lor-jraxn--flw351exn--fpcrj9c3dxn--frde-grandrapidsor-varangerxn" + + "--frna-woaraisaijosoyrovigorlicexn--frya-hraxn--fzc2c9e2clickddi" + + "elddanuorrikuzentakatajirissagamiharaxn--fzys8d69uvgmailxn--g2xx" + + "48clinichernigovernmentjxn--0trq7p7nnishiwakis-a-cubicle-slavell" + + "inowruzhgorodoyxn--gckr3f0fbxostrolekaluganskharkovallee-aostero" + + "yxn--gecrj9cliniquenoharaxn--ggaviika-8ya47hakonexn--gildeskl-g0" + + "axn--givuotna-8yandexn--3pxu8kosugexn--gjvik-wuaxn--gk3at1exn--g" + + "ls-elacaixaxn--gmq050is-very-evillagexn--gmqw5axn--h-2failxn--h1" + + "aeghakubankmpspacekitagatakasugais-a-nascarfanxn--h2brj9clintono" + + "shoesaudaxn--hbmer-xqaxn--hcesuolo-7ya35bashkiriauthordalandroid" + + "gcanonoichinomiyakehimejibestadigitalimanowarudagroks-thisamitsu" + + "kembuchikumagayagawakkanaibetsubamericanfamilydscloudappspotager" + + "epairbusantiquest-a-la-maisondre-landebusinessebyklefrakkestaddn" + + "skingjerdrumckinseyekaterinburgjerstadotsuruokamchatkameokameyam" + + "ashinatsukigatakamatsukawabogadocscbggfareastcoastaldefence-burg" + + "jemnes3-ap-northeast-1xn--hery-iraxn--hgebostad-g3axn--hmmrfeast" + + "a-s4acctuscanyxn--hnefoss-q1axn--hobl-iraxn--holtlen-hxaxn--hpmi" + + "r-xqaxn--hxt814exn--hyanger-q1axn--hylandet-54axn--i1b6b1a6a2exn" + + "--imr513nxn--indery-fyaotsurgutsiracusaitoshimaxn--io0a7is-very-" + + "goodhandsonxn--j1aefermobilyxn--j1amhakuis-a-nurservebbshellaspe" + + "ziaxn--j6w193gxn--jlq61u9w7basilicataniautomotivecodynaliascoli-" + + "picenoipirangamvikarlsoyokozemersongdalenviknakaniikawatanaguram" + + "usementargets-itargi234xn--jlster-byaroslavlaanderenxn--jrpeland" + + "-54axn--jvr189misconfusedxn--k7yn95exn--karmy-yuaxn--kbrq7oxn--k" + + "crx77d1x4axn--kfjord-iuaxn--klbu-woaxn--klt787dxn--kltp7dxn--klt" + + "x9axn--klty5xn--42c2d9axn--koluokta-7ya57hakusandiegoodyearthaga" + + "khanamigawaxn--kprw13dxn--kpry57dxn--kpu716ferraraxn--kput3is-ve" + + "ry-nicexn--krager-gyasakaiminatoyonoxn--kranghke-b0axn--krdshera" + + "d-m8axn--krehamn-dxaxn--krjohka-hwab49jetztrentino-suedtirolxn--" + + "ksnes-uuaxn--kvfjord-nxaxn--kvitsy-fyasugis-very-sweetpepperxn--" + + "kvnangen-k0axn--l-1fairwindsorfoldxn--l1accentureklamborghiniiza" + + "xn--laheadju-7yasuokaratexn--langevg-jxaxn--lcvr32dxn--ldingen-q" + + "1axn--leagaviika-52basketballfinanzgorautoscanadaejeonbukarmoyom" + + "itanobninskarpaczeladz-1xn--lesund-huaxn--lgbbat1ad8jevnakershus" + + "cultureggiocalabriaxn--lgrd-poacoachampionshiphoptobamagazinebra" + + "skaunjargallupinbatochiokinoshimalselvendrellindesnesakyotanabel" + + "lunordlandivtasvuodnaharimamurogawawegroweibolzanordreisa-geekas" + + "hiharaveroykenglandiscountysvardolls3-external-2xn--lhppi-xqaxn-" + + "-linds-pramericanartushuissier-justicexn--lns-qlanxessorreisahay" + + "akawakamiichikawamisatottoris-lostre-toteneis-a-teacherkassymant" + + "echnologyxn--loabt-0qaxn--lrdal-sraxn--lrenskog-54axn--lt-liaclo" + + "thingujolsterxn--lten-granexn--lury-iraxn--mely-iraxn--merker-ku" + + "axn--mgb2ddesortlandxn--mgb9awbferrarittogoldpoint2thisayamanash" + + "iibadajozorahkkeravjudygarlandxn--mgba3a3ejtuvalle-daostavangerx" + + "n--mgba3a4f16axn--mgba3a4franamizuholdingsmileksvikozagawaxn--mg" + + "ba7c0bbn0axn--mgbaakc7dvferreroticapebretonamiasakuchinotsuchiur" + + "akawarszawashingtondclkhersonxn--mgbaam7a8haldenxn--mgbab2bdxn--" + + "mgbai9a5eva00batsfjordivttasvuotnakaiwamizawavocatanzaroweddingj" + + "ovikaruizawasnesoddenmarkets3-ap-northeast-2xn--mgbai9azgqp6jewe" + + "lryxn--mgbayh7gpaduaxn--mgbb9fbpobanazawaxn--mgbbh1a71exn--mgbc0" + + "a9azcgxn--mgbca7dzdoxn--mgberp4a5d4a87gxn--mgberp4a5d4arxn--mgbi" + + "4ecexposedxn--mgbpl2fhskozakis-an-actresshintokushimaxn--mgbqly7" + + "c0a67fbcloudfrontdoorxn--mgbqly7cvafredrikstadtvsorumisakis-foun" + + "dationxn--mgbt3dhdxn--mgbtf8flatangerxn--mgbtx2bauhausposts-and-" + + "telecommunicationsupdatelemarkashiwaravoues3-fips-us-gov-west-1x" + + "n--mgbx4cd0abbottuxfamilyxn--mix082fetsundxn--mix891fgunmarnarda" + + "lxn--mjndalen-64axn--mk0axinfinitis-with-thebandoomdnsaliascolip" + + "icenord-aurdalceshiojirishirifujiedaxn--mk1bu44cloudfunctionsauh" + + "eradxn--mkru45isleofmandalxn--mlatvuopmi-s4axn--mli-tlapyatigors" + + "kpnxn--mlselv-iuaxn--moreke-juaxn--mori-qsakuhokkaidontexisteing" + + "eekppspbananarepublicartierxn--mosjen-eyatominamiawajikissmarter" + + "thanyouslivinghistoryxn--mot-tlaquilancasterxn--mre-og-romsdal-q" + + "qbbcartoonartdecoffeedbackashiwazakiyokawaraxastronomycdn77-secu" + + "rebungoonord-frontierepbodyndns-freebox-oskolegokasells-for-less" + + "3-ap-southeast-1xn--msy-ula0halsaintlouis-a-anarchistoireggio-em" + + "ilia-romagnakanotoddenxn--mtta-vrjjat-k7afamilycompanycntoyookan" + + "zakiwienxn--muost-0qaxn--mxtq1mishimatsumotofukexn--ngbc5azdxn--" + + "ngbe9e0axn--ngbrxn--45brj9circus-2xn--nit225krasnodarxn--nmesjev" + + "uemie-tcbajddarchaeologyxn--nnx388axn--nodexn--nqv7fs00emaxn--nr" + + "y-yla5gxn--ntso0iqx3axn--ntsq17gxn--nttery-byaeservecounterstrik" + + "exn--nvuotna-hwaxn--nyqy26axn--o1achattanooganorfolkebiblegalloc" + + "us-1xn--o3cw4hammarfeastafricamagichofunatorientexpressaseboknow" + + "sitalluxembourgrpanamaxn--od0algxn--od0aq3bbtatamotorsalangenayo" + + "roceanographicsalondonetskasukabedzin-the-bandaioiraseeklogesura" + + "nceoceanographiqueu-2xn--ogbpf8flekkefjordxn--oppegrd-ixaxn--ost" + + "ery-fyatsukaratsuginamikatagamihoboleslawiecolonialwilliamsburgu" + + "lenxn--osyro-wuaxn--p1acfhvalerxn--p1aiwchoshibuyachiyodavvesiid" + + "azaifuefukihaborokunohealth-carereformitakeharaxn--pbt977colorad" + + "oplateaudioxn--pgbs0dhlxn--porsgu-sta26fidonnakamagayachtscrappe" + + "r-sitexn--pssu33lxn--pssy2uxn--q9jyb4columbusheyxn--qcka1pmcdona" + + "ldsouthcarolinazawaxn--qqqt11missilelxn--qxamurskiptveterinairea" + + "ltorlandxn--rady-iraxn--rdal-poaxn--rde-ularvikrasnoyarskomforba" + + "mblebtimnetz-2xn--rdy-0nabarixn--rennesy-v1axn--rhkkervju-01afla" + + "kstadaokagakibichuoxn--rholt-mragowoodsidexn--rhqv96gxn--rht27zx" + + "n--rht3dxn--rht61exn--risa-5narusawaxn--risr-iraxn--rland-uuaxn-" + + "-rlingen-mxaxn--rmskog-byatsushiroxn--rny31hamurakamigoriginshim" + + "okawaxn--rovu88bbvacationswatch-and-clockerxn--rros-granvindafjo" + + "rdxn--rskog-uuaxn--rst-0narutokyotangotpantheonsitextileitungsen" + + "xn--rsta-francaiseharaxn--ryken-vuaxn--ryrvik-byawaraxn--s-1fait" + + "heguardianxn--s9brj9communitysnesavannahgaxn--sandnessjen-ogbizh" + + "evskredirectmeldalxn--sandy-yuaxn--seral-lraxn--ses554gxn--sgne-" + + "gratangenxn--skierv-utazaskvolloabathsbcomobaraxn--skjervy-v1axn" + + "--skjk-soaxn--sknit-yqaxn--sknland-fxaxn--slat-5narviikananporov" + + "noxn--slt-elabourxn--smla-hraxn--smna-gratis-a-bulls-fanxn--snas" + + "e-nraxn--sndre-land-0cbremangerxn--snes-poaxn--snsa-roaxn--sr-au" + + "rdal-l8axn--sr-fron-q1axn--sr-odal-q1axn--sr-varanger-ggbentleyu" + + "kuhashimojiinetatarstanflfanfshostrodawaraxn--srfold-byawatahama" + + "xn--srreisa-q1axn--srum-grazxn--stfold-9xaxn--stjrdal-s1axn--stj" + + "rdalshalsen-sqbeppubolognagasukeverbankasumigaurawa-mazowszexbox" + + "enapponazure-mobilevje-og-hornnesaltdalinkasuyakutiaxn--stre-tot" + + "en-zcbsouthwestfalenxn--t60b56axn--tckweatherchannelxn--tiq49xqy" + + "jewishartgalleryxn--tjme-hraxn--tn0agrinet-freaksowaxn--tnsberg-" + + "q1axn--tor131oxn--trany-yuaxn--trgstad-r1axn--trna-woaxn--troms-" + + "zuaxn--tysvr-vraxn--uc0atversicherungxn--uc0ay4axn--uist22hangou" + + "tsystemscloudcontrolappasadenaklodzkodairaxn--uisz3gxn--unjrga-r" + + "tarantourspjelkavikosakaerodromegalsacechirealminamiuonumasudaxn" + + "--unup4yxn--uuwu58axn--vads-jraxn--vard-jraxn--vegrshei-c0axn--v" + + "ermgensberater-ctberndiyurihonjournalistjohnhlfanhsalvadordaliba" + + "baikaliszczytnorddalinzaiitatebayashijonawatexn--vermgensberatun" + + "g-pwbeskidynathomedepotenzachpomorskienikiiyamanobeauxartsandcra" + + "ftsalzburglassassinationalheritagematsubarakawagoexn--vestvgy-ix" + + "a6oxn--vg-yiabbvieeexn--vgan-qoaxn--vgsy-qoa0jfkomakiyosatokashi" + + "kiyosemitexn--vgu402comparemarkerryhotelsaves-the-whalessandria-" + + "trani-barletta-andriatranibarlettaandriaxn--vhquvestfoldxn--vler" + + "-qoaxn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla5gxn--vuq861bestbu" + + "yshousesamegawaxn--w4r85el8fhu5dnraxn--w4rs40lxn--wcvs22dxn--wgb" + + "h1compute-1xn--wgbl6axn--xhq521betainaboxfusejnynysafetysfjordnp" + + "alanakhodkanagawaxn--xkc2al3hye2axn--xkc2dl3a5ee0hannanmokuizumo" + + "dernxn--y9a3aquariumisugitokorozawaxn--yer-znarvikristiansandcat" + + "shirahamatonbetsurgeryxn--yfro4i67oxn--ygarden-p1axn--ygbi2ammxn" + + "--45q11citadeliveryggeelvinckchristiansburgruexn--ystre-slidre-u" + + "jbieidsvollipetskaszubyusuharaxn--zbx025dxn--zf0ao64axn--zf0avxn" + + "--4gbriminingxn--zfr164bielawallonieruchomoscienceandindustrynik" + + "koebenhavnikolaeventsamnangerxperiaxz" // nodes is the list of nodes. Each node is represented as a uint32, which // encodes the node's children, wildcard bit and node type (as an index into @@ -478,8035 +480,8055 @@ const text = "bievatmallorcadaquesamsunglassassinationalheritagematsubarakawag" // [15 bits] text index // [ 6 bits] text length var nodes = [...]uint32{ - 0x00398ec3, - 0x00271e44, - 0x0026a2c6, - 0x00367e03, - 0x00367e06, - 0x003a5c86, - 0x00252a03, - 0x002dd4c4, - 0x00322447, - 0x00269f08, - 0x01a050c2, - 0x00307107, - 0x00351089, - 0x002aee0a, - 0x002aee0b, - 0x00235c43, - 0x00298f86, - 0x00236985, - 0x01e00342, - 0x00217d44, - 0x0026a443, - 0x002765c5, - 0x02207282, - 0x0022c903, - 0x0260c744, - 0x002e8d05, - 0x02a07182, - 0x00370ace, - 0x002496c3, - 0x0037ab06, - 0x0037ab0b, - 0x02e00bc2, - 0x0027e887, - 0x00239286, - 0x032017c2, - 0x002677c3, - 0x002677c4, - 0x0021c506, - 0x0023b308, - 0x002839c6, - 0x003a1b84, - 0x036001c2, - 0x0032c3c9, - 0x00366447, - 0x00325f86, - 0x00348149, - 0x0028bc08, - 0x00335084, - 0x0026f306, - 0x00211c86, - 0x03a00502, - 0x0021578f, - 0x0032074e, - 0x002122c4, - 0x002b7245, - 0x002dd3c5, - 0x002ebe49, - 0x0023df89, - 0x0031e847, - 0x00213cc6, - 0x00213c03, - 0x03e03082, - 0x0026dcc3, - 0x002043ca, - 0x0020f303, - 0x00252d45, - 0x002003c2, - 0x00283049, - 0x04200e02, - 0x002020c4, - 0x00398a06, - 0x002ad205, - 0x00349cc4, - 0x04a71e84, - 0x00201383, - 0x00235f84, - 0x04e006c2, - 0x00271b84, - 0x002e5704, - 0x0021db4a, - 0x05200102, - 0x0026ec07, - 0x00385908, - 0x05a076c2, - 0x0031de07, - 0x002d7484, - 0x002d7487, - 0x00384385, - 0x00364e47, - 0x0031e606, - 0x00325604, - 0x0032b445, - 0x00292247, - 0x06a00f02, - 0x00334c83, - 0x00209ec2, - 0x00353243, - 0x06e0efc2, - 0x0020f445, - 0x07200dc2, - 0x002e9344, - 0x0027bf05, - 0x00212207, - 0x002e4b4e, - 0x00322144, - 0x00243ec4, - 0x00200dc3, - 0x003767c9, - 0x002c900b, - 0x00305548, - 0x0030ba48, - 0x00318c88, - 0x00223f08, - 0x00347f8a, - 0x00364d47, - 0x00229b86, - 0x07671942, - 0x0036e6c3, - 0x0037bdc3, - 0x0038bac4, - 0x00253283, - 0x00252a43, - 0x0170f302, - 0x07a054c2, - 0x00247f85, - 0x00289c06, - 0x00275984, - 0x002e1007, - 0x0022fac6, - 0x0022bc84, - 0x003a4a87, - 0x002054c3, - 0x07eb9f42, - 0x08302e02, - 0x08619ac2, - 0x00219ac6, - 0x08a00002, - 0x0031a505, - 0x00310843, - 0x002029c4, - 0x002d6004, - 0x002d6005, - 0x00206943, - 0x08f41d03, - 0x092094c2, - 0x00286305, - 0x0028630b, - 0x0022f206, - 0x0020c28b, - 0x00274444, - 0x0020cf49, - 0x0020dd44, - 0x0960c902, - 0x0020f743, - 0x0020fac3, - 0x01610382, - 0x0023d2c3, - 0x0021038a, - 0x09a07f02, - 0x00217fc5, - 0x0028b34a, - 0x00323c04, - 0x00211203, - 0x00212084, - 0x00213683, - 0x00213684, - 0x00213687, - 0x00214745, - 0x00216945, - 0x00217006, - 0x00217346, - 0x00218d83, - 0x0021eb08, - 0x0020f1c3, - 0x09e14f02, - 0x0021ffc8, - 0x00214f0b, - 0x00225408, - 0x00225906, - 0x002263c7, - 0x0022a2c8, - 0x0a62ca02, - 0x0aae3782, - 0x003219c8, - 0x002a7507, - 0x002410c5, - 0x002410c8, - 0x0021ce08, - 0x002a8583, - 0x0022e8c4, - 0x0038bb02, - 0x0ae30642, - 0x0b2168c2, - 0x0ba30c82, - 0x00230c83, - 0x0be00302, - 0x002dd483, - 0x00319184, - 0x00218f03, - 0x00335044, - 0x002521cb, - 0x00214e43, - 0x002cd686, - 0x0021d9c4, - 0x002a5cce, - 0x002e66c5, - 0x00260f08, - 0x0022aa07, - 0x0022aa0a, - 0x00232b03, - 0x00273287, - 0x002c91c5, - 0x00232b04, - 0x00232b06, - 0x00232b07, - 0x002ddb04, - 0x002e4e87, - 0x00203e44, - 0x002051c4, - 0x002051c6, - 0x002d1bc4, - 0x00222d46, - 0x0020db83, - 0x00229408, - 0x00301c48, - 0x00243e83, - 0x0023d283, - 0x00395044, - 0x0039bec3, - 0x0c215e02, - 0x0c701e02, - 0x002068c3, - 0x00206bc6, - 0x003b0503, - 0x00302544, - 0x0ca19942, - 0x0025aac3, - 0x00219943, - 0x0021abc2, - 0x0ce01a82, - 0x002b6146, - 0x00237887, - 0x002e4085, - 0x002e7e04, - 0x00281945, - 0x0037c187, - 0x0027c945, - 0x002c2649, - 0x002ca506, - 0x002ce248, - 0x002e3f86, - 0x0d2047c2, - 0x002349c8, - 0x0034b806, - 0x002047c5, - 0x002ffa07, - 0x00301b44, - 0x00301b45, - 0x00283b84, - 0x00283b88, - 0x0d60c342, - 0x0da0c842, - 0x00339406, - 0x00314488, - 0x00339dc5, - 0x0033b4c6, - 0x00340708, - 0x00362c48, - 0x002c3805, - 0x0020c844, - 0x0020c847, - 0x0de0d6c2, - 0x0e21ed82, - 0x0fa02682, - 0x00354985, - 0x0029bd45, - 0x0036ea46, - 0x00315e07, - 0x00215e47, - 0x1022f303, - 0x00340047, - 0x002cde08, - 0x00391b89, - 0x00370c87, - 0x003a99c7, - 0x002316c8, - 0x00231ec6, - 0x00232646, - 0x0023348c, - 0x0023400a, - 0x00235787, - 0x0023684b, - 0x002376c7, - 0x002376ce, - 0x002381c4, - 0x00238c04, - 0x00239c87, - 0x00372807, - 0x0023cf06, - 0x0023cf07, - 0x0023d387, - 0x12a07102, - 0x0023e606, - 0x0023e60a, - 0x0023e88b, - 0x0023f987, - 0x00240145, - 0x00240483, - 0x00240746, - 0x00240747, - 0x0023e143, - 0x12e30042, - 0x00240aca, - 0x133521c2, - 0x1369ebc2, - 0x13a42302, - 0x13e39382, - 0x00243045, - 0x00243c84, - 0x14627542, - 0x00271c05, - 0x00276583, - 0x00313f05, - 0x00208244, - 0x0028dac6, - 0x0035c146, - 0x00286503, - 0x0023a4c4, - 0x0031b343, - 0x14a03f42, - 0x002074c4, - 0x0020cdc6, - 0x002074c5, - 0x002575c6, - 0x002ffb08, - 0x00263184, - 0x002d45c8, - 0x002d9d85, - 0x002d4e88, - 0x00331486, - 0x002ae607, - 0x0025fe04, - 0x0025fe06, - 0x0032bb83, - 0x00383283, - 0x002bac88, - 0x00309e84, - 0x0031f407, - 0x00307446, - 0x00307449, - 0x003264c8, - 0x0022bdc8, - 0x0024e4c4, - 0x003972c3, - 0x002398c2, - 0x14e08f02, - 0x15210c42, - 0x0039b8c3, - 0x15613942, - 0x00322584, - 0x00334d85, - 0x0023f803, - 0x00233944, - 0x002fef87, - 0x002e7b43, - 0x00368b88, - 0x00207885, - 0x002c9284, - 0x00363503, - 0x0027be85, - 0x0027bfc4, - 0x0020bd06, - 0x0020c5c4, - 0x00210106, - 0x00212146, - 0x00253a84, - 0x002199c3, - 0x15a7d7c2, - 0x0034c585, - 0x00247fc3, - 0x15e02642, - 0x002bc6c5, - 0x00215403, - 0x00236049, - 0x1621be02, - 0x16a0fb82, - 0x002e9705, - 0x0021ba06, - 0x00374987, - 0x002c46c6, - 0x0038df48, - 0x0038df4b, - 0x00206c0b, - 0x002cb9c5, - 0x00396d45, - 0x002bb789, - 0x01600ac2, - 0x00253c48, - 0x0020c4c4, - 0x17200482, - 0x00251e03, - 0x17abb506, - 0x003b0388, - 0x17e05502, - 0x00228948, - 0x002072c2, - 0x0027458a, - 0x0022b343, - 0x0032bbc6, - 0x00397f08, - 0x0035cc88, - 0x00327586, - 0x003621c7, - 0x00215987, - 0x0021180a, - 0x00323c84, - 0x0033ea04, - 0x00350b09, - 0x0038f105, - 0x00320946, - 0x00212a83, - 0x00247504, - 0x00214b84, - 0x00324ec7, - 0x00300c87, - 0x00265244, - 0x00211745, - 0x0036eb08, - 0x00359007, - 0x0035b207, - 0x1820bf82, - 0x00322004, - 0x0028e888, - 0x0037f344, - 0x00244a04, - 0x00244dc5, - 0x00244f07, - 0x0020e389, - 0x00245b04, - 0x002466c9, - 0x00246ec8, - 0x00247284, - 0x00247287, - 0x00247a43, - 0x00248587, - 0x01619fc2, - 0x017a6502, - 0x00249706, - 0x0024a347, - 0x0024a784, - 0x0024c0c7, - 0x0024cd87, - 0x0024d3c8, - 0x0024e103, - 0x0023c9c2, - 0x00218942, - 0x0024fd03, - 0x0024fd04, - 0x0024fd0b, - 0x0030bb48, - 0x003a8644, - 0x00250cc5, - 0x00256107, - 0x00257d45, - 0x002c194a, - 0x00259103, - 0x186046c2, - 0x00259444, - 0x0025b9c9, - 0x0025f6c3, - 0x0025f787, - 0x00369d09, - 0x0036d9c8, - 0x002071c3, - 0x0027a4c7, - 0x0027ac09, - 0x0027f243, - 0x002812c4, - 0x00282949, - 0x00284bc6, - 0x00285c83, - 0x00201202, - 0x002437c3, - 0x0039d0c7, - 0x0034b985, - 0x002e4946, - 0x002453c4, - 0x00312205, - 0x00204383, - 0x00218fc6, - 0x0020d142, - 0x0038fe04, - 0x002281c2, - 0x002d5983, - 0x18a00c02, - 0x00246183, - 0x002177c4, - 0x002177c7, - 0x00202cc6, - 0x0025c582, - 0x18e46b82, - 0x002ffd04, - 0x1924a402, - 0x19602ec2, - 0x0030c284, - 0x0030c285, - 0x0038b205, - 0x002c1446, - 0x19a00642, - 0x00367445, - 0x00200645, - 0x00292603, - 0x00210746, - 0x00213805, - 0x00219a42, - 0x00339a05, - 0x00219a44, - 0x00224243, - 0x00226cc3, - 0x19e0ba02, - 0x002f1107, - 0x0031a644, - 0x0031a649, - 0x00247404, - 0x0029bbc3, - 0x0034d709, - 0x0034c448, - 0x0029bbc4, - 0x0029bbc6, - 0x0029e403, - 0x00212c43, - 0x002235c4, - 0x002d60c3, - 0x1a2e1442, - 0x0035ff02, - 0x1a60a6c2, - 0x00312e08, - 0x0032a2c8, - 0x00394486, - 0x00258fc5, - 0x0024ba85, - 0x0020a6c5, - 0x00231302, - 0x1aa3a3c2, - 0x0162c702, - 0x0038f288, - 0x00234905, - 0x00300fc4, - 0x002d9cc5, - 0x00381ec7, - 0x0025a984, - 0x0021f1c2, - 0x1ae02382, - 0x00309744, - 0x00214387, - 0x0039ff87, - 0x00364e04, - 0x0028b303, - 0x00243dc4, - 0x00243dc8, - 0x00232986, - 0x0023298a, - 0x0020e244, - 0x0028b688, - 0x0024d644, - 0x002264c6, - 0x0028d344, - 0x00354c86, - 0x0031fd09, - 0x0026b887, - 0x0024b543, - 0x1b20a402, - 0x0026c783, - 0x0020e9c2, - 0x1b616442, - 0x002d8f86, - 0x0035a488, - 0x0029d547, - 0x003a3e89, - 0x002d49c9, - 0x0029de05, - 0x0029f089, - 0x002a0605, - 0x002a16c9, - 0x002a2c45, - 0x002901c4, - 0x002901c7, - 0x002a1143, - 0x002a3647, - 0x003a9d86, - 0x002a48c7, - 0x0029a505, - 0x002a6c03, - 0x1ba33ac2, - 0x00391ac4, - 0x1be26ac2, - 0x0025ad03, - 0x1c209f82, - 0x002dfe46, - 0x00385885, - 0x002a6fc7, - 0x003281c3, - 0x00253204, - 0x00206883, - 0x00321703, - 0x1c608202, - 0x1ce00042, - 0x003a5d84, - 0x0023c983, - 0x0032ac85, - 0x002a4445, - 0x1d202fc2, - 0x1da03d02, - 0x0027a806, - 0x0020aac4, - 0x00309fc4, - 0x00309fca, - 0x1e200842, - 0x003693ca, - 0x0037c388, - 0x1e77c544, - 0x00213783, - 0x00249d03, - 0x00318dc9, - 0x0026ca49, - 0x002ff086, - 0x1ea4af03, - 0x002d3505, - 0x002f814d, - 0x003a4186, - 0x002058cb, - 0x1ee00942, - 0x0026f148, - 0x1f21c742, - 0x1f604f82, - 0x002df505, - 0x1fa024c2, - 0x00257fc7, - 0x0029a907, - 0x002183c3, - 0x00267ac8, - 0x1fe00b42, - 0x00312544, - 0x00213a83, - 0x003257c5, - 0x002a7ec3, - 0x002ad106, - 0x002ea344, - 0x0023d243, - 0x0026ce03, - 0x2020a942, - 0x00239904, - 0x0034f185, - 0x00360007, - 0x00277f03, - 0x002a8383, - 0x002a95c3, - 0x0161f9c2, - 0x002a9683, - 0x002a9903, - 0x20607e82, - 0x00376b84, - 0x0027c206, - 0x00209e03, - 0x002a9c83, - 0x20aaa4c2, - 0x002aa4c8, - 0x002aaf04, - 0x0025b0c6, - 0x002ab347, - 0x00223186, - 0x002fff44, - 0x2e602942, - 0x003a9c4b, - 0x002f1b4e, - 0x0021e5cf, - 0x00339ec3, - 0x2ee43782, - 0x01608e42, - 0x2f201e82, - 0x00226303, - 0x002372c3, - 0x00230a86, - 0x002f33c6, - 0x00329247, - 0x002eecc4, - 0x2f64fa82, - 0x2fa07bc2, - 0x00268745, - 0x002f40c7, - 0x002f0746, - 0x2fe69942, - 0x00269944, - 0x0036c843, - 0x3020aa02, - 0x0034e603, - 0x003a2384, - 0x002b2049, - 0x016b8182, - 0x3064b8c2, - 0x002d5bc6, - 0x00266ec5, - 0x30a43f82, - 0x30e00682, - 0x0033da87, - 0x0035c949, - 0x0035130b, - 0x00215745, - 0x0036df49, - 0x002b9386, - 0x0022f247, - 0x002079c4, - 0x0024edc9, - 0x00356547, - 0x00366f07, - 0x0020ac03, - 0x0020ac06, - 0x002d7287, - 0x002761c3, - 0x0027ccc6, - 0x31203002, - 0x316362c2, - 0x00214183, - 0x00252e05, - 0x00222bc7, - 0x0021d106, - 0x0034b905, - 0x0031a5c4, - 0x002d8485, - 0x002e3704, - 0x31a067c2, - 0x0030c807, - 0x002e1c04, - 0x00247804, - 0x002e01cd, - 0x00247809, - 0x00300788, - 0x0022ee84, - 0x00341a85, - 0x00374347, - 0x00263c44, - 0x0022fb87, - 0x00376e45, - 0x31f19604, - 0x002c8cc5, - 0x0025e384, - 0x002d85c6, - 0x00315c05, - 0x32238282, - 0x002112c4, - 0x002112c5, - 0x0038c046, - 0x0034ba45, - 0x002569c4, - 0x002e3e43, - 0x0032a506, - 0x00213245, - 0x00216cc5, - 0x00315d04, - 0x0020e2c3, - 0x0020e2cc, - 0x32685502, - 0x32a07582, - 0x32e12942, - 0x0035ea43, - 0x0035ea44, - 0x33205d42, - 0x00304848, - 0x002e4a05, - 0x002a7b04, - 0x002c2ec6, - 0x33634342, - 0x33a1a9c2, - 0x33e00182, - 0x002b1105, - 0x00253946, - 0x00324e04, - 0x0021ca46, - 0x0026e9c6, - 0x00201943, - 0x3433040a, - 0x00237e05, - 0x002f2346, - 0x002f2349, - 0x00353547, - 0x00368748, - 0x0028bac9, - 0x0032aac8, - 0x00223c46, - 0x00237fc3, - 0x346e5e02, - 0x00384743, - 0x00384749, - 0x002e74c8, - 0x34a0ab02, - 0x34e04502, - 0x0020c943, - 0x002ca385, - 0x002507c4, - 0x002d30c9, - 0x002a3e44, - 0x002ab148, - 0x00204503, - 0x00252644, - 0x002e7f83, - 0x002e0107, - 0x352699c2, - 0x00260c82, - 0x00373245, - 0x00269b89, - 0x0021e083, - 0x0027c844, - 0x002d34c4, - 0x0024e903, - 0x0027cf4a, - 0x35769282, - 0x35a11282, - 0x002b9ec3, - 0x0036b983, - 0x01652602, - 0x002534c3, - 0x35e60542, - 0x003a6904, - 0x36204042, - 0x3660f5c4, - 0x00346b46, - 0x0027aa44, - 0x0025b4c3, - 0x002e88c3, - 0x0021a403, - 0x0023ec06, - 0x002bfc85, - 0x002ba747, - 0x0022f109, - 0x002beac5, - 0x002bfbc6, - 0x002c0148, - 0x002c0346, - 0x00277804, - 0x00293b0b, - 0x002c2143, - 0x002c2145, - 0x002c2288, - 0x0021da42, - 0x0033dd82, - 0x36a430c2, - 0x36e00542, - 0x00263b43, - 0x37207342, - 0x0026b603, - 0x002c2584, - 0x002c3043, - 0x37a015c2, - 0x002c4d8b, - 0x37ec7386, - 0x0024ac86, - 0x002c79c8, - 0x38221802, - 0x3860fb02, - 0x38a26d02, - 0x38e0b302, - 0x39203bc2, - 0x00203bcb, - 0x39600882, - 0x00228b83, - 0x00314fc5, - 0x0031e4c6, - 0x39a12284, - 0x0038d747, - 0x0020cbca, - 0x002e5946, - 0x002cbc04, - 0x00263743, - 0x3a604782, - 0x002032c2, - 0x002097c3, - 0x3aa4a143, - 0x00374547, - 0x00315b07, - 0x3be4fe07, - 0x0022b307, - 0x00215143, - 0x002e6f0a, - 0x0023ff04, - 0x00325104, - 0x0032510a, - 0x00246885, - 0x3c204682, - 0x0024cd43, - 0x3c600602, - 0x00205bc3, - 0x0026c743, - 0x3ce05f82, - 0x0033ffc4, - 0x002214c4, - 0x003aae45, - 0x002d0105, - 0x003802c6, - 0x00380646, - 0x3d20bd82, - 0x3d601542, - 0x00338445, - 0x0024a992, - 0x0029e586, - 0x0020af83, - 0x002fcec6, - 0x00226f05, - 0x01609042, - 0x45a0d2c2, - 0x002f4f83, - 0x0030ee43, - 0x002d6c03, - 0x45e01842, - 0x00370dc3, - 0x46213c42, - 0x00205c43, - 0x00376bc8, - 0x0021d583, - 0x0021d586, - 0x003a1287, - 0x0020a546, - 0x0020a54b, - 0x002cbb47, - 0x003918c4, - 0x46a01582, - 0x002e4885, - 0x00204083, - 0x002a1943, - 0x00316c83, - 0x00316c86, - 0x00396e0a, - 0x0026fcc3, - 0x00239144, - 0x003143c6, - 0x00204bc6, - 0x46e02d43, - 0x002530c7, - 0x0037af8d, - 0x0038ad47, - 0x00293845, - 0x002c06c6, - 0x00213283, - 0x48610983, - 0x48a04402, - 0x00328504, - 0x003009cc, - 0x0037f989, - 0x0023b1c7, - 0x00248285, - 0x00265c84, - 0x0026ce88, - 0x00271f05, - 0x00276c85, - 0x00281a49, - 0x00326043, - 0x00326044, - 0x0029eb44, - 0x48e05702, - 0x00260f83, - 0x492a1542, - 0x002a1546, - 0x016a9702, - 0x496a1102, - 0x002b1008, - 0x002c8c07, - 0x002a1105, - 0x002f730b, - 0x002cc486, - 0x002f7506, - 0x002ce446, - 0x00224b84, - 0x002ced06, - 0x002cf248, - 0x00235103, - 0x002500c3, - 0x002500c4, - 0x002cffc4, - 0x002d0387, - 0x002d1785, - 0x49ad18c2, - 0x49e09382, - 0x00209385, - 0x002a4744, - 0x002d380b, - 0x002d5f08, - 0x002d6604, - 0x00269982, - 0x4a66f082, - 0x002aa703, - 0x002d6a44, - 0x002d6e45, - 0x00225187, - 0x002d9804, - 0x002cba04, - 0x4aa05042, - 0x00355b49, - 0x002da605, - 0x00215a05, - 0x002db185, - 0x4ae1e703, - 0x002dc584, - 0x002dc58b, - 0x002dc944, - 0x002dcdcb, - 0x002df8c5, - 0x0021e70a, - 0x002e0508, - 0x002e070a, - 0x002e0983, - 0x002e098a, - 0x4b22d242, - 0x4b653ec2, - 0x00297fc3, - 0x4bae2782, - 0x002e2783, - 0x4bee9e82, - 0x4c310fc2, - 0x002e3584, - 0x0021ec46, - 0x0021c785, - 0x002e3f03, - 0x00399486, - 0x00262944, - 0x4c604942, - 0x002b2584, - 0x002bb40a, - 0x00270e47, - 0x003856c6, - 0x0022d347, - 0x002153c3, - 0x00372d48, - 0x002153cb, - 0x002d1d05, - 0x002ff185, - 0x002ff186, - 0x002b2984, - 0x0031a088, - 0x00206603, - 0x00211b84, - 0x00211b87, - 0x0021c446, - 0x0030ce86, - 0x002a5b0a, - 0x002443c4, - 0x002443ca, - 0x002e5006, - 0x002e5007, - 0x00250d47, - 0x00273d84, - 0x00273d89, - 0x0035c005, - 0x002d480b, - 0x00270383, - 0x002102c3, - 0x0024bac3, - 0x002a9304, - 0x4ca02282, - 0x0025a146, - 0x002a6985, - 0x002b31c5, - 0x00208b06, - 0x00257b84, - 0x4ce02802, - 0x00208c04, - 0x4d20b082, - 0x00233a44, - 0x00227fc3, - 0x4d6c9942, - 0x002c9943, - 0x00267486, - 0x4da004c2, - 0x002d7b48, - 0x00219e04, - 0x00219e06, - 0x0030c386, - 0x002561c4, - 0x0032a485, - 0x003a4dc8, - 0x002004c7, - 0x00203347, - 0x0020334f, - 0x0028e786, - 0x0021dd83, - 0x0021dd84, - 0x0022a884, - 0x00200743, - 0x00226604, - 0x003a9ec4, - 0x4de2f5c2, - 0x00286243, - 0x00232303, - 0x4e204842, - 0x00255003, - 0x00322643, - 0x002169ca, - 0x002a7707, - 0x00232c8c, - 0x00232f46, - 0x0023bac6, - 0x0023c607, - 0x00231b07, - 0x00240509, - 0x00220104, - 0x002408c4, - 0x4e64d302, - 0x4ea02542, - 0x00252ec4, - 0x0031c8c6, - 0x00231f88, - 0x003b01c4, - 0x00258006, - 0x002c4685, - 0x00264ec8, - 0x00206e03, - 0x002669c5, - 0x0026b243, - 0x00215b03, - 0x00215b04, - 0x0026d043, - 0x4eeda282, - 0x4f2016c2, - 0x00270249, - 0x0027d405, - 0x00281c44, - 0x00282645, - 0x00212604, - 0x00249f07, - 0x003578c5, - 0x0024ffc4, - 0x0024ffc8, - 0x002d2cc6, - 0x002dc804, - 0x002dff88, - 0x002e1a47, - 0x4f600802, - 0x002e3c04, - 0x00200804, - 0x00367107, - 0x4fa414c4, - 0x00254442, - 0x4fe066c2, - 0x0023bf43, - 0x002d5ac4, - 0x0024b883, - 0x00273105, - 0x50230242, - 0x002f1e85, - 0x0021e042, - 0x00387285, - 0x0035a645, - 0x506198c2, - 0x002198c4, - 0x50a05442, - 0x0035e446, - 0x0032d5c6, - 0x00269cc8, - 0x002b37c8, - 0x002dfdc4, - 0x002fab45, - 0x00330dc9, - 0x00374a84, - 0x00396dc4, - 0x00253b83, - 0x00211945, - 0x002b8247, - 0x0029be44, - 0x002e9b0d, - 0x002ea082, - 0x002ea083, - 0x002ea143, - 0x50e02842, - 0x00388005, - 0x003733c7, - 0x0022b3c4, - 0x0022b3c7, - 0x0028bcc9, - 0x002bb549, - 0x002039c7, - 0x00276ac3, - 0x00276ac8, - 0x00218409, - 0x002eb207, - 0x002eb585, - 0x002ebd46, - 0x002ec386, - 0x002ec505, - 0x00247905, - 0x51200582, - 0x00228ec5, - 0x002b5aca, - 0x00297648, - 0x0021a8c6, - 0x002dfb07, - 0x00265184, - 0x003acf87, - 0x002eee46, - 0x51608c42, - 0x0038bd46, - 0x002f258a, - 0x002f3d05, - 0x51accf82, - 0x51e39b02, - 0x00239b06, - 0x002eae48, - 0x003a0147, - 0x52209a42, - 0x0020f883, - 0x00205646, - 0x00307d44, - 0x003a1146, - 0x0020b506, - 0x00329c0a, - 0x0032ad85, - 0x00209886, - 0x00209e83, - 0x00209e84, - 0x00206b82, - 0x00309f43, - 0x52651982, - 0x002c0503, - 0x00369644, - 0x002eaf84, - 0x002eaf8a, - 0x00223d03, - 0x00283a88, - 0x00318f8a, - 0x0023ac47, - 0x002f5286, - 0x0035e304, - 0x0028a2c2, - 0x00207382, - 0x52a09302, - 0x00243d83, - 0x00250b07, - 0x00399747, - 0x0038f1cb, - 0x00271dc4, - 0x00308b07, - 0x00225286, - 0x00219bc7, - 0x002a7644, - 0x00279585, - 0x0029c1c5, - 0x52e140c2, - 0x0021f986, - 0x0037ff43, - 0x002cbd42, - 0x002d5046, - 0x53209c42, - 0x53600142, - 0x00200145, - 0x53a1a602, - 0x53e036c2, - 0x00327dc5, - 0x002bdcc5, - 0x00209945, - 0x00265e83, - 0x00241ec5, - 0x002cc547, - 0x00346105, - 0x00342745, - 0x00261004, - 0x00241b06, - 0x00248944, - 0x54202882, - 0x0027a345, - 0x0029cb47, - 0x00226b08, - 0x00261946, - 0x0026194d, - 0x0026c809, - 0x0026c812, - 0x002ed845, - 0x002f1883, - 0x54e09902, - 0x002e0f84, - 0x003a4203, - 0x00317305, - 0x00355e45, - 0x55213ac2, - 0x00363543, - 0x556424c2, - 0x55ac82c2, - 0x55e09fc2, - 0x0033ee05, - 0x0022c9c3, - 0x002096c8, - 0x56201d42, - 0x56601142, - 0x0033ff86, - 0x0032498a, - 0x00201503, - 0x00256943, - 0x002fa303, - 0x57202402, - 0x65601882, - 0x65e0d482, - 0x002000c2, - 0x0038bb49, - 0x002b75c4, - 0x00267dc8, - 0x662e3f42, - 0x66602602, - 0x002dd005, - 0x00236c88, - 0x002455c8, - 0x0039f74c, - 0x0023ab83, - 0x002348c2, - 0x66a03442, - 0x002bef46, - 0x002f6105, - 0x00329443, - 0x002e2e46, - 0x002f6246, - 0x0024b9c3, - 0x002f70c3, - 0x002f7686, - 0x002f7c04, - 0x00238f86, - 0x002c2305, - 0x002f7f8a, - 0x00234384, - 0x002f8dc4, - 0x00348e4a, - 0x66e09182, - 0x0026e745, - 0x002fa88a, - 0x002fb545, - 0x002fc0c4, - 0x002fc1c6, - 0x002fc344, - 0x0022b0c6, - 0x6721a542, - 0x002acdc6, - 0x003860c5, - 0x00201287, - 0x0022de46, - 0x0023c804, - 0x002cb187, - 0x00330346, - 0x0026bbc5, - 0x002cadc7, - 0x0039c807, - 0x0039c80e, - 0x0021d906, - 0x0022fa45, - 0x0027fe47, - 0x002e5303, - 0x002e5307, - 0x0020fc85, - 0x00214644, - 0x00230682, - 0x0030eec7, - 0x002eed44, - 0x00230a04, - 0x00260b0b, - 0x00220c03, - 0x002824c7, - 0x00220c04, - 0x0029ec07, - 0x00372f43, - 0x0032f68d, - 0x00388848, - 0x0024fec4, - 0x0024fec5, - 0x002fe445, - 0x002fcb83, - 0x6760f082, - 0x002fdbc3, - 0x002fde83, - 0x0020f184, - 0x0027ad05, - 0x0021fb07, - 0x00209f06, - 0x00369383, - 0x002d518b, - 0x0037360b, - 0x002501cb, - 0x0027384a, - 0x0029d90b, - 0x002a034b, - 0x002c1e4c, - 0x002ccfd1, - 0x002ce80a, - 0x0033cf8b, - 0x0034b58b, - 0x0037244a, - 0x003adb4a, - 0x003af10d, - 0x002ff6ce, - 0x003010cb, - 0x0030138a, - 0x00302ad1, - 0x00302f0a, - 0x0030340b, - 0x0030394e, - 0x0030450c, - 0x00304c4b, - 0x00304f0e, - 0x0030528c, - 0x00305a0a, - 0x00306c0c, - 0x67b06f0a, - 0x00308109, - 0x0030a24a, - 0x0030a4ca, - 0x0030a74b, - 0x0030e40e, - 0x0030e791, - 0x00317c89, - 0x00317eca, - 0x00318a0b, - 0x0031b70a, - 0x0031c256, - 0x0031da4b, - 0x0032338a, - 0x00323d8a, - 0x00326c4b, - 0x0032c249, - 0x00330009, - 0x0033084d, - 0x0033160b, - 0x0033264b, - 0x0033300b, - 0x003335c9, - 0x00333c0e, - 0x0033404a, - 0x0033624a, - 0x0033678a, - 0x00336dcb, - 0x0033760b, - 0x003378cd, - 0x0033910d, - 0x00339690, - 0x00339b4b, - 0x0033a44c, - 0x0033b24b, - 0x0033d58b, - 0x0034048b, - 0x0034484b, - 0x003452cf, - 0x0034568b, - 0x0034624a, - 0x00346889, - 0x00346cc9, - 0x0034798b, - 0x00347c4e, - 0x003494cb, - 0x0034a14f, - 0x0034c90b, - 0x0034cbcb, - 0x0034ce8b, - 0x0034d2ca, - 0x00350f09, - 0x00353e8f, - 0x003588cc, - 0x00358d4c, - 0x0035938e, - 0x00359bcf, - 0x00359f8e, - 0x0035aa90, - 0x0035ae8f, - 0x0035ce8e, - 0x0035d34c, - 0x0035d652, - 0x0035fc11, - 0x003601ce, - 0x0036060e, - 0x00360b4e, - 0x00360ecf, - 0x0036128e, - 0x00361613, - 0x00361ad1, - 0x00361f0e, - 0x0036238c, - 0x003627d3, - 0x00362f10, - 0x0036430c, - 0x0036460c, - 0x00364acb, - 0x00367b0e, - 0x00367f8b, - 0x003683cb, - 0x0036990c, - 0x0037174a, - 0x00371c4c, - 0x00371f4c, - 0x00372249, - 0x00377c0b, - 0x00377ec8, - 0x00378389, - 0x0037838f, - 0x00379b8b, - 0x0037a60a, - 0x0037cd8c, - 0x0037f149, - 0x003812c8, - 0x0038178b, - 0x0038304b, - 0x00383b4a, - 0x00383dcb, - 0x003844cc, - 0x003850c8, - 0x00388a4b, - 0x0038b84b, - 0x0038f48b, - 0x00390ccb, - 0x0039c38b, - 0x0039c649, - 0x0039cb8d, - 0x003a274a, - 0x003a3697, - 0x003a44d8, - 0x003a6f49, - 0x003a814b, - 0x003a8d14, - 0x003a920b, - 0x003a978a, - 0x003a9fca, - 0x003aa24b, - 0x003ab210, - 0x003ab611, - 0x003abeca, - 0x003ad14d, - 0x003ad84d, - 0x003af80b, - 0x003b0686, - 0x0021fa83, - 0x00215b83, - 0x0037f686, - 0x00289545, - 0x00220787, - 0x0033ce46, - 0x01629c02, - 0x002aa849, - 0x00399284, - 0x002cb548, - 0x00243cc3, - 0x002e0ec7, - 0x00232142, - 0x002a7003, - 0x67e03c02, - 0x002bd3c6, - 0x002be9c4, - 0x00328b84, - 0x00238383, - 0x00238385, - 0x686c8302, - 0x002d6944, - 0x00273cc7, - 0x01660ac2, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00201543, - 0x002050c2, - 0x001795c8, - 0x00202682, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002169c3, - 0x00313696, - 0x00316853, - 0x00308989, - 0x0020c748, - 0x002e4709, - 0x002faa06, - 0x00309790, - 0x0033bb53, - 0x00207048, - 0x0025b5c7, - 0x00278587, - 0x0036ff8a, - 0x003696c9, - 0x00342409, - 0x003a090b, - 0x0031e606, - 0x0022400a, - 0x00225906, - 0x00398e83, - 0x002f1045, - 0x00229408, - 0x0035e50d, - 0x00354a4c, - 0x00385d87, - 0x00303f8d, - 0x0020c844, - 0x0023320a, - 0x00233b4a, - 0x0023400a, - 0x0033be47, - 0x0023cd47, - 0x0023efc4, - 0x0025fe06, - 0x0031e9c4, - 0x002f2d48, - 0x002a3e89, - 0x0038df46, - 0x0038df48, - 0x0024180d, - 0x002bb789, - 0x0035cc88, - 0x00215987, - 0x0031920a, - 0x0024a346, - 0x0025abc7, - 0x00227384, - 0x00245e87, - 0x0037fd0a, - 0x002e2f8e, - 0x0020a6c5, - 0x002fc8cb, - 0x002f1689, - 0x0026ca49, - 0x0029a747, - 0x0039750a, - 0x00367047, - 0x002f1c89, - 0x00354f08, - 0x00270acb, - 0x002ca385, - 0x0030064a, - 0x0029ff49, - 0x003293ca, - 0x002beb4b, - 0x00245d8b, - 0x003a0695, - 0x002cfa85, - 0x00215a05, - 0x002dc58a, - 0x0031c9ca, - 0x002e5f87, - 0x00215a43, - 0x002a5e48, - 0x002c5e8a, - 0x00219e06, - 0x0023e189, - 0x00264ec8, - 0x002dc804, - 0x0024b889, - 0x002b37c8, - 0x003313c7, - 0x0027a346, - 0x0029cb47, - 0x0029b787, - 0x0023ea05, - 0x0025538c, - 0x0024fec5, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x0022f303, - 0x0024a143, - 0x0021d583, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x00202682, - 0x00202a82, - 0x00234242, - 0x00200b42, - 0x00202342, - 0x002e6002, - 0x0462f303, - 0x00215403, - 0x00205c03, - 0x002d60c3, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00236d43, - 0x001795c8, - 0x002e9a04, - 0x00252407, - 0x00254783, - 0x002df504, - 0x00232043, - 0x00282983, - 0x002d60c3, - 0x002050c2, - 0x00141d03, - 0x05602682, - 0x00234242, - 0x0017c544, - 0x00200282, - 0x000dbd04, - 0x001795c8, - 0x002050c3, - 0x002c81c3, - 0x05e2f303, - 0x00233204, - 0x06215403, - 0x066d60c3, - 0x00208202, - 0x0037c544, - 0x0024a143, - 0x002f0e83, - 0x00202742, - 0x00202d43, - 0x00216ec2, - 0x002e34c3, - 0x002004c2, - 0x00201643, - 0x00264f83, - 0x00200f42, - 0x001795c8, - 0x002050c3, - 0x002f0e83, - 0x00202742, - 0x002e34c3, - 0x002004c2, - 0x00201643, - 0x00264f83, - 0x00200f42, - 0x002e34c3, - 0x002004c2, - 0x00201643, - 0x00264f83, - 0x00200f42, - 0x0022f303, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0020be42, - 0x0021e703, - 0x001795c8, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00202802, - 0x00355284, - 0x0020c604, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024a143, - 0x00202d43, - 0x002eb585, - 0x00213ac2, - 0x002050c2, - 0x001795c8, - 0x002d60c3, - 0x002533c1, - 0x00231681, - 0x0020b881, - 0x0020b8c1, - 0x0020b901, - 0x002593c1, - 0x00254801, - 0x0024c801, - 0x002cd1c1, - 0x002fed01, - 0x00200101, - 0x00200001, - 0x001795c8, - 0x00200301, - 0x00200381, - 0x00200081, - 0x00201101, - 0x00200641, - 0x00200a81, - 0x00200041, - 0x002042c1, - 0x00200ec1, - 0x00200201, - 0x00200181, - 0x00200601, - 0x00200281, - 0x00204401, - 0x00200401, - 0x002002c1, - 0x002004c1, - 0x00200141, - 0x00200441, - 0x002000c1, - 0x00200f41, - 0x00209f01, - 0x002018c1, - 0x00203c01, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x00200282, - 0x00202d43, - 0x00120ac7, - 0x0001a0c6, - 0x0001894a, - 0x00085148, - 0x00050648, - 0x00050a07, - 0x000534c6, - 0x000c8b05, - 0x000546c5, - 0x0006a4c6, - 0x00141846, - 0x0021db44, - 0x0031dcc7, - 0x001795c8, - 0x002cb284, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x002d60c3, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00213ac2, - 0x002b2603, - 0x00214d43, - 0x00270583, - 0x00200502, - 0x00247b43, - 0x00201383, - 0x00203a43, - 0x00200001, - 0x00206943, - 0x00274444, - 0x00328203, - 0x00309f83, - 0x0021ed83, - 0x0037e303, - 0x0a22f303, - 0x00238c04, - 0x0021ed43, - 0x00202643, - 0x00215403, - 0x00235d83, - 0x0021bf03, - 0x0029be03, - 0x00309f03, - 0x00228943, - 0x00214b83, - 0x0024ae04, - 0x0023c9c2, - 0x0024fc43, - 0x00258703, - 0x00276a83, - 0x00253303, - 0x00322703, - 0x002d60c3, - 0x00331003, - 0x002212c3, - 0x0037c383, - 0x0021a003, - 0x00356143, - 0x002e6583, - 0x003ac3c3, - 0x00200c83, - 0x0020c943, - 0x0021e083, - 0x0021da42, - 0x0028cb83, - 0x0024a143, - 0x01601543, - 0x00224483, - 0x002368c3, - 0x00213903, - 0x00202d43, - 0x0038d1c3, - 0x0021e703, - 0x00232f03, - 0x002f7143, - 0x002e3683, - 0x0033b8c5, - 0x00226a03, - 0x002e36c3, - 0x002ea7c3, - 0x00209e84, - 0x00372ac3, - 0x00330643, - 0x002727c3, - 0x00236d43, - 0x00213ac2, - 0x0023ab83, - 0x002f9bc4, - 0x00230a04, - 0x00243fc3, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x00202d43, - 0x0b62f303, - 0x002d60c3, - 0x0021e083, - 0x002048c2, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00003c02, - 0x00202142, - 0x0021d982, - 0x001795c8, - 0x00002682, - 0x00237842, - 0x0020d042, - 0x0022c342, - 0x00204682, - 0x0020bd82, - 0x000546c5, - 0x00203c82, - 0x00202742, - 0x00201842, - 0x00200982, - 0x00205702, - 0x003845c2, - 0x002066c2, - 0x0021d082, - 0x00115fcd, - 0x000ec889, - 0x000453cb, - 0x000cc408, - 0x000d12c9, - 0x002d60c3, - 0x001795c8, - 0x001795c8, - 0x00051906, - 0x002050c2, - 0x0021db44, - 0x00202682, - 0x0022f303, - 0x00202a82, - 0x00215403, - 0x00200fc2, - 0x002cb284, - 0x0024af03, - 0x0020ab02, - 0x0024a143, - 0x00200282, - 0x00202d43, - 0x00215a06, - 0x0030ad0f, - 0x006fe3c3, - 0x001795c8, - 0x00202682, - 0x00205c03, - 0x002d60c3, - 0x0021e083, - 0x00202682, - 0x0022f303, - 0x002d60c3, - 0x0024a143, - 0x002050c2, - 0x00207642, - 0x0e734b09, - 0x002094c2, - 0x0ee2f303, - 0x0023dbc2, - 0x00215403, - 0x00219fc2, - 0x002281c2, - 0x002d60c3, - 0x00231302, - 0x00250182, - 0x0025a042, - 0x00207682, - 0x00288e02, - 0x00200a82, - 0x00201702, - 0x0020a402, - 0x0026ec82, - 0x00216442, - 0x002a8382, - 0x0023bcc2, - 0x0030fd42, - 0x0022fcc2, - 0x0021e083, - 0x00204042, - 0x0024a143, - 0x00241a02, - 0x0024c5c2, - 0x00202d43, - 0x00247bc2, - 0x00204842, - 0x0024d302, - 0x002016c2, - 0x002198c2, - 0x002ccf82, - 0x002140c2, - 0x002424c2, - 0x00226d42, - 0x0030138a, - 0x0034624a, - 0x0037b8ca, - 0x003b0802, - 0x00209b02, - 0x0023d202, - 0x0e831487, - 0x00052a8a, - 0x0f334b09, - 0x0f652a8a, - 0x0002ca42, - 0x002451c4, - 0x0fe2f303, - 0x00215403, - 0x00246ec4, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x00226a03, - 0x0021d903, - 0x001795c8, - 0x01453444, - 0x00052cc5, - 0x00051c0a, - 0x00106b82, - 0x0017ab06, - 0x10734b09, - 0x00120c87, - 0x00000e02, - 0x001a83ca, - 0x000d58c7, - 0x001795c8, - 0x000fd4c8, - 0x0000d5c7, - 0x1181e20b, - 0x00014f02, - 0x00070d07, - 0x000047ca, - 0x001a030f, - 0x0015f28f, - 0x0001ed82, - 0x00002682, - 0x0009bd48, - 0x000ebfca, - 0x000e7148, - 0x00003f42, - 0x0012828b, - 0x0016d488, - 0x0007c0c7, - 0x000d59ca, - 0x000678cb, - 0x0016c489, - 0x0016d387, - 0x000f4bcc, - 0x0018d647, - 0x000267ca, - 0x00125908, - 0x000f124e, - 0x0005510e, - 0x000d570b, - 0x000e60cb, - 0x000ec5cb, - 0x0001a0c9, - 0x0001c0cb, - 0x0001d3cd, - 0x000249cb, - 0x00025d0d, - 0x0002ea8d, - 0x0002f88a, - 0x0003084b, - 0x00062a0b, - 0x00067f85, - 0x00107a50, - 0x0001c80f, - 0x00121b0f, - 0x000275cd, - 0x00074250, - 0x000072c2, - 0x00120948, - 0x11edca05, - 0x00045b0b, - 0x0004e108, - 0x000e628a, - 0x00059449, - 0x00060287, - 0x000605c7, - 0x00060787, - 0x00060dc7, - 0x000617c7, - 0x00061c87, - 0x00063047, - 0x00064bc7, - 0x000653c7, - 0x000656c7, - 0x00066007, - 0x000661c7, - 0x00066387, - 0x00066547, - 0x00066847, - 0x00066d87, - 0x00068f47, - 0x00069287, - 0x00069a47, - 0x0006ab07, - 0x0006acc7, - 0x0006b0c7, - 0x0006b4c7, - 0x0006b6c7, - 0x0006c287, - 0x0006c447, - 0x0006c607, - 0x0006cc87, - 0x0006d547, - 0x0006db07, - 0x0006f647, - 0x0006f907, - 0x00071107, - 0x000712c7, - 0x00071647, - 0x000723c7, - 0x00072887, - 0x00072c87, - 0x00073507, - 0x000736c7, - 0x00073ac7, - 0x00074807, - 0x00074b07, - 0x00075087, - 0x00075247, - 0x000755c7, - 0x00075a87, - 0x0000d142, - 0x000436ca, - 0x000ce507, - 0x120c368b, - 0x014c3696, - 0x0001f591, - 0x000d8c8a, - 0x0009bbca, - 0x00051906, - 0x000bdecb, - 0x0000a6c2, - 0x000a8f51, - 0x000a1349, - 0x0008cf89, - 0x0000a402, - 0x000718ca, - 0x0009d709, - 0x0009de0f, - 0x0009e84e, - 0x000a0188, - 0x00009f82, - 0x00070909, - 0x0016f4ce, - 0x0012db0c, - 0x000cd98f, - 0x0019458e, - 0x0000da4c, - 0x00014989, - 0x00019451, - 0x0001b0c8, - 0x0002ff12, - 0x000d4d4d, - 0x0019224d, - 0x00041ccb, - 0x00042955, - 0x00043589, - 0x00058e8a, - 0x0005a849, - 0x0006a710, - 0x0007210b, - 0x0007b48f, - 0x0007cb8b, - 0x00080fcc, - 0x00085d10, - 0x00146fca, - 0x0008ca4d, - 0x0009184e, - 0x00096f0a, - 0x00098c8c, - 0x0009b454, - 0x000a0fd1, - 0x000a460b, - 0x000a59cf, - 0x000a684d, - 0x0012d48e, - 0x0013128c, - 0x000eaa8c, - 0x0012d18b, - 0x0016b44e, - 0x000aec90, - 0x000b3e8b, - 0x000b450d, - 0x000b534f, - 0x000b69cc, - 0x0018ddce, - 0x001185d1, - 0x000bc44c, - 0x000c69c7, - 0x000d2e0d, - 0x000dd90c, - 0x000df010, - 0x0011200d, - 0x00163d07, - 0x000eef90, - 0x000f3f08, - 0x0011b94b, - 0x0016d00f, - 0x00022fc8, - 0x000d8e8d, - 0x00187210, - 0x000aa6c3, - 0x0000aa02, - 0x0002ee89, - 0x00054f0a, - 0x00012303, - 0x00107251, - 0x00123ac7, - 0x000cd410, - 0x000ce145, - 0x00116d88, - 0x0019d84a, - 0x0012b0c7, - 0x00001542, - 0x00053dca, - 0x00121e49, - 0x00038c8a, - 0x001a008f, - 0x000401cb, - 0x0012850c, - 0x001287d2, - 0x000a9705, - 0x0011a74a, - 0x126db045, - 0x00110fc3, - 0x001845c2, - 0x000e39ca, - 0x0004f9c8, - 0x0015f207, - 0x00002282, - 0x0000b082, - 0x000004c2, - 0x00182050, - 0x00002542, - 0x00031f8f, - 0x0006a4c6, - 0x000d0f8e, - 0x0008858b, - 0x000c49c8, - 0x00075849, - 0x00002552, - 0x0015cb4d, - 0x0017f7c8, - 0x00045289, - 0x000475cd, - 0x00048089, - 0x0004a4cb, - 0x0004b208, - 0x00051a48, - 0x00058408, - 0x0005bf49, - 0x0005c14a, - 0x0005f90c, - 0x000eca8a, - 0x000f7187, - 0x0001194d, - 0x000ed00b, - 0x0019908c, - 0x00061010, - 0x00001142, - 0x0009838d, - 0x00002402, - 0x00001882, - 0x000f70ca, - 0x000d8b8a, - 0x000e0dcb, - 0x00062bcc, - 0x000fd24e, - 0x0000f24d, - 0x00117688, - 0x00003c02, - 0x10b4290e, - 0x10c31487, - 0x11031489, - 0x00010603, - 0x116648cc, - 0x0002ca42, - 0x00122f51, - 0x00142851, - 0x001536d1, - 0x0002ca51, - 0x0006480f, - 0x0010d98c, - 0x0011b3cd, - 0x0012690d, - 0x0012bd15, - 0x00135f4c, - 0x00148590, - 0x0017704c, - 0x0010570c, - 0x0014bb09, - 0x0002ca42, - 0x0012300e, - 0x0014290e, - 0x0015378e, - 0x0002cb0e, - 0x000648cc, - 0x0010da49, - 0x00136009, - 0x0012bf0d, - 0x00177109, - 0x001057c9, - 0x001a6a03, - 0x000ca243, - 0x0002ca42, - 0x000d7785, - 0x001a83c4, - 0x00120c84, - 0x0142aa43, - 0x01411803, - 0x000f1d04, - 0x0000f243, - 0x002050c2, - 0x00202682, - 0x00202a82, - 0x0020bf82, - 0x00200fc2, - 0x00200282, - 0x002004c2, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c383, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x0024a143, - 0x00202d43, - 0x0006ec03, - 0x002d60c3, - 0x002050c2, - 0x00341d03, - 0x1422f303, - 0x003b0247, - 0x002d60c3, - 0x0035ea43, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0025564a, - 0x00215a05, - 0x0021e703, - 0x00200142, - 0x001795c8, - 0x001795c8, - 0x00002682, - 0x0010eb02, - 0x001795c8, - 0x0002f303, - 0x000f15c7, - 0x000c7f8f, - 0x00065bc4, - 0x0016c60a, - 0x0012d747, - 0x001a67ca, - 0x000be34a, - 0x0000720d, - 0x00141d03, - 0x001795c8, - 0x00002682, - 0x00046ec4, - 0x00046b03, - 0x000eb585, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00201383, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x0028d143, - 0x0021d903, - 0x00201383, - 0x0021db44, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00225183, - 0x0022f303, - 0x00215403, - 0x0020e383, - 0x00205c03, - 0x002d60c3, - 0x0037c544, - 0x00376343, - 0x0020c943, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x00205683, - 0x1662f303, - 0x00215403, - 0x002bc643, - 0x002d60c3, - 0x00281103, - 0x0020c943, - 0x00202d43, - 0x00206d43, - 0x00324c44, - 0x001795c8, - 0x16e2f303, - 0x00215403, - 0x002a0243, - 0x002d60c3, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x00221143, - 0x001795c8, - 0x1762f303, - 0x00215403, - 0x00205c03, - 0x00201543, - 0x00202d43, - 0x001795c8, - 0x01431487, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0031e7c5, - 0x001795c8, - 0x0001a0c2, - 0x00030a43, - 0x0024f2c8, - 0x00279087, - 0x0021db44, - 0x00341546, - 0x00348446, - 0x001795c8, - 0x00234983, - 0x00321509, - 0x002ae315, - 0x000ae31f, - 0x0022f303, - 0x00327592, - 0x000fdf06, - 0x0013a705, - 0x000e628a, - 0x00059449, - 0x0032734f, - 0x002cb284, - 0x00229ec5, - 0x00355f10, - 0x0020c947, - 0x00201543, - 0x00331a08, - 0x002d780a, - 0x00216044, - 0x002daa83, - 0x00215a06, - 0x00200142, - 0x0038548b, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002e1543, - 0x00202682, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0035ea43, - 0x00224283, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x0024a143, - 0x00202d43, - 0x002050c2, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0021db44, - 0x0022f303, - 0x00215403, - 0x0020f5c4, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x002212c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00253a43, - 0x0000ca83, - 0x0015ea43, - 0x0024a143, - 0x00202d43, - 0x0030138a, - 0x0031c009, - 0x0033dc4b, - 0x0033e5ca, - 0x0034624a, - 0x0035208b, - 0x0036918a, - 0x0037174a, - 0x0037b8ca, - 0x0037bb4b, - 0x0039d589, - 0x0039f50a, - 0x0039fa4b, - 0x003a94cb, - 0x003aeeca, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00260284, - 0x00219242, - 0x00212284, - 0x002765c5, - 0x00201383, - 0x0021db44, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x00246ec4, - 0x002cb284, - 0x0037c544, - 0x0020c943, - 0x0024a143, - 0x00202d43, - 0x00298545, - 0x00225183, - 0x0021e703, - 0x00215543, - 0x0024ffc4, - 0x00253384, - 0x00270585, - 0x001795c8, - 0x002f8944, - 0x00222d46, - 0x00283b84, - 0x00202682, - 0x0035b307, - 0x00249907, - 0x00244a04, - 0x00257d45, - 0x00312205, - 0x002a3645, - 0x0037c544, - 0x003145c8, - 0x0035c746, - 0x002e3cc8, - 0x00238685, - 0x002ca385, - 0x0023ff04, - 0x00202d43, - 0x002dbd04, - 0x00351246, - 0x00215b03, - 0x0024ffc4, - 0x00258885, - 0x00237484, - 0x0020f0c4, - 0x00200142, - 0x0024d246, - 0x003916c6, - 0x002f6105, - 0x002050c2, - 0x00341d03, - 0x1ca02682, - 0x00236f84, - 0x00200fc2, - 0x0021e083, - 0x0020b302, - 0x0024a143, - 0x00200282, - 0x002169c3, - 0x0021d903, - 0x001795c8, - 0x001795c8, - 0x002d60c3, - 0x002050c2, - 0x1d602682, - 0x002d60c3, - 0x00266303, - 0x00376343, - 0x0031cdc4, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x002050c2, - 0x1de02682, - 0x0022f303, - 0x0024a143, - 0x00202d43, - 0x00209902, - 0x00213ac2, - 0x0035ea43, - 0x002d3c03, - 0x002050c2, - 0x001795c8, - 0x00202682, - 0x00215403, - 0x00246ec4, - 0x002086c3, - 0x002d60c3, - 0x002212c3, - 0x0021e083, - 0x0024a143, - 0x00218e83, - 0x00202d43, - 0x00215a43, - 0x00124293, - 0x00126ed4, - 0x00014d86, - 0x0001a0c6, - 0x00050487, - 0x001995c9, - 0x0011fb4a, - 0x0008500d, - 0x00115ccc, - 0x0017b40a, - 0x000546c5, - 0x00165588, - 0x0006a4c6, - 0x00141846, - 0x002072c2, - 0x0022f303, - 0x00026745, - 0x0001f586, - 0x000a7303, - 0x00199585, - 0x0000c543, - 0x000bdf8c, - 0x001aca08, - 0x0013efc8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002050c2, - 0x00202682, - 0x002d60c3, - 0x00208202, - 0x0024a143, - 0x00202d43, - 0x002169c3, - 0x00359bcf, - 0x00359f8e, - 0x001795c8, - 0x0022f303, - 0x00042147, - 0x00215403, - 0x002d60c3, - 0x0024af03, - 0x0024a143, - 0x00202d43, - 0x00220a43, - 0x00375d07, - 0x00200bc2, - 0x0029c349, - 0x002001c2, - 0x0038234b, - 0x00286cca, - 0x0028b0c9, - 0x00201982, - 0x002535c6, - 0x00255a15, - 0x00382495, - 0x00256bd3, - 0x00382a13, - 0x00203082, - 0x00203945, - 0x0031e18c, - 0x0021b48b, - 0x0023a8c5, - 0x002043c2, - 0x002003c2, - 0x0036de46, - 0x00200e02, - 0x00251f06, - 0x00325a8d, - 0x0036d60c, - 0x00307ac4, - 0x00200102, - 0x00204182, - 0x002302c8, - 0x00200dc2, - 0x00373886, - 0x0026eec4, - 0x00255bd5, - 0x00256d53, - 0x00210543, - 0x0034124a, - 0x0038cf07, - 0x00327c09, - 0x0022b807, - 0x00302e02, - 0x00200002, - 0x003ae3c6, - 0x0020c282, - 0x001795c8, - 0x00210382, - 0x00207f02, - 0x00396a47, - 0x0020fd47, - 0x0021fcc5, - 0x00214f02, - 0x00221087, - 0x00221248, - 0x0022ca02, - 0x002e3782, - 0x00230c82, - 0x00200302, - 0x00239dc8, - 0x00218f03, - 0x00246cc8, - 0x002ca70d, - 0x00214e43, - 0x00322288, - 0x0023504f, - 0x0023540e, - 0x0021d9ca, - 0x00292391, - 0x00292810, - 0x002aff0d, - 0x002b024c, - 0x0020c007, - 0x003413c7, - 0x00341609, - 0x0023d282, - 0x002068c2, - 0x002549cc, - 0x00254ccb, - 0x00201a82, - 0x0032d346, - 0x002047c2, - 0x0020c842, - 0x0021ed82, - 0x00202682, - 0x003a6d44, - 0x0023af87, - 0x00207102, - 0x0023eb47, - 0x0023fdc7, - 0x00212a02, - 0x00205102, - 0x00242005, - 0x00227542, - 0x0026318e, - 0x0027a0cd, - 0x00215403, - 0x0024d88e, - 0x0036fa4d, - 0x0035f183, - 0x00203282, - 0x00208904, - 0x00243e42, - 0x00211742, - 0x00346a85, - 0x0034d107, - 0x00368642, - 0x0020bf82, - 0x00246507, - 0x0024bd08, - 0x0023c9c2, - 0x002a9786, - 0x0025484c, - 0x00254b8b, - 0x002046c2, - 0x0025c5cf, - 0x0025c990, - 0x0025cd8f, - 0x0025d155, - 0x0025d694, - 0x0025db8e, - 0x0025df0e, - 0x0025e28f, - 0x0025e64e, - 0x0025e9d4, - 0x0025eed3, - 0x0025f38d, - 0x00275c49, - 0x00285bc3, - 0x00200c02, - 0x0030bdc5, - 0x002086c6, - 0x00200fc2, - 0x002db947, - 0x002d60c3, - 0x0020a6c2, - 0x002d41c8, - 0x002925d1, - 0x00292a10, - 0x00203d02, - 0x002279c7, - 0x002024c2, - 0x00263d87, - 0x0020aa02, - 0x0024f0c9, - 0x0036de07, - 0x00282748, - 0x00228a86, - 0x002d3b03, - 0x0031f585, - 0x002362c2, - 0x00203802, - 0x003ae7c5, - 0x00215d85, - 0x002067c2, - 0x00216183, - 0x00237507, - 0x003a50c7, - 0x00200242, - 0x002fe084, - 0x00203b43, - 0x002bab09, - 0x002d5588, - 0x00212942, - 0x00205d42, - 0x00227dc7, - 0x0022a945, - 0x0029e108, - 0x00203607, - 0x00201343, - 0x00281886, - 0x002afd8d, - 0x002b010c, - 0x0027a8c6, - 0x0020d042, - 0x002e5e02, - 0x00204502, - 0x00234ecf, - 0x002352ce, - 0x00312287, - 0x0020a142, - 0x00306805, - 0x00306806, - 0x00260542, - 0x00204042, - 0x00224286, - 0x00263cc3, - 0x00263cc6, - 0x002bbe05, - 0x002bbe0d, - 0x002bc995, - 0x002bd14c, - 0x002bd94d, - 0x002be5d2, - 0x00200542, - 0x00207342, - 0x00200882, - 0x002e24c6, - 0x0032d9c6, - 0x00201542, - 0x00208746, - 0x00201842, - 0x003a8805, - 0x00202342, - 0x002632c9, - 0x0026dd0c, - 0x0026e04b, - 0x00200282, - 0x0024c148, - 0x00209e42, - 0x00204402, - 0x0021b246, - 0x003604c5, - 0x0021a2c7, - 0x002585c5, - 0x00292205, - 0x002421c2, - 0x003419c2, - 0x00205702, - 0x0027b787, - 0x0022d44d, - 0x0022d7cc, - 0x002731c7, - 0x002a9702, - 0x00224b82, - 0x00240dc8, - 0x0022f008, - 0x002cf888, - 0x002d8e44, - 0x0036b6c7, - 0x002d67c3, - 0x0026f082, - 0x00209082, - 0x002d95c9, - 0x00320d87, - 0x00205042, - 0x00271785, - 0x00253ec2, - 0x00231542, - 0x00277a03, - 0x00277a06, - 0x002e1542, - 0x002e3442, - 0x00200e42, - 0x003087c6, - 0x00208847, - 0x002002c2, - 0x00204942, - 0x00246b0f, - 0x0024d6cd, - 0x00282b0e, - 0x0036f8cc, - 0x00202d82, - 0x00200b02, - 0x002288c5, - 0x003add06, - 0x00214c02, - 0x0020c502, - 0x00202282, - 0x00203584, - 0x002ca584, - 0x00338b46, - 0x002004c2, - 0x00278907, - 0x00224c43, - 0x00228fc8, - 0x0022a488, - 0x002d4bc7, - 0x00391e86, - 0x00200802, - 0x00239d43, - 0x00259a07, - 0x00266c06, - 0x002e2405, - 0x00345ec8, - 0x00205442, - 0x0030c907, - 0x00211942, - 0x002ea082, - 0x00200702, - 0x002d9389, - 0x00208c42, - 0x00200b82, - 0x00273443, - 0x00342607, - 0x00202782, - 0x0026de8c, - 0x0026e18b, - 0x0027a946, - 0x0020c485, - 0x0021a602, - 0x002036c2, - 0x002adb46, - 0x0022e203, - 0x0032b4c7, - 0x00248242, - 0x00202882, - 0x00255895, - 0x00382655, - 0x00256a93, - 0x00382b93, - 0x00258987, - 0x00274c88, - 0x00274c90, - 0x002766cf, - 0x00286a93, - 0x0028ae92, - 0x0029bf10, - 0x002a328f, - 0x00363e92, - 0x0031bbd1, - 0x0036a4d3, - 0x0034f292, - 0x002b2a4f, - 0x002b5d0e, - 0x002bb992, - 0x002c3bd1, - 0x002c60cf, - 0x002c700e, - 0x002c8511, - 0x002cee50, - 0x002d6192, - 0x002d9191, - 0x002de2c6, - 0x002dfc87, - 0x00369507, - 0x00200d02, - 0x0027e345, - 0x003438c7, - 0x00213ac2, - 0x0020b0c2, - 0x0022d005, - 0x00215483, - 0x00270806, - 0x0022d60d, - 0x0022d94c, - 0x002000c2, - 0x0031e00b, - 0x0021b34a, - 0x002ea3ca, - 0x002abdc9, - 0x002d80cb, - 0x0020374d, - 0x0035974c, - 0x0022368a, - 0x00224dcc, - 0x0022700b, - 0x0023a70c, - 0x0033ae8b, - 0x0026dc83, - 0x00275746, - 0x002c8fc2, - 0x002e3f42, - 0x0023e503, - 0x00202602, - 0x00203243, - 0x00262186, - 0x0025d307, - 0x00256586, - 0x002ec188, - 0x0022ed08, - 0x002f2746, - 0x00203442, - 0x002f5acd, - 0x002f5e0c, - 0x002cb347, - 0x002f8807, - 0x00214dc2, - 0x002346c2, - 0x00259982, - 0x002041c2, - 0x00202682, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x002169c3, - 0x002050c2, - 0x00200342, - 0x20e89fc5, - 0x21201e45, - 0x21708486, - 0x001795c8, - 0x21aa9e45, - 0x00202682, - 0x00202a82, - 0x21e2bac5, - 0x2227ca85, - 0x2267da07, - 0x22a12e89, - 0x22e67684, - 0x00200fc2, - 0x0020a6c2, - 0x23368685, - 0x2368b909, - 0x23b6c308, - 0x23ea66c5, - 0x242ba287, - 0x24620408, - 0x24ad1645, - 0x24e01186, - 0x2526e809, - 0x256c40c8, - 0x25ab4348, - 0x25e9518a, - 0x26247f04, - 0x266c4345, - 0x26aafb08, - 0x26e66ec5, - 0x00218f82, - 0x2723cb03, - 0x2769b006, - 0x27a433c8, - 0x27f98846, - 0x28376988, - 0x2871e4c6, - 0x28b36544, - 0x002032c2, - 0x28e34b47, - 0x292a1c44, - 0x29677f87, - 0x29ba1287, - 0x00200282, - 0x29e93845, - 0x2a20c684, - 0x2a711cc7, - 0x2aa1e947, - 0x2ae80b06, - 0x2b22e705, - 0x2b68df07, - 0x2bacfbc8, - 0x2bf0c147, - 0x2c2af189, - 0x2c6bdcc5, - 0x2caa0e47, - 0x2ce89706, - 0x2d2537c8, - 0x0037ffcd, - 0x00242349, - 0x002dcb0b, - 0x0024c60b, - 0x0025918b, - 0x0027ae0b, - 0x002fe84b, - 0x002feb0b, - 0x002ff309, - 0x0030160b, - 0x003018cb, - 0x0030268b, - 0x0030318a, - 0x003036ca, - 0x00303ccc, - 0x0030604b, - 0x0030698a, - 0x0031814a, - 0x0032de0e, - 0x0032e8ce, - 0x0032ec4a, - 0x00330b8a, - 0x00331f0b, - 0x003321cb, - 0x00332d4b, - 0x003498cb, - 0x00349eca, - 0x0034ab8b, - 0x0034ae4a, - 0x0034b0ca, - 0x0034b34a, - 0x00369f4b, - 0x0037640b, - 0x00378a8e, - 0x00378e0b, - 0x0038388b, - 0x00384b4b, - 0x00388d0a, - 0x00388f89, - 0x003891ca, - 0x0038a84a, - 0x0039e1cb, - 0x0039fd0b, - 0x003a0bca, - 0x003a29cb, - 0x003a6acb, - 0x003ae90b, - 0x2d67ed08, - 0x2da84789, - 0x2df1aa09, - 0x2e2cb548, - 0x003388c5, - 0x00201903, - 0x00209d84, - 0x00396c45, - 0x002673c6, - 0x0026b845, - 0x00283f84, - 0x002db848, - 0x00218c45, - 0x0028aa44, - 0x00206087, - 0x0029594a, - 0x002ad74a, - 0x0039c1c7, - 0x00201807, - 0x002f3d87, - 0x0035e147, - 0x002ddf45, - 0x0032b8c6, - 0x0033f307, - 0x0026afc4, - 0x00323946, - 0x002efa06, - 0x003aaec5, - 0x0024e604, - 0x002b1786, - 0x00294cc7, - 0x00224646, - 0x00300e07, - 0x0027c243, - 0x0024cac6, - 0x00233985, - 0x0027db07, - 0x002b848a, - 0x00279344, - 0x0021f308, - 0x002a5449, - 0x002cc1c7, - 0x0022c546, - 0x0024c3c8, - 0x003a1609, - 0x0031f184, - 0x00234d44, - 0x002f96c5, - 0x0032cd48, - 0x002b9587, - 0x002a0b89, - 0x00235a88, - 0x002fc3c6, - 0x00241b06, - 0x002905c8, - 0x0036cc06, - 0x00201e45, - 0x00280bc6, - 0x00278288, - 0x00234dc6, - 0x00250ecb, - 0x002872c6, - 0x00291bcd, - 0x00397445, - 0x002a1b06, - 0x002204c5, - 0x002945c9, - 0x0037e6c7, - 0x0037de08, - 0x0037b746, - 0x00290cc9, - 0x002e45c6, - 0x002b8405, - 0x00297c46, - 0x0029dc86, - 0x002bf749, - 0x0031ef86, - 0x00257a47, - 0x002a28c5, - 0x002030c3, - 0x00251045, - 0x0029f247, - 0x00341b86, - 0x00397349, - 0x00308486, - 0x00280e06, - 0x00210a09, - 0x002805c9, - 0x00298b07, - 0x0031f748, - 0x0038b049, - 0x0027dfc8, - 0x00349746, - 0x002c7785, - 0x0030778a, - 0x00280e86, - 0x003b00c6, - 0x0029f8c5, - 0x002a8dc8, - 0x0020e107, - 0x0023278a, - 0x00247306, - 0x00227245, - 0x0022c7c6, - 0x00298207, - 0x0022c407, - 0x002ef505, - 0x002b85c5, - 0x002a7386, - 0x002a7f46, - 0x002a8406, - 0x0032f204, - 0x0027f249, - 0x00285646, - 0x0027e98a, - 0x0028a008, - 0x002e6848, - 0x002ad74a, - 0x0035eb85, - 0x00294c05, - 0x0037f508, - 0x002bf9c8, - 0x0036ecc7, - 0x0032d046, - 0x00310b08, - 0x002dd147, - 0x0027fbc8, - 0x0036b306, - 0x00281608, - 0x002b0606, - 0x00238807, - 0x00291706, - 0x002b1786, - 0x0030214a, - 0x003a6dc6, - 0x002c7789, - 0x002aa146, - 0x002cc90a, - 0x00336549, - 0x002f2846, - 0x00386d44, - 0x0030be8d, - 0x00284a07, - 0x00313b86, - 0x002b4205, - 0x002e4645, - 0x0030c386, - 0x0026ff89, - 0x002ac3c7, - 0x00279b86, - 0x002c7e06, - 0x00284009, - 0x002ba444, - 0x002686c4, - 0x003a42c8, - 0x002e6e06, - 0x0026fb08, - 0x00380dc8, - 0x00312607, - 0x003afd89, - 0x002a8607, - 0x002a9d0a, - 0x0038078f, - 0x0036898a, - 0x002286c5, - 0x002784c5, - 0x0021ae45, - 0x0026ee07, - 0x00204e03, - 0x0031f948, - 0x002f6706, - 0x002f6809, - 0x002c27c6, - 0x00384f07, - 0x00290a89, - 0x0037dd08, - 0x0029f987, - 0x002fe303, - 0x00338945, - 0x00204d85, - 0x0032f04b, - 0x00266f84, - 0x002df2c4, - 0x00277246, - 0x002fe687, - 0x0039a1ca, - 0x0023cb87, - 0x00205747, - 0x0027ca85, - 0x00202a05, - 0x002218c9, - 0x002b1786, - 0x0023ca0d, - 0x00354e45, - 0x002fee43, - 0x0020a283, - 0x003088c5, - 0x0034dd45, - 0x0024c3c8, - 0x0027a5c7, - 0x00268446, - 0x00296006, - 0x0022dfc5, - 0x00236307, - 0x00201a87, - 0x0035c607, - 0x002c43ca, - 0x0024cb88, - 0x0032f204, - 0x002a89c7, - 0x0027c387, - 0x00331886, - 0x00265807, - 0x002aca08, - 0x0031a908, - 0x0026d806, - 0x002e82c8, - 0x002b8cc4, - 0x0033f306, - 0x00210f46, - 0x0037cc06, - 0x003092c6, - 0x00296584, - 0x0035e206, - 0x002b3306, - 0x0028fd46, - 0x0022e546, - 0x0020a146, - 0x002ac846, - 0x00268348, - 0x003237c8, - 0x002c5048, - 0x0026ba48, - 0x0037f486, - 0x00212585, - 0x00278a46, - 0x002a6745, - 0x00388147, - 0x00235b45, - 0x00213703, - 0x00201585, - 0x002a7dc4, - 0x0020a285, - 0x00218143, - 0x00304a87, - 0x00318408, - 0x00300ec6, - 0x002ddbcd, - 0x00278486, - 0x0028f205, - 0x0026da43, - 0x002af4c9, - 0x002ba5c6, - 0x0028f806, - 0x00271844, - 0x00368907, - 0x002371c6, - 0x002a8c05, - 0x0020ecc3, - 0x00202404, - 0x0027c546, - 0x002ab0c4, - 0x0030b048, - 0x00327ec9, - 0x0037ebc9, - 0x00297b4a, - 0x0023f20d, - 0x00373d07, - 0x00398506, - 0x00208244, - 0x00212e89, - 0x00283508, - 0x00284606, - 0x00263546, - 0x00265807, - 0x002c11c6, - 0x00222806, - 0x0035ec86, - 0x003a130a, - 0x00220408, - 0x0022fe05, - 0x002bafc9, - 0x002800ca, - 0x00220688, - 0x00294308, - 0x0028f788, - 0x00201e8c, - 0x00331185, - 0x00296288, - 0x00306706, - 0x002bd7c6, - 0x00384dc7, - 0x0023ca85, - 0x00280d45, - 0x0037ea89, - 0x00212b07, - 0x002f67c5, - 0x00223487, - 0x0020a283, - 0x002b9ac5, - 0x00367908, - 0x002cf607, - 0x002941c9, - 0x002dc805, - 0x00333f44, - 0x00299848, - 0x002ca9c7, - 0x0029fb48, - 0x00375048, - 0x002ee1c5, - 0x00278e06, - 0x00251546, - 0x002dee09, - 0x00311387, - 0x002a6dc6, - 0x0038d307, - 0x0020f283, - 0x00267684, - 0x0029b105, - 0x00267844, - 0x00244044, - 0x0027f987, - 0x00205307, - 0x00279d44, - 0x00294010, - 0x0030c507, - 0x00202a05, - 0x002f018c, - 0x002ddf44, - 0x002b4a08, - 0x00238709, - 0x003af686, - 0x0033f108, - 0x0025b344, - 0x0025b348, - 0x002a9346, - 0x0022e3c8, - 0x0029f506, - 0x002c314b, - 0x002030c5, - 0x002b8c48, - 0x00217644, - 0x002e8aca, - 0x002941c9, - 0x00300546, - 0x002d2448, - 0x003a4085, - 0x002efc84, - 0x002b4906, - 0x0035c4c8, - 0x0027ed08, - 0x00345c46, - 0x0032a084, - 0x00307706, - 0x002a8687, - 0x00277e87, - 0x0026580f, - 0x00206dc7, - 0x002f2907, - 0x002bd685, - 0x002f4f05, - 0x002987c9, - 0x0026a206, - 0x0027e6c5, - 0x002808c7, - 0x002a2688, - 0x0028fe45, - 0x00291706, - 0x0021ee48, - 0x0039884a, - 0x0024db88, - 0x003abac7, - 0x00380bc6, - 0x002baf86, - 0x00204bc3, - 0x00209e43, - 0x00280289, - 0x0038aec9, - 0x002af086, - 0x002dc805, - 0x002a1cc8, - 0x002d2448, - 0x002fa688, - 0x0035ed0b, - 0x002dde07, - 0x002fcd09, - 0x00265a88, - 0x00340884, - 0x002bf848, - 0x00288209, - 0x002a70c5, - 0x0026ed07, - 0x00326145, - 0x0027ec08, - 0x00289e4b, - 0x0028dc50, - 0x002a1905, - 0x0021758c, - 0x00268605, - 0x0027cb03, - 0x0029ef06, - 0x002b2904, - 0x003422c6, - 0x00294cc7, - 0x0021a644, - 0x002ad648, - 0x0031f80d, - 0x002d2305, - 0x0023f704, - 0x00228404, - 0x0033f789, - 0x0029a048, - 0x00308307, - 0x002a93c8, - 0x0027f308, - 0x00279e85, - 0x00320547, - 0x00279e07, - 0x003212c7, - 0x002b85c9, - 0x00237049, - 0x0023ecc6, - 0x002b0446, - 0x00265a46, - 0x00268d45, - 0x00355304, - 0x00201086, - 0x00202186, - 0x00279ec8, - 0x00297ecb, - 0x00279207, - 0x00208244, - 0x00314006, - 0x002dd6c7, - 0x00334645, - 0x00315185, - 0x00203304, - 0x00236fc6, - 0x00201108, - 0x00212e89, - 0x00244c46, - 0x00282e88, - 0x002a8cc6, - 0x00332448, - 0x003acd0c, - 0x00279d46, - 0x0028eecd, - 0x0028f34b, - 0x00257b05, - 0x00201bc7, - 0x0031f086, - 0x0022c2c8, - 0x0023ed49, - 0x002dea48, - 0x00202a05, - 0x002f3107, - 0x0027e0c8, - 0x0035f9c9, - 0x002d9ec6, - 0x0024930a, - 0x0022c048, - 0x002de88b, - 0x002c07cc, - 0x0025b448, - 0x0027bc86, - 0x0031ff48, - 0x00206f07, - 0x002372c9, - 0x0028b80d, - 0x00295c86, - 0x002efb08, - 0x00323689, - 0x002b0e08, - 0x00281708, - 0x002b3bcc, - 0x002b4ec7, - 0x002b6087, - 0x002b8405, - 0x0023c087, - 0x002a2548, - 0x002b4986, - 0x00244acc, - 0x002df988, - 0x002c0ac8, - 0x0035be06, - 0x00204b07, - 0x0023eec4, - 0x0026ba48, - 0x0036fd0c, - 0x0021a64c, - 0x00228745, - 0x00208fc7, - 0x0032a006, - 0x00204a86, - 0x00294788, - 0x00365b04, - 0x0022464b, - 0x00228c8b, - 0x00380bc6, - 0x0031f687, - 0x0024ea45, - 0x0026fa45, - 0x00224786, - 0x003a4045, - 0x00266f45, - 0x002d2747, - 0x00277849, - 0x002873c4, - 0x0031adc5, - 0x002d0545, - 0x0025a408, - 0x002ad485, - 0x00297489, - 0x002df547, - 0x002df54b, - 0x0022db46, - 0x00268089, - 0x0024e548, - 0x00272005, - 0x003213c8, - 0x00237088, - 0x0021bc87, - 0x0033fb87, - 0x0027fa09, - 0x0022e307, - 0x00283d49, - 0x002a37cc, - 0x002af088, - 0x002b1209, - 0x002bae47, - 0x0027f3c9, - 0x00205447, - 0x002c08c8, - 0x0025a745, - 0x0033f286, - 0x002b4248, - 0x002f7d88, - 0x0027ff89, - 0x00266f87, - 0x0024af85, - 0x00211d49, - 0x0038b406, - 0x00289704, - 0x002de706, - 0x00243248, - 0x00244607, - 0x002980c8, - 0x002e8389, - 0x0035bb87, - 0x00295b06, - 0x00201c84, - 0x00201609, - 0x003203c8, - 0x0035bcc7, - 0x0032b9c6, - 0x00204e46, - 0x003b0044, - 0x0032a946, - 0x0020a203, - 0x0024f5c9, - 0x00203086, - 0x0029e345, - 0x00296006, - 0x0029fc85, - 0x0027e548, - 0x0025b187, - 0x0035df86, - 0x0022bb06, - 0x002e6848, - 0x00298947, - 0x00295cc5, - 0x00296508, - 0x0038ac08, - 0x0022c048, - 0x002684c5, - 0x0033f306, - 0x0037e989, - 0x002513c4, - 0x0036cd0b, - 0x0022250b, - 0x0022fd09, - 0x0020a283, - 0x002567c5, - 0x0020d746, - 0x00279688, - 0x00380704, - 0x00300ec6, - 0x002c4509, - 0x002c4b85, - 0x002d2686, - 0x002ca9c6, - 0x0021af04, - 0x00299c0a, - 0x0029e288, - 0x002f7d86, - 0x002e9285, - 0x00201407, - 0x0037e387, - 0x00278e04, - 0x00222747, - 0x0022bfc4, - 0x00235b06, - 0x0021ef83, - 0x002b85c5, - 0x0036d2c5, - 0x002c29c8, - 0x00267785, - 0x00279a89, - 0x0026b887, - 0x0026b88b, - 0x0029ae0c, - 0x0029b94a, - 0x002ba287, - 0x00200843, - 0x00312388, - 0x00268685, - 0x0028fec5, - 0x00338a04, - 0x002c07c6, - 0x00238706, - 0x0032a987, - 0x0020ec0b, - 0x00296584, - 0x0037df84, - 0x002b9104, - 0x002bf346, - 0x0021a644, - 0x0032ce48, - 0x00338805, - 0x0022dd85, - 0x002fa5c7, - 0x00201cc9, - 0x0034dd45, - 0x0037810a, - 0x002a27c9, - 0x0029780a, - 0x003a1449, - 0x002e4284, - 0x002c7ec5, - 0x002c12c8, - 0x00311d8b, - 0x002f96c5, - 0x0038ce06, - 0x002150c4, - 0x00279fc6, - 0x0035ba09, - 0x003140c7, - 0x00308648, - 0x0023f586, - 0x002a8607, - 0x0027ed08, - 0x0038edc6, - 0x00242884, - 0x0035a2c7, - 0x00346ec5, - 0x0034c1c7, - 0x00201184, - 0x0031f006, - 0x00393988, - 0x0028f508, - 0x002f40c7, - 0x00224388, - 0x002b06c5, - 0x0020a0c4, - 0x002e6748, - 0x00224484, - 0x0021adc5, - 0x002eea84, - 0x002dd247, - 0x00285707, - 0x0027f508, - 0x0029fcc6, - 0x00267705, - 0x00279888, - 0x0024dd88, - 0x00297a89, - 0x00222806, - 0x00232808, - 0x002e894a, - 0x003346c8, - 0x002d1645, - 0x00207e86, - 0x0026fe48, - 0x002f31ca, - 0x00324d07, - 0x00283905, - 0x0028e448, - 0x002aac84, - 0x002a8e46, - 0x002b6808, - 0x0020a146, - 0x00325448, - 0x00251207, - 0x00205f86, - 0x00386d44, - 0x0037ae07, - 0x0032cb84, - 0x0035b9c7, - 0x0030028d, - 0x0022fd85, - 0x002cf40b, - 0x0029f606, - 0x0024c248, - 0x003577c4, - 0x00276386, - 0x0027c546, - 0x00320287, - 0x0028eb8d, - 0x002a4487, - 0x002fed88, - 0x0024a8c5, - 0x0028ff88, - 0x002b9506, - 0x002b0748, - 0x00214846, - 0x002e7ac7, - 0x00229f89, - 0x003577c7, - 0x002848c8, - 0x00273c05, - 0x0021fd48, - 0x002049c5, - 0x00240f85, - 0x00352c85, - 0x00222fc3, - 0x00280c44, - 0x0028e645, - 0x0026e809, - 0x002cfd46, - 0x002acb08, - 0x00249cc5, - 0x0032ee87, - 0x00249aca, - 0x002d25c9, - 0x0029db8a, - 0x002c50c8, - 0x002232cc, - 0x0028094d, - 0x003369c3, - 0x00325348, - 0x002023c5, - 0x00398606, - 0x0037db86, - 0x002d0ec5, - 0x0038d409, - 0x00375485, - 0x00279888, - 0x00257946, - 0x0033c546, - 0x00299709, - 0x0038e5c7, - 0x00363bc6, - 0x00249a48, - 0x0037cb08, - 0x002cb747, - 0x0022e54e, - 0x002b9745, - 0x0035f8c5, - 0x0020a048, - 0x0032b2c7, - 0x00203ac2, - 0x002b3744, - 0x003421ca, - 0x0035bd88, - 0x002dd7c6, - 0x00290bc8, - 0x00251546, - 0x00319e88, - 0x002a6dc8, - 0x00240f44, - 0x00333345, - 0x00683b84, - 0x00683b84, - 0x00683b84, - 0x00201e43, - 0x00204cc6, - 0x00279d46, - 0x002954cc, - 0x00205fc3, - 0x002800c6, - 0x0021ef44, - 0x002ba548, - 0x002c4345, - 0x003422c6, - 0x002afc08, - 0x002c5e06, - 0x0035df06, - 0x00341e08, - 0x0029b187, - 0x0022e0c9, - 0x0030428a, - 0x0026ae44, - 0x00235b45, - 0x002a0b45, - 0x00212c86, - 0x00373d46, - 0x002a20c6, - 0x002edd86, - 0x0022e204, - 0x0022e20b, - 0x00235904, - 0x00201485, - 0x002a58c5, - 0x003126c6, - 0x003a8b08, - 0x00280807, - 0x00308404, - 0x00259d03, - 0x002aa785, - 0x002de5c7, - 0x0029c709, - 0x0028070b, - 0x0032a987, - 0x002c28c7, - 0x002e45c4, - 0x002afb08, - 0x002f4347, - 0x0029c946, - 0x00242608, - 0x0033fd8b, - 0x00396b86, - 0x00213449, - 0x0033ff05, - 0x002fe303, - 0x002d2686, - 0x00251108, - 0x00212d43, - 0x002de6c3, - 0x0027ed06, - 0x00251546, - 0x0038a5ca, - 0x0027bcc5, - 0x0027c38b, - 0x00295f4b, - 0x0020cd83, - 0x0021cec3, - 0x002a9c84, - 0x002e7f07, - 0x00251184, - 0x00201e84, - 0x00306584, - 0x003349c8, - 0x002e91c8, - 0x00327a49, - 0x002bdd48, - 0x003a17c7, - 0x0022e546, - 0x002ac74f, - 0x002b9886, - 0x002c42c4, - 0x002e900a, - 0x002de4c7, - 0x003aaf46, - 0x00289749, - 0x003279c5, - 0x002c2b05, - 0x00327b06, - 0x0021fe83, - 0x002aacc9, - 0x00220586, - 0x002e8149, - 0x0039a1c6, - 0x002b85c5, - 0x00228b45, - 0x00204d43, - 0x002e8048, - 0x00200ec7, - 0x002f6704, - 0x002ba3c8, - 0x002b1504, - 0x002cdfc6, - 0x0029ef06, - 0x0023dec6, - 0x002b8b09, - 0x0028fe45, - 0x002b1786, - 0x00257e49, - 0x002b8806, - 0x002ac846, - 0x003870c6, - 0x00212f85, - 0x002eea86, - 0x002e7ac4, - 0x0025a745, - 0x002b4244, - 0x00306486, - 0x00354e04, - 0x00200d03, - 0x002835c5, - 0x00236d88, - 0x00262847, - 0x002ae189, - 0x00283808, - 0x00290391, - 0x002caa4a, - 0x00380b07, - 0x002cbd86, - 0x0021ef44, - 0x002b4348, - 0x00281e88, - 0x0029054a, - 0x0029724d, - 0x00297c46, - 0x00341f06, - 0x0037aec6, - 0x002ef387, - 0x002fee45, - 0x00253687, - 0x002ba485, - 0x002df684, - 0x002a2d06, - 0x0032a7c7, - 0x002aa9cd, - 0x0026fd87, - 0x002db748, - 0x00279b89, - 0x00207d86, - 0x002d9e45, - 0x00218184, - 0x00243346, - 0x00278d06, - 0x0035bf06, - 0x00293a08, - 0x00217b03, - 0x0020a5c3, - 0x0031a245, - 0x00236446, - 0x002a6d85, - 0x0023f788, - 0x00294e8a, - 0x00376b04, - 0x002ba548, - 0x0028f788, - 0x00312507, - 0x00249d89, - 0x002af808, - 0x00212f07, - 0x00258b86, - 0x0020a14a, - 0x002433c8, - 0x002c0609, - 0x0029a108, - 0x00221cc9, - 0x002deb47, - 0x00346045, - 0x0031ab86, - 0x002b4808, - 0x0027ee88, - 0x00289a88, - 0x0021af08, - 0x00201485, - 0x00210a44, - 0x00200bc8, - 0x00208f84, - 0x003a1244, - 0x002b85c5, - 0x0028aa87, - 0x00201a89, - 0x00320087, - 0x00210a85, - 0x00277446, - 0x0033ed46, - 0x00213584, - 0x00299a46, - 0x002a8944, - 0x00281d86, - 0x00365bc6, - 0x00219206, - 0x00202a05, - 0x0023f647, - 0x00200843, - 0x003196c9, - 0x003638c8, - 0x00212d84, - 0x00212d8d, - 0x0028f608, - 0x002a5008, - 0x002c0586, - 0x0022a089, - 0x002d25c9, - 0x0035b705, - 0x00294f8a, - 0x0027b24a, - 0x002858cc, - 0x00285a46, - 0x00277d06, - 0x002b9a06, - 0x0026ae09, - 0x00398846, - 0x002536c6, - 0x00375546, - 0x0026ba48, - 0x00224386, - 0x002b8e4b, - 0x0028ac05, - 0x0022dd85, - 0x00277f85, - 0x0037c0c6, - 0x0020a103, - 0x0023de46, - 0x0026fd07, - 0x002b4205, - 0x00241bc5, - 0x002e4645, - 0x003382c6, - 0x0030c384, - 0x0036c206, - 0x0028c789, - 0x0037bf4c, - 0x002df3c8, - 0x0028c8c4, - 0x002ee706, - 0x0029f706, - 0x00251108, - 0x002d2448, - 0x0037be49, - 0x00201407, - 0x002e6b49, - 0x00359206, - 0x00230d84, - 0x0020ddc4, - 0x0022c844, - 0x0027ed08, - 0x002018ca, - 0x0034dcc6, - 0x00351a07, - 0x002d4407, - 0x00268185, - 0x002a0b04, - 0x002881c6, - 0x002fee86, - 0x00230a43, - 0x00363707, - 0x00374f48, - 0x0035b84a, - 0x002bff48, - 0x00376988, - 0x00354e45, - 0x00257c05, - 0x00279305, - 0x00268546, - 0x0037b286, - 0x00205245, - 0x0024f809, - 0x002a090c, - 0x00262287, - 0x002905c8, - 0x003875c5, - 0x00683b84, - 0x0027f104, - 0x002cf744, - 0x002bc306, - 0x00296ace, - 0x002c2b87, - 0x002ef585, - 0x0025134c, - 0x002b13c7, - 0x0032a747, - 0x00353049, - 0x0021f3c9, - 0x00283905, - 0x003638c8, - 0x0037e989, - 0x003175c5, - 0x002b4148, - 0x0026d986, - 0x002ad8c6, - 0x00336544, - 0x00249508, - 0x00207f43, - 0x00320bc4, - 0x002aa805, - 0x0030c387, - 0x00205b45, - 0x002e8809, - 0x00331bcd, - 0x0029a646, - 0x0037fa84, - 0x0032cfc8, - 0x0027768a, - 0x0020e607, - 0x002d4745, - 0x0020b0c3, - 0x0029610e, - 0x0025154c, - 0x002f9a07, - 0x00296c87, - 0x002011c3, - 0x00398885, - 0x002cf745, - 0x00290f88, - 0x0028e289, - 0x0035c346, - 0x00251184, - 0x00380a46, - 0x0037c8cb, - 0x002a22cc, - 0x0031fe07, - 0x002c4005, - 0x0038ab08, - 0x002cb505, - 0x002e9007, - 0x00234b47, - 0x00247d45, - 0x0020a103, - 0x00334d04, - 0x00209d45, - 0x002a8005, - 0x002a8006, - 0x00288b48, - 0x0032a7c7, - 0x0037de86, - 0x003aff46, - 0x00352bc6, - 0x00297d49, - 0x00320647, - 0x0035c1c6, - 0x002a2446, - 0x00247e06, - 0x002a1c05, - 0x0020d446, - 0x00396905, - 0x002ad508, - 0x0028d88b, - 0x00287fc6, - 0x002d4444, - 0x002f2f89, - 0x0026b884, - 0x0026d908, - 0x00289207, - 0x00281604, - 0x002aeac8, - 0x002b5a44, - 0x002a1c44, - 0x00284305, - 0x002d2346, - 0x00334907, - 0x0021c603, - 0x00295bc5, - 0x003260c4, - 0x0035f906, - 0x0035b788, - 0x00341d05, - 0x0028a509, - 0x00211f45, - 0x002e1e48, - 0x00328dc7, - 0x00388288, - 0x002adfc7, - 0x002f29c9, - 0x0035e086, - 0x0038dc86, - 0x00375544, - 0x00258ac5, - 0x002f534c, - 0x00277f87, - 0x00278387, - 0x002d42c8, - 0x0029a646, - 0x0026fc44, - 0x002ea2c4, - 0x0027f889, - 0x002b9b06, - 0x00221947, - 0x00309244, - 0x002cfe46, - 0x00324905, - 0x0029f807, - 0x002b8dc6, - 0x002491c9, - 0x0027b087, - 0x00265807, - 0x00299586, - 0x0023f105, - 0x0027d0c8, - 0x00220408, - 0x00237d46, - 0x00341d45, - 0x00254206, - 0x00206103, - 0x00290e09, - 0x002a1e4e, - 0x002adcc8, - 0x002b1608, - 0x00237b4b, - 0x0028a746, - 0x0031e4c4, - 0x00280544, - 0x002a1f4a, - 0x00217487, - 0x0035c285, - 0x00213449, - 0x002b33c5, - 0x003a1287, - 0x0037f404, - 0x00328047, - 0x00380cc8, - 0x002cc286, - 0x00329089, - 0x002af90a, - 0x00217406, - 0x0028f146, - 0x002a5845, - 0x003793c5, - 0x0024e887, - 0x00243988, - 0x00324848, - 0x00240f46, - 0x00228bc5, - 0x00373ace, - 0x0032f204, - 0x00237cc5, - 0x00276dc9, - 0x0026a008, - 0x003aba06, - 0x0029368c, - 0x00294a90, - 0x0029670f, - 0x002986c8, - 0x002ba287, - 0x00202a05, - 0x0028e645, - 0x00334789, - 0x0028e649, - 0x00307806, - 0x002f9747, - 0x00208f45, - 0x0036ecc9, - 0x00331906, - 0x0039868d, - 0x002843c9, - 0x00201e84, - 0x002ada48, - 0x00200c89, - 0x0034de86, - 0x00277545, - 0x0038dc86, - 0x00308509, - 0x00385a48, - 0x00212585, - 0x00249504, - 0x0029384b, - 0x0034dd45, - 0x00279706, - 0x00280c86, - 0x00265086, - 0x0035ef0b, - 0x0028a609, - 0x00205585, - 0x00388047, - 0x002ca9c6, - 0x00342006, - 0x002e86c8, - 0x00258c89, - 0x002db50c, - 0x002de3c8, - 0x0034df86, - 0x00345c43, - 0x0026ef06, - 0x002f2885, - 0x0027c6c8, - 0x002285c6, - 0x0029fa48, - 0x0023cc05, - 0x00290705, - 0x00299e08, - 0x002eeb87, - 0x0037dac7, - 0x0032a987, - 0x0033f108, - 0x00289908, - 0x0023bf86, - 0x003062c7, - 0x00267547, - 0x0033f88a, - 0x0024ae83, - 0x0037c0c6, - 0x00201a05, - 0x0020c684, - 0x00279b89, - 0x002f2944, - 0x002628c4, - 0x0029f584, - 0x00296c8b, - 0x00200e07, - 0x0034dd05, - 0x0028d708, - 0x00277446, - 0x00277448, - 0x0027bc06, - 0x002867c5, - 0x00286f45, - 0x00288f46, - 0x002893c8, - 0x00289688, - 0x00279d46, - 0x0028d54f, - 0x002908d0, - 0x00397445, - 0x00200843, - 0x0024a805, - 0x002fcc48, - 0x0028e549, - 0x0022c048, - 0x00328f08, - 0x003980c8, - 0x00200ec7, - 0x00277109, - 0x0029fc48, - 0x00370544, - 0x0029f408, - 0x0025a4c9, - 0x00307e07, - 0x0029f384, - 0x00320148, - 0x0023f40a, - 0x002bf1c6, - 0x00297c46, - 0x002226c9, - 0x00294cc7, - 0x002bfdc8, - 0x00208988, - 0x003090c8, - 0x00351545, - 0x0037a205, - 0x0022dd85, - 0x002cf705, - 0x002f0987, - 0x0020a105, - 0x002b4205, - 0x00213bc6, - 0x0022bf87, - 0x00311cc7, - 0x0023f706, - 0x002c5605, - 0x00279706, - 0x0025b205, - 0x002bd508, - 0x002f4e84, - 0x002b8886, - 0x00327dc4, - 0x002efc88, - 0x00216d8a, - 0x0027a5cc, - 0x0020ee05, - 0x002ef446, - 0x002db6c6, - 0x00374846, - 0x002fce44, - 0x00324bc5, - 0x0027ba47, - 0x00294d49, - 0x0029c807, - 0x00683b84, - 0x00683b84, - 0x00308285, - 0x0022b8c4, - 0x0029304a, - 0x002772c6, - 0x002de804, - 0x003aaec5, - 0x002ea985, - 0x002fed84, - 0x002808c7, - 0x00211ec7, - 0x002bf348, - 0x00315408, - 0x00212589, - 0x00295748, - 0x0029320b, - 0x00212c84, - 0x00359145, - 0x0027e745, - 0x0032a909, - 0x00258c89, - 0x002f2e88, - 0x00235908, - 0x003126c4, - 0x0029f745, - 0x00201903, - 0x00212c45, - 0x002b1806, - 0x0028e0cc, - 0x00220486, - 0x0025b246, - 0x0028e285, - 0x00338348, - 0x002ade46, - 0x002cbf06, - 0x00297c46, - 0x002239cc, - 0x0035c0c4, - 0x00352d0a, - 0x003abbc8, - 0x0028df07, - 0x00242786, - 0x0035c407, - 0x002da345, - 0x0032b9c6, - 0x00350106, - 0x0037d987, - 0x00262904, - 0x002dd345, - 0x00276dc4, - 0x002df707, - 0x00277008, - 0x00277b8a, - 0x0027df47, - 0x00237ec7, - 0x002ba207, - 0x002cb649, - 0x0028e0ca, - 0x0022e1c3, - 0x00262805, - 0x00219243, - 0x003065c9, - 0x002bc788, - 0x002bd687, - 0x0022c149, - 0x00220506, - 0x002cac48, - 0x00304a05, - 0x0024de8a, - 0x002c67c9, - 0x0026d6c9, - 0x00384dc7, - 0x00281f89, - 0x00219108, - 0x002ee886, - 0x002ef608, - 0x00217c47, - 0x0022e307, - 0x002a27c7, - 0x002cfbc8, - 0x002ee586, - 0x0023f1c5, - 0x0027ba47, - 0x0028ec48, - 0x00352b44, - 0x0027e844, - 0x00363ac7, - 0x002a7147, - 0x0037e80a, - 0x002ee806, - 0x002f988a, - 0x002b3687, - 0x0032efc7, - 0x00241044, - 0x00283e04, - 0x00225f46, - 0x00375a44, - 0x00375a4c, - 0x00397a85, - 0x0021ad49, - 0x002e1fc4, - 0x002fee45, - 0x00277608, - 0x00289745, - 0x0030c386, - 0x0020eb04, - 0x00293d8a, - 0x002aafc6, - 0x0028f90a, - 0x0030c147, - 0x00298205, - 0x0021fe85, - 0x002681ca, - 0x00299b45, - 0x00297b46, - 0x00208f84, - 0x002a9e06, - 0x0024e945, - 0x00228686, - 0x002f40cc, - 0x002bf4ca, - 0x00258b84, - 0x0022e546, - 0x00294cc7, - 0x002c3604, - 0x0026ba48, - 0x0038cd06, - 0x00373949, - 0x002c1689, - 0x002af189, - 0x0036cec6, - 0x00217d46, - 0x002ef747, - 0x0024f748, - 0x00217b49, - 0x00200e07, - 0x002b0546, - 0x002a8687, - 0x0037ad85, - 0x0032f204, - 0x002ef307, - 0x00326145, - 0x00284245, - 0x002fb1c7, - 0x00247c08, - 0x0038aa86, - 0x0028fb8d, - 0x0029118f, - 0x00295f4d, - 0x00210ac4, - 0x00236e86, - 0x002c6cc8, - 0x00375505, - 0x0033fa48, - 0x0021bb4a, - 0x00201e84, - 0x002f4486, - 0x0027d847, - 0x003920c7, - 0x0029b249, - 0x002ef5c5, - 0x002fed84, - 0x0033328a, - 0x002af3c9, - 0x00282087, - 0x00269586, - 0x0034de86, - 0x0029f686, - 0x0035a386, - 0x002c648f, - 0x002c6b89, - 0x00224386, - 0x003924c6, - 0x003992c9, - 0x003063c7, - 0x002181c3, - 0x00223b46, - 0x00209e43, - 0x002d0d88, - 0x002a84c7, - 0x002988c9, - 0x0029ed88, - 0x0037dc08, - 0x002670c6, - 0x00278b49, - 0x00234c85, - 0x00242784, - 0x002d6c87, - 0x0026ae85, - 0x00210ac4, - 0x00373dc8, - 0x00217744, - 0x00302907, - 0x00318386, - 0x002a7445, - 0x0029a108, - 0x0034dd4b, - 0x002a0e47, - 0x00268446, - 0x002b9904, - 0x0031e446, - 0x002b85c5, - 0x00326145, - 0x0027ce49, - 0x002804c9, - 0x0022e344, - 0x0022e385, - 0x0022e585, - 0x0024dd06, - 0x003639c8, - 0x002b2f86, - 0x00374d8b, - 0x003af50a, - 0x0032cc85, - 0x00286fc6, - 0x002f6405, - 0x0020c145, - 0x00294487, - 0x003a42c8, - 0x00289444, - 0x0035b606, - 0x00289706, - 0x002192c7, - 0x002fe2c4, - 0x0027c546, - 0x00239f05, - 0x00239f09, - 0x00217f44, - 0x002a0c89, - 0x00279d46, - 0x002b4f88, - 0x0022e585, - 0x002d4505, - 0x00228686, - 0x002db409, - 0x0021f3c9, - 0x0025b2c6, - 0x0026a108, - 0x00251448, - 0x002f63c4, - 0x0035a884, - 0x0035a888, - 0x00313c88, - 0x002e6c49, - 0x002b1786, - 0x00297c46, - 0x003109cd, - 0x00300ec6, - 0x003acbc9, - 0x0037c285, - 0x00327b06, - 0x002537c8, - 0x0030df05, - 0x00267584, - 0x002b85c5, - 0x0027f708, - 0x00292e09, - 0x00276e84, - 0x0031f006, - 0x002dec8a, - 0x00220688, - 0x0037e989, - 0x0022dc4a, - 0x0022c0c6, - 0x00291348, - 0x002e8dc5, - 0x00329788, - 0x002ae0c5, - 0x002203c9, - 0x00360909, - 0x00201002, - 0x0033ff05, - 0x0026f786, - 0x00279c87, - 0x0020c685, - 0x002f7c86, - 0x0030dfc8, - 0x0029a646, - 0x002c1189, - 0x00278486, - 0x002e8548, - 0x002a2f45, - 0x00248d06, - 0x002e7bc8, - 0x0027ed08, - 0x00365c48, - 0x002fc448, - 0x0020d444, - 0x0022e883, - 0x002c13c4, - 0x0027e146, - 0x0037adc4, - 0x002b1547, - 0x002cbe09, - 0x002b9105, - 0x00208986, - 0x00223b46, - 0x0028898b, - 0x0032cbc6, - 0x003147c6, - 0x002b8988, - 0x00241b06, - 0x00297543, - 0x00209643, - 0x0032f204, - 0x00232705, - 0x002a8b07, - 0x00277008, - 0x0027700f, - 0x0027b94b, - 0x003637c8, - 0x0031f086, - 0x002e684e, - 0x00228683, - 0x00227304, - 0x0032cb45, - 0x002fda46, - 0x002882cb, - 0x0028ab46, - 0x0021eec9, - 0x002a7445, - 0x003896c8, - 0x0020d888, - 0x0021f28c, - 0x00296cc6, - 0x00212c86, - 0x002dc805, - 0x00284688, - 0x0022c405, - 0x00340888, - 0x0029638a, - 0x0031aa09, - 0x00683b84, - 0x2ea02682, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024a143, - 0x00202d43, - 0x002006c3, - 0x0021db44, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x002cb284, - 0x002d60c3, - 0x0020c947, - 0x0021e083, - 0x00201543, - 0x00331a08, - 0x00202d43, - 0x002d780b, - 0x002daa83, - 0x00215a06, - 0x00200142, - 0x0038548b, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00202d43, - 0x0021c443, - 0x00205e03, - 0x002050c2, - 0x001795c8, - 0x0021c5c5, - 0x002d3c88, - 0x002e2808, - 0x00202682, - 0x0022c8c5, - 0x0032b687, - 0x00200482, - 0x0021f107, - 0x00200fc2, - 0x0023c7c7, - 0x00375f89, - 0x00314b88, - 0x00308f49, - 0x00333f02, - 0x00266687, - 0x0025b044, - 0x0032b747, - 0x003af407, - 0x00243782, - 0x0021e083, - 0x00200542, - 0x002032c2, - 0x00200282, - 0x00205702, - 0x00204942, - 0x00204842, - 0x00297105, - 0x0027f045, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00000301, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x0024a143, - 0x00202d43, - 0x0021e7c3, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00009602, - 0x001795c8, - 0x00043944, - 0x000cb905, - 0x002050c2, - 0x002b6504, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00300943, - 0x002a3645, - 0x0024af03, - 0x0035ea43, - 0x0024a143, - 0x00205bc3, - 0x00202d43, - 0x002169c3, - 0x0021dbc3, - 0x0021d903, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x00202d43, - 0x001795c8, - 0x002d60c3, - 0x001795c8, - 0x002c81c3, - 0x0022f303, - 0x00233204, - 0x00215403, - 0x002d60c3, - 0x00208202, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00208202, - 0x0020c943, - 0x0024a143, - 0x00202d43, - 0x002d3c03, - 0x002169c3, - 0x002050c2, - 0x00202682, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00215a05, - 0x000a80c6, - 0x0021db44, - 0x00200142, - 0x001795c8, - 0x002050c2, - 0x00020e88, - 0x00202682, - 0x0000de46, - 0x000e7144, - 0x000c958b, - 0x00018886, - 0x00120ac7, - 0x00215403, - 0x002d60c3, - 0x00154d45, - 0x0000b844, - 0x0023bec3, - 0x0004ae47, - 0x000c7d44, - 0x0024a143, - 0x0006f0c4, - 0x00202d43, - 0x002dbd04, - 0x00108dc8, - 0x00141846, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x00201543, - 0x00202d43, - 0x002daa83, - 0x00200142, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c383, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002cb284, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00215a06, - 0x00215403, - 0x002d60c3, - 0x00170dc3, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00120ac7, - 0x001795c8, - 0x002d60c3, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x3762f303, - 0x00215403, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x002050c2, - 0x00202682, - 0x0022f303, - 0x002d60c3, - 0x0024a143, - 0x00200282, - 0x00202d43, - 0x00307107, - 0x0032164b, - 0x00207043, - 0x002d9fc8, - 0x0024f4c7, - 0x00366b86, - 0x002b7305, - 0x003696c9, - 0x00215788, - 0x00264449, - 0x00264450, - 0x00355bcb, - 0x002ebe49, - 0x00203383, - 0x00213dc9, - 0x00233d06, - 0x00233d0c, - 0x0021c688, - 0x003ac0c8, - 0x00270649, - 0x002a5f4e, - 0x0037794b, - 0x002ad20c, - 0x00201383, - 0x0025fc8c, - 0x00206b09, - 0x0036e907, - 0x00235f8c, - 0x0039d00a, - 0x002451c4, - 0x00365f0d, - 0x0025fb48, - 0x002006cd, - 0x00266b06, - 0x003a090b, - 0x0020b149, - 0x00314687, - 0x002e57c6, - 0x0030c689, - 0x0032560a, - 0x003040c8, - 0x002da684, - 0x0031ac87, - 0x00276487, - 0x00309444, - 0x0022b544, - 0x00263789, - 0x003767c9, - 0x00223f08, - 0x00210545, - 0x00391a05, - 0x0020d186, - 0x00365dc9, - 0x0021bdcd, - 0x002acc88, - 0x0020d087, - 0x002b7388, - 0x0022fac6, - 0x0039b7c4, - 0x0031a505, - 0x00202f86, - 0x00205c84, - 0x00206a07, - 0x0020924a, - 0x00213384, - 0x00217346, - 0x00218d89, - 0x00218d8f, - 0x0021aa4d, - 0x0021b746, - 0x00220a90, - 0x00220e86, - 0x002215c7, - 0x00221f07, - 0x00221f0f, - 0x00222989, - 0x00227f86, - 0x0022a2c7, - 0x0022a2c8, - 0x0022a689, - 0x0028a848, - 0x002d08c7, - 0x0020c3c3, - 0x0038f846, - 0x00200308, - 0x002a620a, - 0x00214e49, - 0x00208103, - 0x0032b586, - 0x0035b44a, - 0x002f6cc7, - 0x0036e74a, - 0x00203e4e, - 0x00222ac6, - 0x00340107, - 0x002128c6, - 0x00206bc6, - 0x0037a00b, - 0x0033b60a, - 0x0022990d, - 0x00217e07, - 0x003756c8, - 0x003756c9, - 0x003756cf, - 0x00204f0c, - 0x003701c9, - 0x002d3e8e, - 0x0020ca4a, - 0x002e9646, - 0x00372686, - 0x0030eb8c, - 0x0032e14c, - 0x00330208, - 0x003576c7, - 0x0026bdc5, - 0x00398b04, - 0x0032294e, - 0x00325884, - 0x00373087, - 0x0026154a, - 0x00381a14, - 0x0038404f, - 0x002220c8, - 0x0038f708, - 0x0036528d, - 0x0036528e, - 0x00391b89, - 0x002316c8, - 0x002316cf, - 0x00235c8c, - 0x00235c8f, - 0x00236bc7, - 0x0023910a, - 0x0022014b, - 0x0023aac8, - 0x0023b507, - 0x0037280d, - 0x00326586, - 0x003660c6, - 0x0023dcc9, - 0x0031ca48, - 0x002415c8, - 0x002415ce, - 0x002469c7, - 0x002a4045, - 0x00243045, - 0x0020ae04, - 0x00366e46, - 0x00223e08, - 0x00252503, - 0x0025bc0e, - 0x00372bc8, - 0x0036750b, - 0x00353487, - 0x003a3f85, - 0x0025fe06, - 0x002a4e07, - 0x002e1708, - 0x0022bdc9, - 0x00326805, - 0x00283608, - 0x002142c6, - 0x0037aa0a, - 0x00322849, - 0x00236049, - 0x0023604b, - 0x0030d1c8, - 0x00309309, - 0x00210606, - 0x0037410a, - 0x0034770a, - 0x0023930c, - 0x002f69c7, - 0x0029c48a, - 0x0033520b, - 0x00335219, - 0x00239988, - 0x00215a85, - 0x002bb506, - 0x002d5cc9, - 0x00315086, - 0x0021234a, - 0x00320946, - 0x00214b84, - 0x002bb68d, - 0x00324ec7, - 0x00214b89, - 0x00383745, - 0x00244288, - 0x002447c9, - 0x00244a04, - 0x002450c7, - 0x002450c8, - 0x002457c7, - 0x00264d08, - 0x0024bf07, - 0x0023b3c5, - 0x0025720c, - 0x00257749, - 0x002c194a, - 0x0038e449, - 0x00213ec9, - 0x0026d08c, - 0x00259bcb, - 0x00259e88, - 0x0025c3c8, - 0x0025f784, - 0x002812c8, - 0x00282949, - 0x0039d0c7, - 0x00218fc6, - 0x00216207, - 0x002ffd49, - 0x00334e4b, - 0x003246c7, - 0x00202dc7, - 0x002e2047, - 0x00200644, - 0x00200645, - 0x002a19c5, - 0x00337e4b, - 0x0039aa44, - 0x00316248, - 0x002a3c4a, - 0x00214387, - 0x0034d807, - 0x00287b52, - 0x00281c86, - 0x00232986, - 0x00319a0e, - 0x00282686, - 0x0028b688, - 0x0028c28f, - 0x00200a88, - 0x0036f748, - 0x002b560a, - 0x002b5611, - 0x0029a30e, - 0x0023b80a, - 0x0023b80c, - 0x002318c7, - 0x002318d0, - 0x00202208, - 0x0029a505, - 0x002a520a, - 0x00205ccc, - 0x002b088d, - 0x002f21c6, - 0x0032d887, - 0x0032d88c, - 0x002f21cc, - 0x002d350c, - 0x00298e4b, - 0x00282fc4, - 0x00222844, - 0x00381489, - 0x002d01c7, - 0x00236609, - 0x00347549, - 0x00360007, - 0x0039ce86, - 0x0039ce89, - 0x003a64c3, - 0x0029a74a, - 0x00398d47, - 0x0031b0cb, - 0x0022978a, - 0x0023c904, - 0x00351b46, - 0x0027e1c9, - 0x0038d5c4, - 0x00397b4a, - 0x00268745, - 0x002b1985, - 0x002b198d, - 0x002b1cce, - 0x00312a85, - 0x00393dc6, - 0x00215607, - 0x002d1b0a, - 0x002e1906, - 0x002fa1c4, - 0x002fabc7, - 0x0021df4b, - 0x0022fb87, - 0x0035eb44, - 0x002d85c6, - 0x002d85cd, - 0x0031ec4c, - 0x0032a506, - 0x002ace8a, - 0x0021c346, - 0x00218288, - 0x003024c7, - 0x002a7b0a, - 0x00233086, - 0x00217d03, - 0x00253946, - 0x00200188, - 0x0029340a, - 0x0024b047, - 0x0024b048, - 0x0024c544, - 0x002780c7, - 0x0038b488, - 0x0029fdc8, - 0x003925c8, - 0x003471ca, - 0x002ca385, - 0x002ca607, - 0x0023b653, - 0x0022f386, - 0x002ab148, - 0x00226589, - 0x0021efc8, - 0x0026714b, - 0x002b3488, - 0x0021e084, - 0x00299f06, - 0x003add86, - 0x002d2189, - 0x003ac287, - 0x00257308, - 0x003abd46, - 0x0021a404, - 0x002bfc85, - 0x002ba048, - 0x002ba90a, - 0x002bb308, - 0x002c0346, - 0x00293b0a, - 0x00287448, - 0x002c3408, - 0x002c4848, - 0x002c52c6, - 0x002c6ec6, - 0x002e5ccc, - 0x002c7390, - 0x0028cb85, - 0x00200888, - 0x002f8290, - 0x00200890, - 0x002642ce, - 0x002e594e, - 0x002e5954, - 0x0030d38f, - 0x0030d746, - 0x00335b51, - 0x002c9813, - 0x002c9c88, - 0x0031df85, - 0x00355088, - 0x0020e005, - 0x0022d0cc, - 0x0022ac09, - 0x00372ec9, - 0x00215f87, - 0x0023ff09, - 0x00215147, - 0x002ddfc6, - 0x0031a307, - 0x0024a985, - 0x0030ee43, - 0x002526c9, - 0x00229cc9, - 0x00370dc3, - 0x00219d04, - 0x0032a14d, - 0x003a524f, - 0x002fb105, - 0x00316c86, - 0x002101c7, - 0x0033ba47, - 0x00285286, - 0x0028528b, - 0x0029bb05, - 0x003a85c6, - 0x0020be87, - 0x00271409, - 0x0039b946, - 0x0020a7c5, - 0x002310cb, - 0x003306c6, - 0x00248285, - 0x0027d508, - 0x002b1008, - 0x002b224c, - 0x002b2250, - 0x002c57c9, - 0x002ce687, - 0x002f730b, - 0x002cfa86, - 0x002d078a, - 0x002d1f0b, - 0x002d290a, - 0x002d2b86, - 0x002d3ac5, - 0x0024f3c6, - 0x00278648, - 0x0021604a, - 0x00364f1c, - 0x002dab4c, - 0x002dae48, - 0x00215a05, - 0x002de147, - 0x002a5b86, - 0x003969c5, - 0x0021ec46, - 0x00285448, - 0x002af647, - 0x002a5e48, - 0x0034020a, - 0x0030ca0c, - 0x0030cc89, - 0x003a88c7, - 0x00203584, - 0x00243b06, - 0x0036f2ca, - 0x00347645, - 0x0036620c, - 0x00367288, - 0x0034c2c8, - 0x0020460c, - 0x0020f7cc, - 0x002113c9, - 0x00211607, - 0x002caf4c, - 0x00373544, - 0x0037118a, - 0x0038d8cc, - 0x002729cb, - 0x0023238b, - 0x00232f46, - 0x0023d087, - 0x00231b07, - 0x00231b0f, - 0x002f38d1, - 0x003aa9d2, - 0x0023d50d, - 0x0023d50e, - 0x0023d84e, - 0x0030d548, - 0x0030d552, - 0x002408c8, - 0x002f9fc7, - 0x0024870a, - 0x00209b88, - 0x00282645, - 0x002f07ca, - 0x002213c7, - 0x002e3c04, - 0x0023bf43, - 0x002e64c5, - 0x002b5887, - 0x002ff507, - 0x002b0a8e, - 0x0039bf4d, - 0x0039da89, - 0x00211945, - 0x002e9e43, - 0x00251e46, - 0x00363445, - 0x00367748, - 0x002ea589, - 0x0028bcc5, - 0x00372a0f, - 0x002c9687, - 0x00369605, - 0x003a214a, - 0x002b6c46, - 0x00218409, - 0x002eba4c, - 0x002ed649, - 0x00202446, - 0x002a3a4c, - 0x002edc06, - 0x002f0b48, - 0x002f0d46, - 0x00239b06, - 0x0024e684, - 0x0025ad43, - 0x002eaf8a, - 0x00365711, - 0x00238e8a, - 0x00271ac5, - 0x002be207, - 0x00250b07, - 0x002e0084, - 0x0038b58b, - 0x00314a08, - 0x002adb46, - 0x002d4345, - 0x00261004, - 0x00258789, - 0x00399844, - 0x0033bf07, - 0x002ed845, - 0x002ed847, - 0x00319c45, - 0x002971c3, - 0x002f9e88, - 0x0032498a, - 0x0021c603, - 0x0021c60a, - 0x00270106, - 0x0037278f, - 0x00246949, - 0x0025bb90, - 0x00354488, - 0x002c0bc9, - 0x00295307, - 0x002d854f, - 0x0022c504, - 0x002cb304, - 0x0021b5c6, - 0x00273386, - 0x0031198a, - 0x002e2e46, - 0x003466c7, - 0x002f7688, - 0x002f7887, - 0x002f7a47, - 0x00348e4a, - 0x002f9ccb, - 0x003860c5, - 0x003aa608, - 0x0020b003, - 0x0023a24c, - 0x0038bd8f, - 0x0026bbcd, - 0x0024aac7, - 0x0039dbc9, - 0x00262607, - 0x0025ae08, - 0x00381c0c, - 0x0026b2c8, - 0x0024fec8, - 0x00309b8e, - 0x0031cc54, - 0x0031d164, - 0x0033eb0a, - 0x0035630b, - 0x00215204, - 0x00215209, - 0x002f4508, - 0x00243cc5, - 0x0025200a, - 0x00375e47, - 0x0020c744, - 0x00341d03, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x0021e083, - 0x002c7386, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x002050c2, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x002d60c3, - 0x0024af03, - 0x002c7386, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x00623d08, - 0x00200302, - 0x00215e02, - 0x00202682, - 0x0022f303, - 0x00206382, - 0x00200842, - 0x0037c544, - 0x0020f5c4, - 0x00226d02, - 0x00212284, - 0x00200282, - 0x00202d43, - 0x0021e703, - 0x00232f46, - 0x00213ac2, - 0x00202402, - 0x0020f082, - 0x39e00a83, - 0x3a2053c3, - 0x00051846, - 0x00051846, - 0x0021db44, - 0x0012208c, - 0x0000f44c, - 0x0007fd0d, - 0x000d58c7, - 0x0001b8c8, - 0x00025608, - 0x001a4b8a, - 0x3af01e05, - 0x00101e09, - 0x00120b48, - 0x00169bca, - 0x00170e4e, - 0x000e7144, - 0x0016d488, - 0x0007c0c7, - 0x00013947, - 0x0016c489, - 0x0018d647, - 0x00125908, - 0x001a3d49, - 0x000d5405, - 0x00052f0e, - 0x000a2f8d, - 0x00120948, - 0x3b265246, - 0x00060947, - 0x00061407, - 0x00068b47, - 0x0006f487, - 0x0000d142, - 0x0000b5c7, - 0x0013b7cc, - 0x000ec787, - 0x000920c6, - 0x0009d709, - 0x000a0188, - 0x00009f82, - 0x00000842, - 0x0019834b, - 0x00014989, - 0x00043589, - 0x00022fc8, - 0x000aa4c2, - 0x00078f09, - 0x0000b309, - 0x000c8348, - 0x000c8947, - 0x000ca309, - 0x000ccec5, - 0x000cd410, - 0x0015e806, - 0x000546c5, - 0x0001d58d, - 0x0018d206, - 0x000d6887, - 0x000dbd18, - 0x0004f9c8, - 0x001a23ca, - 0x0004128d, - 0x00002542, - 0x0006a4c6, - 0x0008acc8, - 0x000c49c8, - 0x00179489, - 0x0017f7c8, - 0x0004cf0e, - 0x000e3b05, - 0x0004d548, - 0x00001142, - 0x00141846, - 0x00003c02, - 0x000002c1, - 0x3b6dc584, - 0x3ba8d103, - 0x00000101, - 0x00010746, - 0x00000101, - 0x00000001, - 0x00010746, - 0x014e2305, - 0x002451c4, - 0x0022f303, - 0x00246ec4, - 0x0037c544, - 0x0024a143, - 0x00226445, - 0x0021e7c3, - 0x00226a03, - 0x002eb585, - 0x0021d903, - 0x3ca2f303, - 0x00215403, - 0x002d60c3, - 0x00200041, - 0x0021e083, - 0x0020f5c4, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x002169c3, - 0x001795c8, - 0x002050c2, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x00200842, - 0x0037c544, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x0021d903, - 0x001795c8, - 0x0038bb02, - 0x00002682, - 0x3da28382, - 0x00398f08, - 0x00228806, - 0x002b6e46, - 0x00228187, - 0x3de07642, - 0x3e354308, - 0x00207b8a, - 0x002603c8, - 0x002001c2, - 0x00398b89, - 0x00386107, - 0x00218f46, - 0x00207549, - 0x0025a6c4, - 0x00366a86, - 0x002e1b84, - 0x002777c4, - 0x00256809, - 0x0021cd06, - 0x0027f105, - 0x00213145, - 0x003a9ac7, - 0x002b3907, - 0x00213084, - 0x002283c6, - 0x002f1ac5, - 0x002dd0c5, - 0x002f6345, - 0x003917c7, - 0x003532c5, - 0x00305e09, - 0x00375205, - 0x00226984, - 0x002e1847, - 0x0024eb4e, - 0x00263f09, - 0x003198c9, - 0x00334486, - 0x0033e0c8, - 0x002a9f0b, - 0x002cc68c, - 0x00268dc6, - 0x00377807, - 0x0020ab85, - 0x0022b54a, - 0x0030bc49, - 0x0024e2c9, - 0x003a66c6, - 0x002eff85, - 0x0027b145, - 0x0035da89, - 0x002f64cb, - 0x0027bd86, - 0x00333746, - 0x0020d084, - 0x00287806, - 0x002a40c8, - 0x00200006, - 0x003a4f86, - 0x00208348, - 0x002094c7, - 0x0020a909, - 0x0020b945, - 0x001795c8, - 0x002138c4, - 0x0037b384, - 0x00211205, - 0x00395089, - 0x00225a87, - 0x00225a8b, - 0x00227b8a, - 0x0022b245, - 0x3e60c3c2, - 0x00229647, - 0x3ea2ce88, - 0x00283347, - 0x0021d045, - 0x0031ea4a, - 0x00002682, - 0x0020414b, - 0x002a87ca, - 0x003a8706, - 0x003a3f83, - 0x002fffcd, - 0x0035dc8c, - 0x0035f60d, - 0x0037f3c5, - 0x00238945, - 0x00252547, - 0x00206389, - 0x00207a86, - 0x002e2cc5, - 0x0028c088, - 0x00287703, - 0x002e2b08, - 0x00287708, - 0x002b7e07, - 0x00355388, - 0x0031f209, - 0x002379c7, - 0x003211c7, - 0x002e2188, - 0x0024a184, - 0x0024a187, - 0x00266a08, - 0x00203206, - 0x0039990f, - 0x002306c7, - 0x002d0a46, - 0x0025af85, - 0x00219e83, - 0x00368207, - 0x00339f03, - 0x00245986, - 0x00247a46, - 0x00248e86, - 0x0028a305, - 0x00264d03, - 0x00387f08, - 0x00364889, - 0x0037d00b, - 0x00249008, - 0x0024bbc5, - 0x0024c8c5, - 0x3ee3c9c2, - 0x0031a3c9, - 0x0037c5c7, - 0x003a8645, - 0x00256707, - 0x002582c6, - 0x0035a245, - 0x0036328b, - 0x00259e84, - 0x0025ff85, - 0x002600c7, - 0x00275e86, - 0x002762c5, - 0x002814c7, - 0x00282247, - 0x002700c4, - 0x0028610a, - 0x002865c8, - 0x002e8e49, - 0x0026f2c5, - 0x00221786, - 0x002a428a, - 0x002c2cc6, - 0x00265507, - 0x00314d0d, - 0x00226049, - 0x002e9905, - 0x00322dc7, - 0x002e7308, - 0x002e7988, - 0x002e5487, - 0x002c9e46, - 0x00217947, - 0x00247403, - 0x00337e44, - 0x00357e05, - 0x0038c407, - 0x003911c9, - 0x0022f6c8, - 0x002a7d45, - 0x00362e04, - 0x002d14c5, - 0x0024600d, - 0x00207682, - 0x002d1d86, - 0x0026a406, - 0x0034c68a, - 0x0035d1c6, - 0x0036f205, - 0x00315505, - 0x00315507, - 0x0037a84c, - 0x0027408a, - 0x00287146, - 0x002c6dc5, - 0x00287646, - 0x00287987, - 0x002890c6, - 0x0028a20c, - 0x00207689, - 0x3f210bc7, - 0x0028c645, - 0x0028c646, - 0x0028cd88, - 0x002aba05, - 0x0029cac5, - 0x0029cd08, - 0x0029cf0a, - 0x3f66ec82, - 0x3fa0e9c2, - 0x0037e005, - 0x002d09c3, - 0x0030f008, - 0x00218543, - 0x0029d184, - 0x0021854b, - 0x002aa2c8, - 0x002a0748, - 0x3ff1e6c9, - 0x002a2a09, - 0x002a2e86, - 0x002a4a88, - 0x002a4c89, - 0x002a5686, - 0x002a5805, - 0x00362646, - 0x002a6489, - 0x0022bc47, - 0x00248bc6, - 0x00230ac7, - 0x00207907, - 0x00234884, - 0x402f8b89, - 0x002bf008, - 0x00354208, - 0x002440c7, - 0x002b9cc6, - 0x002fb309, - 0x00326347, - 0x0037e4ca, - 0x0032c988, - 0x003746c7, - 0x0024e746, - 0x0038104a, - 0x0027d248, - 0x00269e85, - 0x00230fc5, - 0x002b4d07, - 0x002c5bc9, - 0x002cea4b, - 0x002fa3c8, - 0x00375289, - 0x00249807, - 0x003ac80c, - 0x002ab5cc, - 0x002ab8ca, - 0x002abb4c, - 0x002b6dc8, - 0x002b6fc8, - 0x002b71c4, - 0x002b7589, - 0x002b77c9, - 0x002b7a0a, - 0x002b7c89, - 0x002b7fc7, - 0x003ae4cc, - 0x00240cc6, - 0x00270408, - 0x002c2d86, - 0x00386b06, - 0x002e9807, - 0x00264108, - 0x00253fcb, - 0x00283207, - 0x002f34c9, - 0x00247049, - 0x00256247, - 0x002e1dc4, - 0x0035a707, - 0x00374c06, - 0x00216b86, - 0x002ad045, - 0x002c7b48, - 0x0020df04, - 0x0020df06, - 0x00273f4b, - 0x0029aa49, - 0x002e5606, - 0x00376e49, - 0x00391946, - 0x002fe088, - 0x00203b43, - 0x0020bdc5, - 0x00206589, - 0x0020e585, - 0x00304844, - 0x00275446, - 0x00268a05, - 0x002d6646, - 0x002fb8c7, - 0x00335106, - 0x002914cb, - 0x00374007, - 0x00352f06, - 0x00381606, - 0x003a9b86, - 0x00213049, - 0x00221a8a, - 0x00333485, - 0x0032990d, - 0x0029d006, - 0x003a25c6, - 0x002db246, - 0x00218205, - 0x002cd707, - 0x00295d87, - 0x002a77ce, - 0x0021e083, - 0x002b9c89, - 0x00315249, - 0x0022b947, - 0x0027aa47, - 0x002a21c5, - 0x0032bac5, - 0x406638cf, - 0x002c0e07, - 0x002c0fc8, - 0x002c15c4, - 0x002c1bc6, - 0x40a430c2, - 0x002c5546, - 0x002c7386, - 0x0025430e, - 0x002e294a, - 0x00229146, - 0x00391f8a, - 0x00206189, - 0x00313245, - 0x00393808, - 0x003ac6c6, - 0x00319448, - 0x00329608, - 0x0025b70b, - 0x00228285, - 0x00353348, - 0x0020848c, - 0x0021cf07, - 0x00248646, - 0x00268848, - 0x00366d08, - 0x40e0bd82, - 0x00325d4b, - 0x0036d889, - 0x003668c9, - 0x0020ad07, - 0x0038d048, - 0x4120bb48, - 0x0020fe8b, - 0x00222e49, - 0x0037a2cd, - 0x00224488, - 0x00230448, - 0x41602742, - 0x003b0584, - 0x41a048c2, - 0x002ed386, - 0x41e022c2, - 0x0021a44a, - 0x00341946, - 0x00224808, - 0x0033e3c8, - 0x002d7686, - 0x00270f86, - 0x002e1306, - 0x003676c5, - 0x0023afc4, - 0x422fe004, - 0x00338a46, - 0x0023a907, - 0x426cba47, - 0x002edfcb, - 0x0024ef09, - 0x0023898a, - 0x00253bc4, - 0x00315648, - 0x0024898d, - 0x002d9909, - 0x002d9b48, - 0x002da1c9, - 0x002dbd04, - 0x00207444, - 0x0027de05, - 0x0031ae8b, - 0x002aa246, - 0x00338885, - 0x0021d1c9, - 0x00228488, - 0x00298b84, - 0x0022b6c9, - 0x00373f45, - 0x002b3948, - 0x00321887, - 0x00319cc8, - 0x0027e3c6, - 0x00229507, - 0x0028b449, - 0x00231249, - 0x00248305, - 0x00342105, - 0x42a2a902, - 0x002e1604, - 0x002fd105, - 0x0029c246, - 0x00338205, - 0x0024c987, - 0x00269685, - 0x00269704, - 0x00334546, - 0x002e2d47, - 0x00243106, - 0x002ffc85, - 0x00329e48, - 0x00228a05, - 0x0035e9c7, - 0x00399c89, - 0x0029ab8a, - 0x00380387, - 0x0038038c, - 0x0027f0c6, - 0x0022f4c9, - 0x00339545, - 0x003579c8, - 0x002105c3, - 0x002105c5, - 0x00236545, - 0x00397147, - 0x42e12a42, - 0x00238587, - 0x002e2606, - 0x002f8ac6, - 0x002ed4c6, - 0x00366c46, - 0x002cccc8, - 0x003551c5, - 0x002d0b07, - 0x002d0b0d, - 0x0023bf43, - 0x00321105, - 0x003a1f07, - 0x00385348, - 0x003a1ac5, - 0x0022af88, - 0x00239806, - 0x00301fc7, - 0x002b92c5, - 0x00228306, - 0x002d7a85, - 0x002b658a, - 0x00311bc6, - 0x00302347, - 0x002c4c45, - 0x002f8647, - 0x002fab44, - 0x003047c6, - 0x00336485, - 0x0021cb0b, - 0x00374a89, - 0x00242dca, - 0x00248388, - 0x00350d08, - 0x003566cc, - 0x00358b87, - 0x003635c8, - 0x00384948, - 0x0038db85, - 0x002e438a, - 0x002e9e49, - 0x43202842, - 0x00202bc6, - 0x002039c4, - 0x002d82c9, - 0x00359989, - 0x00223847, - 0x0033b087, - 0x003473c9, - 0x00397708, - 0x0039770f, - 0x0026e4c6, - 0x0023e34b, - 0x002eb3c5, - 0x002eb3c7, - 0x002eb809, - 0x00218686, - 0x0022b647, - 0x003aad45, - 0x00233844, - 0x002623c6, - 0x002077c4, - 0x00307f47, - 0x002eda08, - 0x436efe88, - 0x002f0485, - 0x002f05c7, - 0x00262009, - 0x002a1ec4, - 0x003ab008, - 0x43b70388, - 0x002e0084, - 0x00234188, - 0x002e5884, - 0x002140c9, - 0x002257c5, - 0x43e00142, - 0x0026e505, - 0x002216c5, - 0x0029e648, - 0x00236a07, - 0x44202882, - 0x002c3085, - 0x00250886, - 0x00258146, - 0x002e15c8, - 0x002e37c8, - 0x003381c6, - 0x002ea1c6, - 0x00227809, - 0x002f8a06, - 0x002c930b, - 0x00289d05, - 0x00209ac6, - 0x00219f08, - 0x00391d46, - 0x00326686, - 0x0021e40a, - 0x00267c4a, - 0x00288805, - 0x002208c7, - 0x00345e46, - 0x446000c2, - 0x003a2047, - 0x0035e385, - 0x002a4204, - 0x002a4205, - 0x00253ac6, - 0x00274947, - 0x00203745, - 0x00264184, - 0x00256448, - 0x00326745, - 0x00286907, - 0x0028d405, - 0x00219805, - 0x00245344, - 0x00299089, - 0x002f1908, - 0x00376d06, - 0x00213b06, - 0x0038b286, - 0x44ba7148, - 0x002f4707, - 0x002f494d, - 0x002f504c, - 0x002f5649, - 0x002f5889, - 0x44f4fb82, - 0x003a6283, - 0x00203443, - 0x00374cc5, - 0x0038c50a, - 0x003171c6, - 0x002f8e45, - 0x002fbe04, - 0x002fbe0b, - 0x0030aa0c, - 0x0030b24c, - 0x0030b555, - 0x0030dc8d, - 0x0030f20f, - 0x0030f5d2, - 0x0030fa4f, - 0x0030fe12, - 0x00310293, - 0x0031074d, - 0x00310d0d, - 0x0031108e, - 0x0031154e, - 0x0031284c, - 0x00312bcc, - 0x0031300b, - 0x0031338e, - 0x00316452, - 0x00316f8c, - 0x00317890, - 0x0032e452, - 0x0032f30c, - 0x0032f9cd, - 0x0032fd0c, - 0x00332911, - 0x003338cd, - 0x00336a8d, - 0x0033708a, - 0x0033730c, - 0x00337c0c, - 0x0033858c, - 0x00338e0c, - 0x0033c0d3, - 0x0033c6d0, - 0x0033cad0, - 0x0033d24d, - 0x0033d84c, - 0x0033e849, - 0x00340a8d, - 0x00340dd3, - 0x00342f91, - 0x003433d3, - 0x00343a8f, - 0x00343e4c, - 0x0034414f, - 0x0034450d, - 0x00344b0f, - 0x00344ed0, - 0x0034594e, - 0x0034898e, - 0x003490d0, - 0x00349b8d, - 0x0034a50e, - 0x0034a88c, - 0x0034bd53, - 0x0034d9ce, - 0x0034e110, - 0x0034e511, - 0x0034e94f, - 0x0034ed13, - 0x0034f70d, - 0x0034fa4f, - 0x0034fe0e, - 0x00350550, - 0x00350949, - 0x00351690, - 0x00351ccf, - 0x0035234f, - 0x00352712, - 0x00353b0e, - 0x0035468d, - 0x0035558d, - 0x003558cd, - 0x003569cd, - 0x00356d0d, - 0x00357050, - 0x0035744b, - 0x00357bcc, - 0x00357f4c, - 0x0035824c, - 0x0035854e, - 0x00368d90, - 0x0036a992, - 0x0036ae0b, - 0x0036b88e, - 0x0036bc0e, - 0x0036c90e, - 0x0036dbcb, - 0x4536e196, - 0x0036ef0d, - 0x00370654, - 0x0037140d, - 0x00377355, - 0x0037874d, - 0x003790cf, - 0x003797cf, - 0x0037d2cf, - 0x0037d68e, - 0x0037ee0d, - 0x00383351, - 0x003862cc, - 0x003865cc, - 0x003868cb, - 0x00386e8c, - 0x0038770f, - 0x00387ad2, - 0x0038848d, - 0x0038944c, - 0x003898cc, - 0x00389bcd, - 0x00389f0f, - 0x0038a2ce, - 0x0038c1cc, - 0x0038c78d, - 0x0038cacb, - 0x0038e20c, - 0x0038e78d, - 0x0038eace, - 0x0038ef49, - 0x0038f9d3, - 0x0039064d, - 0x0039098d, - 0x00390f8c, - 0x0039140e, - 0x003927cf, - 0x00392b8c, - 0x00392e8d, - 0x003931cf, - 0x0039358c, - 0x00393b8c, - 0x00393f4c, - 0x0039424c, - 0x0039490d, - 0x00394c52, - 0x003952cc, - 0x003955cc, - 0x003958d1, - 0x00395d0f, - 0x003960cf, - 0x00396493, - 0x00399ece, - 0x0039a44f, - 0x0039a80c, - 0x4579ab4e, - 0x0039aecf, - 0x0039b296, - 0x0039bad2, - 0x0039d28c, - 0x0039de0f, - 0x0039e48d, - 0x0039e7cf, - 0x0039eb8c, - 0x0039ee8d, - 0x0039f1cd, - 0x003a0e4e, - 0x003a2c8c, - 0x003a2f8c, - 0x003a3290, - 0x003a5611, - 0x003a5a4b, - 0x003a5e8c, - 0x003a618e, - 0x003a7651, - 0x003a7a8e, - 0x003a7e0d, - 0x003ac48b, - 0x003ad48f, - 0x003adf14, - 0x00231302, - 0x00231302, - 0x002032c3, - 0x00231302, - 0x002032c3, - 0x00231302, - 0x00203982, - 0x00362685, - 0x003a734c, - 0x00231302, - 0x00231302, - 0x00203982, - 0x00231302, - 0x0028d205, - 0x0029ab85, - 0x00231302, - 0x00231302, - 0x00207f02, - 0x0028d205, - 0x0030e1c9, - 0x00342c8c, - 0x00231302, - 0x00231302, - 0x00231302, - 0x00231302, - 0x00362685, - 0x00231302, - 0x00231302, - 0x00231302, - 0x00231302, - 0x00207f02, - 0x0030e1c9, - 0x00231302, - 0x00231302, - 0x00231302, - 0x0029ab85, - 0x00231302, - 0x0029ab85, - 0x00342c8c, - 0x003a734c, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024a143, - 0x00202d43, - 0x00124f88, - 0x0004d044, - 0x0004a008, - 0x002050c2, - 0x46602682, - 0x0023f983, - 0x002230c4, - 0x002086c3, - 0x002d60c4, - 0x00232986, - 0x00206803, - 0x002eecc4, - 0x00269085, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x0025564a, - 0x00232f46, - 0x0036bf8c, - 0x001795c8, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0020c943, - 0x002c7386, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x00007282, - 0x000d58c7, - 0x000b2708, - 0x0000e7ce, - 0x00084c92, - 0x000dd48b, - 0x47301e05, - 0x4771c74c, - 0x00115e0a, - 0x0003c250, - 0x0016d488, - 0x0007c0c7, - 0x000678cb, - 0x0016c489, - 0x0016d387, - 0x0018d647, - 0x0007bfc7, - 0x000187c6, - 0x00125908, - 0x47c1a0c6, - 0x000a2f8d, - 0x001157d0, - 0x480072c2, - 0x00120948, - 0x00069447, - 0x00090089, - 0x00051906, - 0x0000a402, - 0x000718ca, - 0x000f14c7, - 0x000ec787, - 0x0009d709, - 0x000a0188, - 0x00154d45, - 0x000da70e, - 0x00007fce, - 0x0001278f, - 0x00014989, - 0x00043589, - 0x0007254b, - 0x0013f48f, - 0x0009928c, - 0x000ee2cb, - 0x000c1888, - 0x000edec7, - 0x000f2bc8, - 0x0013decb, - 0x0014648c, - 0x0014d50c, - 0x0015024c, - 0x0016a1cd, - 0x00022fc8, - 0x00078f09, - 0x0017198b, - 0x000b9ec6, - 0x000c8b05, - 0x000cd410, - 0x0012af86, - 0x000546c5, - 0x000d6887, - 0x000ed1ca, - 0x000b258a, - 0x0006a4c6, - 0x00091e8d, - 0x000c49c8, - 0x0017f7c8, - 0x00045289, - 0x000ecd0c, - 0x001235c4, - 0x0005aa46, - 0x00002402, - 0x00141846, - 0x00003c02, - 0x000bdc05, - 0x00000301, - 0x00032c43, - 0x47b8ad46, - 0x0008d103, - 0x00000fc2, - 0x000920c4, - 0x000001c2, - 0x0001db44, - 0x00000102, - 0x000076c2, - 0x000054c2, - 0x00102e02, - 0x00000302, - 0x00101e02, - 0x00001a82, - 0x0001ed82, - 0x00039382, - 0x00027542, - 0x00003f42, - 0x00008f02, - 0x00015403, - 0x0001be02, - 0x00000482, - 0x0000bf82, - 0x000046c2, - 0x0000a6c2, - 0x00033ac2, - 0x00009f82, - 0x00000042, - 0x00002fc2, - 0x00000842, - 0x0004af03, - 0x000024c2, - 0x00000b42, - 0x000aa4c2, - 0x0000aa02, - 0x00012942, - 0x00005d42, - 0x00034342, - 0x000e5e02, - 0x00004502, - 0x00169282, - 0x00007342, - 0x0000b302, - 0x0004a143, - 0x00000602, - 0x0000bd82, - 0x00001542, - 0x00013c42, - 0x00048285, - 0x00009382, - 0x00053ec2, - 0x0003dc03, - 0x00002282, - 0x0000b082, - 0x00002542, - 0x00000802, - 0x000066c2, - 0x00002882, - 0x00001142, - 0x00002402, - 0x0006d2c7, - 0x002111c3, - 0x002050c2, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x00213783, - 0x0020c943, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x0028d143, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x0021e083, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00200041, - 0x0021e083, - 0x0024a143, - 0x00205bc3, - 0x00202d43, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x002a3dc3, - 0x00205c03, - 0x00236443, - 0x00280e03, - 0x0029e403, - 0x0025b183, - 0x002d60c3, - 0x0037c544, - 0x0024a143, - 0x00202d43, - 0x0021d903, - 0x0031fb04, - 0x00246203, - 0x00001383, - 0x00200103, - 0x0022c688, - 0x00325604, - 0x0031420a, - 0x00398246, - 0x003a3c07, - 0x0022220a, - 0x0026e389, - 0x003aa4c7, - 0x003afa8a, - 0x00341d03, - 0x0037e08b, - 0x002e93c9, - 0x0038b385, - 0x002c5387, - 0x00002682, - 0x0022f303, - 0x002ca0c7, - 0x00227545, - 0x002e1c89, - 0x00215403, - 0x00228086, - 0x002b6243, - 0x000e2683, - 0x000fae86, - 0x000528c6, - 0x00006787, - 0x00214506, - 0x0021ee05, - 0x0020ba07, - 0x00338c47, - 0x4a2d60c3, - 0x0032f547, - 0x0035a603, - 0x00386005, - 0x0037c544, - 0x00226d88, - 0x002a998c, - 0x002a8245, - 0x00366646, - 0x002c9f87, - 0x003a8987, - 0x00216787, - 0x00217148, - 0x0026becf, - 0x0026f005, - 0x0023fa87, - 0x0027d707, - 0x0029d2ca, - 0x0028bec9, - 0x002d0085, - 0x002d190a, - 0x000e51c6, - 0x002b62c5, - 0x0036b044, - 0x002d75c6, - 0x002e6587, - 0x0023bbc7, - 0x0020ae88, - 0x00203b45, - 0x00227446, - 0x003a4f05, - 0x00262505, - 0x0021c284, - 0x0033e2c7, - 0x002ccb0a, - 0x0020ef88, - 0x002ee906, - 0x0000c943, - 0x002ca385, - 0x00373306, - 0x003ae706, - 0x002545c6, - 0x0021e083, - 0x00388707, - 0x0027d685, - 0x0024a143, - 0x003aa74d, - 0x00201543, - 0x0020af88, - 0x00219d84, - 0x00276185, - 0x0029d1c6, - 0x00238246, - 0x002099c7, - 0x0029e447, - 0x00265ec5, - 0x00202d43, - 0x0032b1c7, - 0x0033a7c9, - 0x00259609, - 0x0026974a, - 0x002421c2, - 0x00385fc4, - 0x002d0684, - 0x0021de07, - 0x00238448, - 0x002d7d49, - 0x00320fc9, - 0x002d8907, - 0x0026eb06, - 0x000da486, - 0x002dbd04, - 0x002dc30a, - 0x002e0c08, - 0x002e11c9, - 0x00294906, - 0x002fef05, - 0x0020ee48, - 0x002bb40a, - 0x00215543, - 0x0031eec6, - 0x002d8a07, - 0x0020eb05, - 0x002e4145, - 0x00215b03, - 0x0024ffc4, - 0x00230f85, - 0x00282347, - 0x002f1a45, - 0x002fa286, - 0x001380c5, - 0x00229203, - 0x00229209, - 0x00275f4c, - 0x002a6a8c, - 0x002c2388, - 0x0028c8c7, - 0x002f0ec8, - 0x002f1fca, - 0x002f370b, - 0x002e9508, - 0x00366748, - 0x0035c846, - 0x0020b745, - 0x0030cfca, - 0x0020d345, - 0x00200142, - 0x002b9187, - 0x00261946, - 0x003511c5, - 0x0032c7c9, - 0x003857c5, - 0x002db345, - 0x00385bc9, - 0x00373186, - 0x0023a0c8, - 0x00263643, - 0x0020fb46, - 0x00275386, - 0x002fd845, - 0x002fd849, - 0x002ac109, - 0x00242507, - 0x000fd6c4, - 0x002fd6c7, - 0x00320ec9, - 0x00222405, - 0x0003b0c8, - 0x00341745, - 0x00348345, - 0x00215c09, - 0x002043c2, - 0x00262784, - 0x00203e02, - 0x002024c2, - 0x0033ef05, - 0x002d7148, - 0x00376685, - 0x002b8183, - 0x002b8185, - 0x002c5743, - 0x0020fb02, - 0x0033fcc4, - 0x002873c3, - 0x00204402, - 0x002e4a84, - 0x002d1603, - 0x00209082, - 0x002b8203, - 0x00288504, - 0x002b0f83, - 0x0023c744, - 0x002004c2, - 0x00272dc3, - 0x002066c3, - 0x00205442, - 0x002ea082, - 0x002abf49, - 0x00201d42, - 0x00285804, - 0x00207302, - 0x0020ecc4, - 0x0026eac4, - 0x002dfb44, - 0x00202402, - 0x0023df02, - 0x00211583, - 0x002f25c3, - 0x0023f084, - 0x002636c4, - 0x002ac304, - 0x002c0484, - 0x002fcc03, - 0x00334cc3, - 0x002e5144, - 0x002fe284, - 0x002fe586, - 0x0025a082, - 0x00202682, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x002050c2, - 0x00341d03, - 0x0022f303, - 0x00215403, - 0x00202b83, - 0x002d60c3, - 0x0037c544, - 0x002ac204, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x002dc944, - 0x00398ec3, - 0x002b0203, - 0x00343804, - 0x00341546, - 0x00200dc3, - 0x0021b203, - 0x0021bf03, - 0x002ab503, - 0x002761c3, - 0x0020c943, - 0x00226a05, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x002d5543, - 0x00231f83, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024af03, - 0x0024a143, - 0x002355c4, - 0x00202d43, - 0x002a5b84, - 0x002d73c5, - 0x00202682, - 0x00202a82, - 0x00200fc2, - 0x002032c2, - 0x00200282, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x002169c3, - 0x0021db44, - 0x001795c8, - 0x0022f303, - 0x00201543, - 0x002451c4, - 0x001795c8, - 0x0022f303, - 0x00246ec4, - 0x0037c544, - 0x00201543, - 0x00202742, - 0x00202d43, - 0x00226a03, - 0x002eb585, - 0x00200142, - 0x002fe3c3, - 0x002050c2, - 0x001795c8, - 0x00202682, - 0x00215403, - 0x002d60c3, - 0x00200842, - 0x00202d43, - 0x002050c2, - 0x003afc47, - 0x0025a6c5, - 0x0022dc84, - 0x00385246, - 0x00210ccb, - 0x002633c9, - 0x00366586, - 0x00334289, - 0x002b3088, - 0x00206a03, - 0x001795c8, - 0x0022ae47, - 0x00271c88, - 0x00322683, - 0x002395c4, - 0x002395cb, - 0x0026b845, - 0x003261c8, - 0x002fdc49, - 0x0025ad83, - 0x0022f303, - 0x00202ac8, - 0x002f0047, - 0x00322c86, - 0x00215403, - 0x00322787, - 0x002d60c3, - 0x002e32c6, - 0x0024af03, - 0x00230e47, - 0x0024b587, - 0x0038fe87, - 0x0033e245, - 0x002042c3, - 0x0020a34b, - 0x00376188, - 0x002261c8, - 0x0033a986, - 0x002e7d49, - 0x0031a007, - 0x002f9185, - 0x002d3e44, - 0x0026e5c8, - 0x00339fca, - 0x0033a209, - 0x002563c3, - 0x0027dc45, - 0x00288903, - 0x002ac506, - 0x002fa584, - 0x002fafc8, - 0x0039000b, - 0x0033edc5, - 0x002b2e06, - 0x002b4c05, - 0x002b5188, - 0x002b6407, - 0x0037c747, - 0x00313e07, - 0x00290744, - 0x00307907, - 0x00290746, - 0x0021e083, - 0x002bee08, - 0x0024ca03, - 0x002c5a08, - 0x002cd8c5, - 0x00208dc8, - 0x00236247, - 0x0024a143, - 0x00243f43, - 0x00286844, - 0x002ef887, - 0x00208743, - 0x0024b64b, - 0x00206683, - 0x0024c9c4, - 0x002eb608, - 0x00202d43, - 0x00317605, - 0x002e6485, - 0x00208cc6, - 0x00217a45, - 0x002cdc84, - 0x0020be42, - 0x002e1483, - 0x0036b0ca, - 0x0039b843, - 0x003a1909, - 0x00307606, - 0x00216548, - 0x00288046, - 0x00224c47, - 0x00330fc8, - 0x00317408, - 0x002f4883, - 0x00376743, - 0x00225009, - 0x002c92c3, - 0x00345d46, - 0x0025a346, - 0x00311846, - 0x0032ad89, - 0x002fd304, - 0x00211d43, - 0x00380f45, - 0x00308c49, - 0x00230f43, - 0x002fa144, - 0x003596c4, - 0x00213ac4, - 0x0028ea06, - 0x00246303, - 0x00246308, - 0x00257448, - 0x002ea846, - 0x002f8f8b, - 0x002f92c8, - 0x002f94cb, - 0x002fb609, - 0x002fad87, - 0x002fba88, - 0x002fc643, - 0x002cbc86, - 0x00211047, - 0x00291445, - 0x00348c89, - 0x002e768d, - 0x00216391, - 0x0022e985, - 0x002050c2, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002cb284, - 0x002d60c3, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0020c943, - 0x0024a143, - 0x00202d43, - 0x00297fc3, - 0x002169c3, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0020c943, - 0x0024a143, - 0x00202d43, - 0x00213ac2, - 0x00200101, - 0x002050c2, - 0x00200001, - 0x0030f302, - 0x001795c8, - 0x00220a85, - 0x00200301, - 0x0002f303, - 0x00200381, - 0x00200081, - 0x00201101, - 0x003336c2, - 0x00339f04, - 0x00362603, - 0x00200641, - 0x00200a81, - 0x00200041, - 0x00200ec1, - 0x003a6547, - 0x0039028f, - 0x002c1d06, - 0x00200201, - 0x00268c86, - 0x00200181, - 0x00200601, - 0x0033580e, - 0x00200281, - 0x00202d43, - 0x00204401, - 0x0026a605, - 0x0020be42, - 0x00215a05, - 0x002002c1, - 0x002004c1, - 0x00200141, - 0x00200142, - 0x00200441, - 0x00200f41, - 0x00209f01, - 0x002018c1, - 0x00203c01, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x0021e7c3, - 0x0022f303, - 0x002d60c3, - 0x00088d48, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x014d3308, - 0x001795c8, - 0x00043944, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0024a143, - 0x00202d43, - 0x00201383, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002cb284, - 0x00202d43, - 0x00298545, - 0x00324984, - 0x0022f303, - 0x0024a143, - 0x00202d43, - 0x00202682, - 0x0022f303, - 0x00233789, - 0x00215403, - 0x00237f89, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002dbb08, - 0x002180c7, - 0x002eb585, - 0x003afc47, - 0x00210ccb, - 0x00210808, - 0x00334289, - 0x0022ae47, - 0x00202ac8, - 0x002e32c6, - 0x0024b587, - 0x002261c8, - 0x0033a986, - 0x0031a007, - 0x0033a209, - 0x00386c49, - 0x002b2e06, - 0x002b3a85, - 0x002bee08, - 0x0024ca03, - 0x002c5a08, - 0x00236247, - 0x00208743, - 0x00328c47, - 0x00217a45, - 0x002d6f88, - 0x00375645, - 0x00376743, - 0x002793c9, - 0x002a4e87, - 0x002fa144, - 0x003596c4, - 0x002f8f8b, - 0x002f92c8, - 0x002fad87, - 0x0022f303, - 0x00215403, - 0x00205c03, - 0x00202d43, - 0x002153c3, - 0x002d60c3, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002050c2, - 0x00202682, - 0x00202d43, - 0x001795c8, - 0x002050c2, - 0x00202682, - 0x00200fc2, - 0x00200842, - 0x0020a142, - 0x0024a143, - 0x00200282, - 0x002050c2, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x00200fc2, - 0x002d60c3, - 0x0024af03, - 0x0021e083, - 0x00212284, - 0x0024a143, - 0x00218e83, - 0x00202d43, - 0x002fd304, - 0x0021d903, - 0x002d60c3, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00201543, - 0x00202d43, - 0x0039d747, - 0x0022f303, - 0x00397007, - 0x00374486, - 0x00206643, - 0x0020e383, - 0x002d60c3, - 0x002212c3, - 0x0037c544, - 0x0036f344, - 0x002cdd46, - 0x00200883, - 0x0024a143, - 0x00202d43, - 0x00298545, - 0x0020d284, - 0x00316303, - 0x00229c83, - 0x002b9187, - 0x00321805, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00204182, - 0x002c4b03, - 0x002acc83, - 0x00341d03, - 0x5462f303, - 0x00206382, - 0x00215403, - 0x002086c3, - 0x002d60c3, - 0x0037c544, - 0x00376343, - 0x0026f003, - 0x0021e083, - 0x00212284, - 0x54a04782, - 0x0024a143, - 0x00202d43, - 0x00225183, - 0x00223d03, - 0x00213ac2, - 0x0021d903, - 0x001795c8, - 0x002d60c3, - 0x0020c744, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00238c04, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x00376b84, - 0x0020f5c4, - 0x002c7386, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x00261946, - 0x00018a4b, - 0x0001a0c6, - 0x0001d74a, - 0x000fc70a, - 0x001795c8, - 0x0020c844, - 0x0022f303, - 0x00341cc4, - 0x00215403, - 0x002453c4, - 0x002d60c3, - 0x00253a43, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x0032400b, - 0x0039f50a, - 0x003aebcc, - 0x002050c2, - 0x00202682, - 0x00200fc2, - 0x002a3645, - 0x0037c544, - 0x00204502, - 0x0021e083, - 0x0020f5c4, - 0x002032c2, - 0x00200282, - 0x00204842, - 0x00213ac2, - 0x00141d03, - 0x002eac89, - 0x0025a1c8, - 0x0037fb89, - 0x0024b3c9, - 0x0025980a, - 0x00261e0a, - 0x0020c342, - 0x0021ed82, - 0x00002682, - 0x0022f303, - 0x00207102, - 0x0023fc46, - 0x003521c2, - 0x00218882, - 0x003a1c0e, - 0x00272e0e, - 0x0027c7c7, - 0x0032a5c7, - 0x0026d382, - 0x00215403, - 0x002d60c3, - 0x002010c2, - 0x00200842, - 0x002343cf, - 0x00208e42, - 0x00234747, - 0x0023a587, - 0x0023adc7, - 0x0023bd4c, - 0x0033ab8c, - 0x00203184, - 0x0027dc4a, - 0x0024fa82, - 0x0020aa02, - 0x002ac684, - 0x002152c2, - 0x002b6dc2, - 0x0033adc4, - 0x00218f82, - 0x00212942, - 0x0033aa07, - 0x0037b645, - 0x00234342, - 0x00234344, - 0x00369282, - 0x002c8e08, - 0x0024a143, - 0x00397d88, - 0x00208542, - 0x00236f45, - 0x00378006, - 0x00202d43, - 0x00209382, - 0x002d7f87, - 0x0000be42, - 0x00269145, - 0x00209105, - 0x002025c2, - 0x0022f5c2, - 0x003148ca, - 0x00265d4a, - 0x0021e042, - 0x00323a44, - 0x00202782, - 0x00385e88, - 0x0020d482, - 0x002fcfc8, - 0x002f6b87, - 0x002f6e89, - 0x00209182, - 0x002fb845, - 0x0025a685, - 0x002bc0cb, - 0x002bce4c, - 0x00230cc8, - 0x002fbc08, - 0x0025a082, - 0x00209a82, - 0x002050c2, - 0x001795c8, - 0x00202682, - 0x0022f303, - 0x00200fc2, - 0x002032c2, - 0x00200282, - 0x00202d43, - 0x00204842, - 0x002050c2, - 0x56a02682, - 0x56ed60c3, - 0x0035ea43, - 0x00204502, - 0x0024a143, - 0x0035e943, - 0x00202d43, - 0x002d3c03, - 0x0026d3c6, - 0x016169c3, - 0x001795c8, - 0x000546c5, - 0x00064ec7, - 0x57600e82, - 0x57a001c2, - 0x57e00e02, - 0x582006c2, - 0x5860efc2, - 0x58a00302, - 0x58e02682, - 0x59205102, - 0x59622a82, - 0x59a03f42, - 0x00272e03, - 0x00211743, - 0x59e16b42, - 0x5a201202, - 0x00047407, - 0x5a62c702, - 0x5aa01702, - 0x5ae02f02, - 0x5b208202, - 0x5b602fc2, - 0x5ba00842, - 0x000bb1c5, - 0x00222fc3, - 0x0038d5c4, - 0x5be152c2, - 0x5c24b8c2, - 0x5c600682, - 0x0007874b, - 0x5ca00182, - 0x5d20ab02, - 0x5d604502, - 0x5da0a142, - 0x5de60542, - 0x5e204042, - 0x5e600542, - 0x5ea07342, - 0x5ee04782, - 0x5f2033c2, - 0x5f6032c2, - 0x5fa39202, - 0x5fe04282, - 0x60241a02, - 0x0006f0c4, - 0x002d7a43, - 0x60605902, - 0x60a19d02, - 0x60e06042, - 0x61201c02, - 0x61600282, - 0x61a04402, - 0x000d6b47, - 0x61e05042, - 0x62200b02, - 0x62604842, - 0x62a4d302, - 0x000ecd0c, - 0x62e1a602, - 0x63273802, - 0x63601602, - 0x63a000c2, - 0x63e03442, - 0x64259982, - 0x64600f42, - 0x64a06842, - 0x64e75702, - 0x652151c2, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x5cf76343, - 0x00281103, - 0x00226a84, - 0x0025a0c6, - 0x002e1543, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x00215e02, - 0x00215e02, - 0x00376343, - 0x00281103, - 0x65a2f303, - 0x00215403, - 0x0022c983, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x001795c8, - 0x00202682, - 0x0022f303, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002451c4, - 0x00202682, - 0x0022f303, - 0x0024fb83, - 0x00215403, - 0x00246ec4, - 0x00205c03, - 0x002d60c3, - 0x0037c544, - 0x0024af03, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x00226a03, - 0x002eb585, - 0x00241543, - 0x0021d903, - 0x00202682, - 0x0022f303, - 0x00376343, - 0x0024a143, - 0x00202d43, - 0x002050c2, - 0x00341d03, - 0x001795c8, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x00232986, - 0x0037c544, - 0x0024af03, - 0x00212284, - 0x0024a143, - 0x00202d43, - 0x0021e703, - 0x0022f303, - 0x00215403, - 0x0024a143, - 0x00202d43, - 0x0022f303, - 0x0001a0c6, - 0x00215403, - 0x002d60c3, - 0x000cc086, - 0x0024a143, - 0x00202d43, - 0x00305c88, - 0x00309549, - 0x00317c89, - 0x0032c608, - 0x00379e48, - 0x00379e49, - 0x002050c2, - 0x00321645, - 0x0022de83, - 0x68202682, - 0x00215403, - 0x002d60c3, - 0x00262e87, - 0x002761c3, - 0x0021e083, - 0x0024a143, - 0x00205bc3, - 0x00212583, - 0x00201543, - 0x00202d43, - 0x00232f46, - 0x00200142, - 0x0021d903, - 0x001795c8, - 0x002050c2, - 0x00341d03, - 0x00202682, - 0x0022f303, - 0x00215403, - 0x002d60c3, - 0x0037c544, - 0x0021e083, - 0x0024a143, - 0x00202d43, - 0x002169c3, + 0x27a003, + 0x328304, + 0x272406, + 0x36e2c3, + 0x36e2c6, + 0x3a6306, + 0x260483, + 0x206e44, + 0x345647, + 0x272048, + 0x1a00882, + 0x30abc7, + 0x355a09, + 0x2eb6ca, + 0x2eb6cb, + 0x22f803, + 0x28f606, + 0x232a05, + 0x1e00702, + 0x215f44, + 0x236483, + 0x278b45, + 0x2208ac2, + 0x330fc3, + 0x26cf584, + 0x328c05, + 0x2a014c2, + 0x378a0e, + 0x24d0c3, + 0x37e606, + 0x37e60b, + 0x2e01c42, + 0x350f47, + 0x235446, + 0x3200a42, + 0x258943, + 0x258944, + 0x343086, + 0x23c1c8, + 0x287c86, + 0x2717c4, + 0x3600ec2, + 0x329b89, + 0x3a2ec7, + 0x2f7646, + 0x357689, + 0x295f08, + 0x2af504, + 0x3a0846, + 0x216b86, + 0x3a02a82, + 0x25af4f, + 0x34280e, + 0x211dc4, + 0x2bc7c5, + 0x2e4bc5, + 0x2ec7c9, + 0x23ecc9, + 0x340e47, + 0x212fc6, + 0x212f03, + 0x3e04a42, + 0x270703, + 0x22098a, + 0x20b0c3, + 0x2607c5, + 0x287302, + 0x287309, + 0x4201e02, + 0x208184, + 0x206986, + 0x237bc5, + 0x34ea44, + 0x4a86a04, + 0x201e03, + 0x231a44, + 0x4e02902, + 0x328044, + 0x31ea44, + 0x22350a, + 0x52009c2, + 0x2d2687, + 0x238088, + 0x5a08f02, + 0x321407, + 0x2b7744, + 0x2b7747, + 0x385185, + 0x36ccc7, + 0x340c06, + 0x21cec4, + 0x357985, + 0x299d07, + 0x6a01cc2, + 0x2af103, + 0x213402, + 0x375ac3, + 0x6e136c2, + 0x283905, + 0x7204a02, + 0x329244, + 0x27eec5, + 0x211d07, + 0x3731ce, + 0x2e3e04, + 0x245c04, + 0x208143, + 0x2ce4c9, + 0x307ecb, + 0x30f508, + 0x31a288, + 0x31e088, + 0x323148, + 0x3574ca, + 0x36cbc7, + 0x2272c6, + 0x769ed02, + 0x375043, + 0x37fa83, + 0x38d3c4, + 0x260d03, + 0x2604c3, + 0x1711602, + 0x7a070c2, + 0x24a0c5, + 0x28ecc6, + 0x2c9e84, + 0x396e07, + 0x32cc06, + 0x341644, + 0x3a9e87, + 0x2070c3, + 0x7ebefc2, + 0x8305b42, + 0x8619ac2, + 0x219ac6, + 0x8a00002, + 0x37dd45, + 0x312b43, + 0x204384, + 0x2db0c4, + 0x2db0c5, + 0x2075c3, + 0x8f27883, + 0x920a882, + 0x28a905, + 0x28a90b, + 0x22be86, + 0x20cd4b, + 0x276844, + 0x20d309, + 0x20f104, + 0x960f602, + 0x210943, + 0x2125c3, + 0x1612742, + 0x245dc3, + 0x21274a, + 0x9a12bc2, + 0x2161c5, + 0x290fca, + 0x2cd084, + 0x213a83, + 0x213f44, + 0x2159c3, + 0x2159c4, + 0x2159c7, + 0x216f85, + 0x217785, + 0x218e86, + 0x219d86, + 0x21a783, + 0x21e908, + 0x258283, + 0x9e03482, + 0x21f388, + 0x21474b, + 0x222208, + 0x222986, + 0x223907, + 0x227e88, + 0xa63a242, + 0xaa715c2, + 0x2e3688, + 0x29f847, + 0x242c85, + 0x242c88, + 0x343988, + 0x383b83, + 0x22a7c4, + 0x38d402, + 0xae2cb02, + 0xb2519c2, + 0xba2ce42, + 0x22ce43, + 0xbe01482, + 0x206e03, + 0x201484, + 0x21a903, + 0x2af4c4, + 0x25fc4b, + 0x214683, + 0x2d3946, + 0x223384, + 0x29e18e, + 0x341045, + 0x265808, + 0x2246c7, + 0x2246ca, + 0x22fd03, + 0x275647, + 0x308085, + 0x22fd04, + 0x22fd06, + 0x22fd07, + 0x2c62c4, + 0x373507, + 0x2028c4, + 0x2093c4, + 0x2093c6, + 0x2dc104, + 0x221c46, + 0x2138c3, + 0x226b48, + 0x303708, + 0x245bc3, + 0x245d83, + 0x395544, + 0x39b103, + 0xc200482, + 0xc707ac2, + 0x2004c3, + 0x208406, + 0x381043, + 0x228584, + 0xca19942, + 0x2d7f03, + 0x219943, + 0x21b682, + 0xce008c2, + 0x2bb486, + 0x233907, + 0x2e9005, + 0x344c04, + 0x2a1c45, + 0x2021c7, + 0x26e685, + 0x2aff89, + 0x2c75c6, + 0x2d0108, + 0x2e8f06, + 0xd2092c2, + 0x23bd88, + 0x300a86, + 0x20dc05, + 0x3af1c7, + 0x303604, + 0x303605, + 0x287e44, + 0x287e48, + 0xd60a1c2, + 0xda036c2, + 0x32f506, + 0x3160c8, + 0x338e05, + 0x33a086, + 0x33c2c8, + 0x35ff48, + 0xdec8b85, + 0x2036c4, + 0x324407, + 0xe20d9c2, + 0xe61eb82, + 0xfa06a82, + 0x3597c5, + 0x2a22c5, + 0x3753c6, + 0x317a47, + 0x22aac7, + 0x1022bf83, + 0x2a5b07, + 0x2d4808, + 0x390509, + 0x378bc7, + 0x3a7507, + 0x22e108, + 0x22e906, + 0x22f846, + 0x23020c, + 0x230d8a, + 0x231247, + 0x2328cb, + 0x233747, + 0x23374e, + 0x234744, + 0x234a44, + 0x238e47, + 0x25a647, + 0x23d186, + 0x23d187, + 0x23dd87, + 0x13208942, + 0x23f586, + 0x23f58a, + 0x23f80b, + 0x240bc7, + 0x241585, + 0x2418c3, + 0x241dc6, + 0x241dc7, + 0x23ee83, + 0x1362ea42, + 0x24268a, + 0x13b56b42, + 0x13ea4c42, + 0x14244142, + 0x14635542, + 0x244ec5, + 0x2459c4, + 0x14e00682, + 0x3280c5, + 0x278b03, + 0x315b45, + 0x2124c4, + 0x293906, + 0x202bc6, + 0x28ab03, + 0x3654c4, + 0x324ec3, + 0x15201582, + 0x208d04, + 0x324986, + 0x208d05, + 0x258006, + 0x3af2c8, + 0x21ecc4, + 0x236248, + 0x2e01c5, + 0x32bcc8, + 0x2dce46, + 0x2b4247, + 0x22f244, + 0x22f246, + 0x323fc3, + 0x385503, + 0x2bfd08, + 0x30d944, + 0x341787, + 0x248cc6, + 0x30af09, + 0x35c488, + 0x330488, + 0x24f8c4, + 0x3a2543, + 0x206c82, + 0x1560b042, + 0x15a05382, + 0x3abf43, + 0x15e12c42, + 0x345784, + 0x2af205, + 0x29d8c3, + 0x2306c4, + 0x302947, + 0x344943, + 0x2465c8, + 0x205f85, + 0x308144, + 0x36bb43, + 0x27ee45, + 0x27ef84, + 0x2090c6, + 0x20c244, + 0x20d086, + 0x211c46, + 0x261504, + 0x2199c3, + 0x162b1a02, + 0x350e05, + 0x223cc3, + 0x16600442, + 0x2bbf85, + 0x231b03, + 0x231b09, + 0x16a04142, + 0x172110c2, + 0x329605, + 0x21cd46, + 0x34c707, + 0x2c9a46, + 0x2b9908, + 0x2b990b, + 0x20844b, + 0x2e9205, + 0x2d07c5, + 0x2c0a89, + 0x1600bc2, + 0x2616c8, + 0x20cf84, + 0x17a00202, + 0x25f883, + 0x1825a806, + 0x380ec8, + 0x18602e42, + 0x226088, + 0x18a08b02, + 0x27698a, + 0x228bc3, + 0x3b23c6, + 0x3997c8, + 0x204188, + 0x334fc6, + 0x36a0c7, + 0x25b147, + 0x21670a, + 0x2cd104, + 0x33ed84, + 0x3554c9, + 0x38ff05, + 0x342a06, + 0x20b203, + 0x249604, + 0x2143c4, + 0x24fd07, + 0x22d547, + 0x26b1c4, + 0x216645, + 0x375488, + 0x3617c7, + 0x364607, + 0x18e09342, + 0x2e3cc4, + 0x2946c8, + 0x3859c4, + 0x246a04, + 0x246e05, + 0x246f47, + 0x210c49, + 0x247d04, + 0x248a09, + 0x248fc8, + 0x249384, + 0x249387, + 0x249b83, + 0x24a707, + 0x1649242, + 0x17a6b82, + 0x24b646, + 0x24c287, + 0x24c884, + 0x24d607, + 0x24e647, + 0x24ed88, + 0x24f503, + 0x23d6c2, + 0x202442, + 0x251003, + 0x251004, + 0x25100b, + 0x31a388, + 0x257f44, + 0x251d05, + 0x253c87, + 0x2569c5, + 0x36bf0a, + 0x257e83, + 0x1920db02, + 0x258184, + 0x25a409, + 0x25f283, + 0x25f347, + 0x36b309, + 0x376348, + 0x208a03, + 0x27dd47, + 0x27e489, + 0x2840c3, + 0x285e04, + 0x286bc9, + 0x289286, + 0x28a343, + 0x201c82, + 0x244d43, + 0x39c247, + 0x37de85, + 0x35a206, + 0x24a304, + 0x2e6285, + 0x220943, + 0x21a9c6, + 0x20d502, + 0x390ec4, + 0x225902, + 0x2daa43, + 0x196007c2, + 0x247643, + 0x21a204, + 0x21a207, + 0x204686, + 0x24cdc2, + 0x19a53a02, + 0x3af4c4, + 0x19e39ec2, + 0x1a202842, + 0x31aac4, + 0x31aac5, + 0x28de45, + 0x2c2a86, + 0x1a603ac2, + 0x308d05, + 0x3a5245, + 0x29a0c3, + 0x204e86, + 0x212b05, + 0x219a42, + 0x339cc5, + 0x219a44, + 0x21ec03, + 0x21ee43, + 0x1aa0be82, + 0x2f1f87, + 0x361a44, + 0x361a49, + 0x249504, + 0x23a103, + 0x34a009, + 0x350cc8, + 0x2a2144, + 0x2a2146, + 0x2a4543, + 0x214dc3, + 0x22a0c4, + 0x250cc3, + 0x1aee0682, + 0x301c42, + 0x1b210702, + 0x314a48, + 0x3801c8, + 0x394986, + 0x245545, + 0x229b85, + 0x210705, + 0x224242, + 0x1b6931c2, + 0x1633602, + 0x390088, + 0x23bcc5, + 0x3052c4, + 0x2e0105, + 0x32b887, + 0x257c84, + 0x23d4c2, + 0x1ba03e82, + 0x30d204, + 0x2140c7, + 0x39ee87, + 0x36cc84, + 0x290f83, + 0x245b04, + 0x245b08, + 0x22fb86, + 0x22fb8a, + 0x210b04, + 0x291308, + 0x24f004, + 0x223a06, + 0x293184, + 0x359ac6, + 0x341dc9, + 0x266587, + 0x235903, + 0x1be10442, + 0x26ecc3, + 0x20f802, + 0x1c217e82, + 0x2df3c6, + 0x363888, + 0x2a3687, + 0x3a4389, + 0x23a009, + 0x2a3f45, + 0x2a50c9, + 0x2a5f45, + 0x2a6a09, + 0x2a8105, + 0x288484, + 0x288487, + 0x2998c3, + 0x2a8e07, + 0x3a78c6, + 0x2a9607, + 0x2a0f05, + 0x2ab543, + 0x1c630842, + 0x392904, + 0x1ca29982, + 0x25a043, + 0x1ce134c2, + 0x2e6cc6, + 0x238005, + 0x2acc47, + 0x335583, + 0x260c84, + 0x203bc3, + 0x2e33c3, + 0x1d20b542, + 0x1da00042, + 0x3a6404, + 0x23d683, + 0x397285, + 0x2aafc5, + 0x1de04982, + 0x1e600942, + 0x27e086, + 0x20ad44, + 0x30da84, + 0x30da8a, + 0x1ee02002, + 0x2f920a, + 0x36f688, + 0x1f2023c4, + 0x215ac3, + 0x24bc43, + 0x31e1c9, + 0x22dec9, + 0x302a46, + 0x1f602243, + 0x2d9885, + 0x2f9e4d, + 0x207286, + 0x21134b, + 0x1fa016c2, + 0x34c188, + 0x1fe1ea02, + 0x20208282, + 0x370545, + 0x20603fc2, + 0x269947, + 0x2a6507, + 0x21db43, + 0x258c48, + 0x20a07382, + 0x282f04, + 0x212d83, + 0x34bb85, + 0x383983, + 0x237ac6, + 0x2eae04, + 0x245d43, + 0x26f203, + 0x20e0abc2, + 0x2e9184, + 0x353985, + 0x367f07, + 0x27bbc3, + 0x2ad443, + 0x2adc43, + 0x1622602, + 0x2add03, + 0x2adf83, + 0x21202dc2, + 0x2ce884, + 0x27f1c6, + 0x20fa03, + 0x2ae303, + 0x216afcc2, + 0x2afcc8, + 0x2b0784, + 0x2402c6, + 0x2b0bc7, + 0x218fc6, + 0x338f04, + 0x2f2001c2, + 0x3a778b, + 0x2f29ce, + 0x21d4cf, + 0x234343, + 0x2fa44d02, + 0x1605482, + 0x2fe04b42, + 0x227dc3, + 0x233343, + 0x238c46, + 0x2f0ac6, + 0x2e6587, + 0x379084, + 0x3028da82, + 0x306062c2, + 0x2f9b45, + 0x2ee007, + 0x2f15c6, + 0x30a6cf82, + 0x26cf84, + 0x372003, + 0x30e0ac82, + 0x352e03, + 0x3910c4, + 0x2b6949, + 0x16bd702, + 0x31235c82, + 0x2dac86, + 0x26b485, + 0x31645cc2, + 0x31a00102, + 0x33e107, + 0x2033c9, + 0x355c8b, + 0x25af05, + 0x3748c9, + 0x2be006, + 0x22bec7, + 0x2060c4, + 0x2cf089, + 0x35dbc7, + 0x2b7ec7, + 0x20ae83, + 0x20ae86, + 0x2dd5c7, + 0x2387c3, + 0x27cf86, + 0x31e049c2, + 0x32231d82, + 0x21bfc3, + 0x260885, + 0x221ac7, + 0x343c86, + 0x37de05, + 0x376b04, + 0x2de1c5, + 0x2e9b84, + 0x32600f02, + 0x321d87, + 0x2e2904, + 0x22ddc4, + 0x22ddcd, + 0x24c649, + 0x2e04c8, + 0x22bb04, + 0x323605, + 0x2633c7, + 0x2ceb44, + 0x32ccc7, + 0x35ab05, + 0x32b9a984, + 0x2ce185, + 0x25df44, + 0x374206, + 0x317845, + 0x32e34802, + 0x213b44, + 0x213b45, + 0x38d946, + 0x37df45, + 0x2548c4, + 0x2e7043, + 0x380406, + 0x20efc5, + 0x210e45, + 0x317944, + 0x210b83, + 0x210b8c, + 0x33289bc2, + 0x33605602, + 0x33a17382, + 0x39a883, + 0x39a884, + 0x33e03702, + 0x2fd288, + 0x35a2c5, + 0x37f144, + 0x29fe46, + 0x34233a82, + 0x3461ca02, + 0x34a00982, + 0x2b5dc5, + 0x2613c6, + 0x24fc44, + 0x3435c6, + 0x2d2446, + 0x207a03, + 0x34f2afca, + 0x23d9c5, + 0x2f3506, + 0x2f3509, + 0x367547, + 0x291748, + 0x295dc9, + 0x218388, + 0x322e86, + 0x23db83, + 0x35206a42, + 0x386e83, + 0x386e89, + 0x3442c8, + 0x3560ad82, + 0x35a0f842, + 0x232003, + 0x2cff85, + 0x251804, + 0x2c1a09, + 0x2aa9c4, + 0x2b09c8, + 0x20f843, + 0x2600c4, + 0x329d03, + 0x22dd07, + 0x35e3c442, + 0x25a2c2, + 0x22af85, + 0x26d1c9, + 0x220ec3, + 0x27f804, + 0x2d9844, + 0x263443, + 0x28088a, + 0x3636f542, + 0x36613b02, + 0x2bef43, + 0x3721c3, + 0x1660082, + 0x260f43, + 0x36a50702, + 0x3891c4, + 0x36e02ac2, + 0x3730db04, + 0x34a586, + 0x27e2c4, + 0x2406c3, + 0x284a83, + 0x21c443, + 0x23fb86, + 0x2c4d05, + 0x2bf7c7, + 0x22bd89, + 0x2c37c5, + 0x2c4c46, + 0x2c5248, + 0x2c5446, + 0x256604, + 0x29920b, + 0x2c70c3, + 0x2c70c5, + 0x2c7208, + 0x21e782, + 0x33e402, + 0x37629382, + 0x37a03642, + 0x2632c3, + 0x37e08b82, + 0x26e443, + 0x2c7504, + 0x2c83c3, + 0x38607682, + 0x2c9f8b, + 0x38acc586, + 0x2ef8c6, + 0x2ccbc8, + 0x38ecae42, + 0x39212602, + 0x3961ee82, + 0x39a0b602, + 0x39e02642, + 0x20264b, + 0x3a201842, + 0x2262c3, + 0x316c05, + 0x321ac6, + 0x3a611004, + 0x20b687, + 0x32478a, + 0x31ec86, + 0x2e9444, + 0x262ec3, + 0x3b20dbc2, + 0x202b42, + 0x2570c3, + 0x3b64c083, + 0x2635c7, + 0x317747, + 0x3ca51107, + 0x228b87, + 0x214983, + 0x2248ca, + 0x214984, + 0x248bc4, + 0x248bca, + 0x24f205, + 0x3ce02402, + 0x24e143, + 0x3d200dc2, + 0x20f543, + 0x26ec83, + 0x3da01742, + 0x2a5a84, + 0x220684, + 0x201745, + 0x2d8385, + 0x2368c6, + 0x236c46, + 0x3de09142, + 0x3e201042, + 0x3360c5, + 0x2ef5d2, + 0x24ca86, + 0x226a03, + 0x33b046, + 0x2ff645, + 0x160b282, + 0x4660d682, + 0x2efd43, + 0x310b83, + 0x2dbcc3, + 0x46a07902, + 0x378d03, + 0x46e12f42, + 0x2a3443, + 0x2ce8c8, + 0x222f43, + 0x222f46, + 0x313c87, + 0x210586, + 0x21058b, + 0x2e9387, + 0x392704, + 0x47602102, + 0x3a0745, + 0x202b03, + 0x22cd43, + 0x3188c3, + 0x3188c6, + 0x2d088a, + 0x273f43, + 0x235304, + 0x316006, + 0x20e006, + 0x47a04703, + 0x260b47, + 0x37ea8d, + 0x38cd87, + 0x298f45, + 0x246406, + 0x20f003, + 0x492050c3, + 0x49609242, + 0x3283c4, + 0x22d28c, + 0x32bf09, + 0x23a787, + 0x249885, + 0x268144, + 0x272748, + 0x279205, + 0x286a85, + 0x28d409, + 0x2f7703, + 0x2f7704, + 0x2a4bc4, + 0x49a00ac2, + 0x265883, + 0x49e92c42, + 0x2a1d46, + 0x160b142, + 0x4a299882, + 0x2b5cc8, + 0x2ce0c7, + 0x299885, + 0x2de9cb, + 0x2d1dc6, + 0x2debc6, + 0x2f8346, + 0x224cc4, + 0x2fba46, + 0x2d51c8, + 0x232243, + 0x247403, + 0x247404, + 0x2d6c84, + 0x2d7007, + 0x2d8185, + 0x4a6d82c2, + 0x4aa0a742, + 0x20a745, + 0x29cd44, + 0x2d9b8b, + 0x2dafc8, + 0x2db6c4, + 0x26cfc2, + 0x4b2aff02, + 0x2aff03, + 0x2dbb04, + 0x2dd185, + 0x22a547, + 0x2dfc44, + 0x2e9244, + 0x4b608582, + 0x35d1c9, + 0x2e0b05, + 0x25b1c5, + 0x2e1685, + 0x4ba1d603, + 0x2e24c4, + 0x2e24cb, + 0x2e4144, + 0x2e45cb, + 0x2e6745, + 0x21d60a, + 0x2e7108, + 0x2e730a, + 0x2e7583, + 0x2e758a, + 0x4be297c2, + 0x4c242242, + 0x263c83, + 0x4c6e8e82, + 0x2e8e83, + 0x4caea942, + 0x4cf132c2, + 0x2e9a04, + 0x21ea46, + 0x343305, + 0x2ea303, + 0x27a5c6, + 0x22b644, + 0x4d203942, + 0x2b6e84, + 0x2c070a, + 0x387f47, + 0x237e46, + 0x2d0d47, + 0x22d3c3, + 0x24f088, + 0x25ab8b, + 0x302b45, + 0x2b7285, + 0x2b7286, + 0x217c04, + 0x323908, + 0x203943, + 0x216a84, + 0x216a87, + 0x342fc6, + 0x31f2c6, + 0x29dfca, + 0x246104, + 0x24610a, + 0x322406, + 0x322407, + 0x251d87, + 0x276184, + 0x276189, + 0x266c05, + 0x239e4b, + 0x279443, + 0x20d243, + 0x229bc3, + 0x384904, + 0x4d6034c2, + 0x25b486, + 0x2ab2c5, + 0x2b2645, + 0x223e46, + 0x248684, + 0x4da00c02, + 0x223f44, + 0x4de0ed42, + 0x2307c4, + 0x225703, + 0x4e301102, + 0x308803, + 0x258606, + 0x4e602942, + 0x2d30c8, + 0x3abc84, + 0x3abc86, + 0x31abc6, + 0x253d44, + 0x380385, + 0x2035c8, + 0x204d07, + 0x20c307, + 0x20c30f, + 0x2945c6, + 0x220bc3, + 0x220bc4, + 0x228444, + 0x233083, + 0x223b44, + 0x22fe84, + 0x4ea2b382, + 0x28a843, + 0x23a203, + 0x4ee03682, + 0x253503, + 0x345843, + 0x21780a, + 0x29fa47, + 0x23b08c, + 0x23b346, + 0x23b886, + 0x23d307, + 0x22e547, + 0x241f49, + 0x21f4c4, + 0x242e44, + 0x4f24ecc2, + 0x4f604042, + 0x260944, + 0x375f06, + 0x22e9c8, + 0x380d04, + 0x269986, + 0x2c9a05, + 0x26ae48, + 0x208643, + 0x26df45, + 0x272903, + 0x25b2c3, + 0x25b2c4, + 0x2744c3, + 0x4fa50642, + 0x4fe01f82, + 0x279309, + 0x286985, + 0x288004, + 0x34adc5, + 0x213604, + 0x24be47, + 0x340005, + 0x2512c4, + 0x2512c8, + 0x2d5b06, + 0x2d9544, + 0x2de648, + 0x2e2747, + 0x50202742, + 0x2e6e04, + 0x2e63c4, + 0x2b80c7, + 0x50679d44, + 0x236b42, + 0x50a03a02, + 0x24ddc3, + 0x2dab84, + 0x235c43, + 0x2754c5, + 0x50e4acc2, + 0x2ed405, + 0x20b5c2, + 0x373e45, + 0x363a45, + 0x512198c2, + 0x2198c4, + 0x51609642, + 0x236506, + 0x2abb46, + 0x26d308, + 0x2b90c8, + 0x2e6c44, + 0x2f5905, + 0x302f49, + 0x34c804, + 0x2d0844, + 0x261603, + 0x216845, + 0x2bd7c7, + 0x277b44, + 0x2ea5cd, + 0x2eab42, + 0x2eab43, + 0x2eac03, + 0x51a04582, + 0x38a045, + 0x22b107, + 0x228c44, + 0x228c47, + 0x295fc9, + 0x2c0849, + 0x20c987, + 0x279043, + 0x279048, + 0x21db89, + 0x2ebb87, + 0x2ebf05, + 0x2ec6c6, + 0x2ecd06, + 0x2ece85, + 0x24c745, + 0x51e00c42, + 0x226605, + 0x2bae0a, + 0x2a7a08, + 0x21c906, + 0x2e6987, + 0x26b104, + 0x3ae3c7, + 0x2f0186, + 0x52200242, + 0x38d646, + 0x2f374a, + 0x2f4745, + 0x526d3382, + 0x52a56142, + 0x2dd906, + 0x35ee88, + 0x39f047, + 0x52e00602, + 0x213d03, + 0x200a06, + 0x30b804, + 0x313b46, + 0x34d186, + 0x37fb0a, + 0x397385, + 0x20fa86, + 0x2133c3, + 0x2133c4, + 0x2083c2, + 0x300a43, + 0x53248c82, + 0x2c5603, + 0x2f9484, + 0x2dca84, + 0x35efca, + 0x2468c3, + 0x287d48, + 0x279dca, + 0x234cc7, + 0x2f5d86, + 0x2363c4, + 0x28fcc2, + 0x208bc2, + 0x5360a6c2, + 0x245ac3, + 0x251b47, + 0x27a887, + 0x38ffcb, + 0x328284, + 0x30c5c7, + 0x22a646, + 0x219bc7, + 0x29f984, + 0x2c7d05, + 0x291bc5, + 0x53a1bf02, + 0x2225c6, + 0x33a583, + 0x2be6c2, + 0x32b206, + 0x53e0fe42, + 0x542012c2, + 0x2012c5, + 0x5461c642, + 0x54a05702, + 0x2e7dc5, + 0x38e705, + 0x20fb45, + 0x26c743, + 0x239ac5, + 0x2d1e87, + 0x2a94c5, + 0x3a0145, + 0x265904, + 0x243586, + 0x24aac4, + 0x54e05a02, + 0x27dbc5, + 0x2a2c87, + 0x2299c8, + 0x26ed46, + 0x26ed4d, + 0x26f609, + 0x26f612, + 0x2ee645, + 0x2f2703, + 0x55a0f042, + 0x2e7b84, + 0x207303, + 0x318f45, + 0x35d4c5, + 0x55e12dc2, + 0x36bb83, + 0x56244302, + 0x566cd782, + 0x56a13082, + 0x33f185, + 0x331083, + 0x264048, + 0x56e07e02, + 0x57201bc2, + 0x2a5a46, + 0x325c0a, + 0x20d803, + 0x239103, + 0x2edd83, + 0x57e03f02, + 0x66207942, + 0x66a0a302, + 0x201242, + 0x38d449, + 0x2bcb44, + 0x258f48, + 0x66eea342, + 0x67204102, + 0x2e4805, + 0x232d08, + 0x24a508, + 0x39e64c, + 0x239cc3, + 0x23bc82, + 0x6760c402, + 0x2c3c46, + 0x2f6c05, + 0x326903, + 0x32b746, + 0x2f6d46, + 0x235d83, + 0x2f8103, + 0x2f8b46, + 0x2f9904, + 0x276a86, + 0x2c7285, + 0x2f9c8a, + 0x233f84, + 0x2faac4, + 0x34da8a, + 0x67a74b82, + 0x271185, + 0x2fcf4a, + 0x2fdcc5, + 0x2fe844, + 0x2fe946, + 0x2feac4, + 0x228946, + 0x67e00282, + 0x237786, + 0x238845, + 0x201d07, + 0x300fc6, + 0x23d504, + 0x2c8047, + 0x32af06, + 0x267e05, + 0x267e07, + 0x39b987, + 0x39b98e, + 0x2232c6, + 0x32cb85, + 0x283a47, + 0x2f1c03, + 0x366e07, + 0x35ba05, + 0x212644, + 0x214382, + 0x267207, + 0x379104, + 0x238bc4, + 0x25a14b, + 0x21fdc3, + 0x286807, + 0x21fdc4, + 0x2a4c87, + 0x22ac83, + 0x32e98d, + 0x38a888, + 0x2511c4, + 0x2511c5, + 0x301705, + 0x2ff303, + 0x68214a02, + 0x300a03, + 0x301143, + 0x399f04, + 0x27e585, + 0x21eec7, + 0x213446, + 0x36f643, + 0x32b34b, + 0x32f70b, + 0x27338b, + 0x27e68a, + 0x2a55cb, + 0x2caf0b, + 0x2d33cc, + 0x2f8711, + 0x33d50a, + 0x35030b, + 0x37a40b, + 0x3aef8a, + 0x3b0f8a, + 0x301b0d, + 0x3032ce, + 0x30438b, + 0x30464a, + 0x305811, + 0x305c4a, + 0x30614b, + 0x30668e, + 0x30720c, + 0x3075cb, + 0x30788e, + 0x307c0c, + 0x3094ca, + 0x30a6cc, + 0x6870a9ca, + 0x30bbc9, + 0x30dd0a, + 0x30df8a, + 0x30e20b, + 0x31014e, + 0x3104d1, + 0x319509, + 0x31974a, + 0x31a00b, + 0x31baca, + 0x31c656, + 0x31de0b, + 0x3200ca, + 0x320dca, + 0x32528b, + 0x329a09, + 0x32f309, + 0x33154d, + 0x331dcb, + 0x332b0b, + 0x3334cb, + 0x333c89, + 0x3342ce, + 0x3346ca, + 0x335b0a, + 0x33620a, + 0x33698b, + 0x3371cb, + 0x33748d, + 0x338b0d, + 0x339950, + 0x339e0b, + 0x33b3cc, + 0x33c04b, + 0x33dc0b, + 0x33fb8b, + 0x34814b, + 0x348bcf, + 0x348f8b, + 0x349bca, + 0x34a2c9, + 0x34a709, + 0x34b0cb, + 0x34b38e, + 0x34e10b, + 0x34eecf, + 0x3512cb, + 0x35158b, + 0x35184b, + 0x351c8a, + 0x355889, + 0x35898f, + 0x36104c, + 0x36150c, + 0x36278e, + 0x362fcf, + 0x36338e, + 0x363e90, + 0x36428f, + 0x36574e, + 0x365c0c, + 0x365f12, + 0x367b11, + 0x3680ce, + 0x36850e, + 0x368a4e, + 0x368dcf, + 0x36918e, + 0x369513, + 0x3699d1, + 0x369e0e, + 0x36a28c, + 0x36ad53, + 0x36b550, + 0x36c18c, + 0x36c48c, + 0x36c94b, + 0x36dfce, + 0x36e64b, + 0x36ea8b, + 0x37090c, + 0x37954a, + 0x379c0c, + 0x379f0c, + 0x37a209, + 0x37b60b, + 0x37b8c8, + 0x37bac9, + 0x37bacf, + 0x37d40b, + 0x37e10a, + 0x38154c, + 0x383409, + 0x3837c8, + 0x384bcb, + 0x3852cb, + 0x38644a, + 0x3866cb, + 0x386c0c, + 0x387948, + 0x38aa8b, + 0x38d14b, + 0x39028b, + 0x391b0b, + 0x39b50b, + 0x39b7c9, + 0x39bd0d, + 0x3a0f8a, + 0x3a1ed7, + 0x3a3b58, + 0x3a8a09, + 0x3a9c0b, + 0x3aa3d4, + 0x3aa8cb, + 0x3aae4a, + 0x3ab2ca, + 0x3ab54b, + 0x3ac450, + 0x3ac851, + 0x3ad10a, + 0x3ae58d, + 0x3aec8d, + 0x3b134b, + 0x3b2746, + 0x2226c3, + 0x68a5b343, + 0x385d06, + 0x28e605, + 0x2d6487, + 0x33d3c6, + 0x1627342, + 0x2ad589, + 0x27a3c4, + 0x2d0348, + 0x245a03, + 0x2e7ac7, + 0x22eb82, + 0x2acc83, + 0x68e006c2, + 0x2c2686, + 0x2c36c4, + 0x328a44, + 0x23e083, + 0x23e085, + 0x696cd7c2, + 0x2dba04, + 0x2760c7, + 0x1662e02, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x2020c3, + 0x200882, + 0x77a48, + 0x206a82, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x20b803, + 0x3152d6, + 0x318493, + 0x30c449, + 0x324308, + 0x3a05c9, + 0x2fd0c6, + 0x30d250, + 0x303e13, + 0x208888, + 0x2407c7, + 0x27c647, + 0x29f48a, + 0x2f9509, + 0x34cf89, + 0x290ccb, + 0x340c06, + 0x32324a, + 0x222986, + 0x279fc3, + 0x2f1ec5, + 0x226b48, + 0x2365cd, + 0x35988c, + 0x238507, + 0x304e0d, + 0x2036c4, + 0x22ff8a, + 0x2308ca, + 0x230d8a, + 0x304107, + 0x23cfc7, + 0x23ff44, + 0x22f246, + 0x340fc4, + 0x2f0448, + 0x2aaa09, + 0x2b9906, + 0x2b9908, + 0x24328d, + 0x2c0a89, + 0x204188, + 0x25b147, + 0x20150a, + 0x24c286, + 0x259f07, + 0x2b1e04, + 0x248087, + 0x33a34a, + 0x25958e, + 0x210705, + 0x2ff04b, + 0x2f2509, + 0x22dec9, + 0x2a6347, + 0x3a278a, + 0x2b8007, + 0x2f2b09, + 0x359d48, + 0x3141cb, + 0x2cff85, + 0x2e038a, + 0x21ec49, + 0x32688a, + 0x2c384b, + 0x247f8b, + 0x290a55, + 0x2d59c5, + 0x25b1c5, + 0x2e24ca, + 0x2501ca, + 0x376507, + 0x220283, + 0x29e308, + 0x2cb24a, + 0x3abc86, + 0x241949, + 0x26ae48, + 0x2d9544, + 0x235c49, + 0x2b90c8, + 0x2dcd87, + 0x27dbc6, + 0x2a2c87, + 0x297b87, + 0x23f985, + 0x25388c, + 0x2511c5, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x206a82, + 0x22bf83, + 0x24c083, + 0x2020c3, + 0x204703, + 0x22bf83, + 0x24c083, + 0x222f43, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x77a48, + 0x206a82, + 0x200e42, + 0x230fc2, + 0x207382, + 0x203202, + 0x2d3cc2, + 0x462bf83, + 0x231b03, + 0x20f583, + 0x250cc3, + 0x202243, + 0x220ec3, + 0x24c083, + 0x204703, + 0x232dc3, + 0x77a48, + 0x329904, + 0x25fe87, + 0x262203, + 0x3395c4, + 0x22ea83, + 0x286c03, + 0x250cc3, + 0x200882, + 0x127883, + 0x5606a82, + 0x230fc2, + 0x23c4, + 0x200fc2, + 0xe1c44, + 0x77a48, + 0x20e503, + 0x2cd683, + 0x5e2bf83, + 0x22ff84, + 0x6231b03, + 0x6650cc3, + 0x20b542, + 0x2023c4, + 0x24c083, + 0x2f1d03, + 0x2018c2, + 0x204703, + 0x21f0c2, + 0x2e9943, + 0x202942, + 0x207703, + 0x26af03, + 0x201d02, + 0x77a48, + 0x20e503, + 0x2f1d03, + 0x2018c2, + 0x2e9943, + 0x202942, + 0x207703, + 0x26af03, + 0x201d02, + 0x2e9943, + 0x202942, + 0x207703, + 0x26af03, + 0x201d02, + 0x22bf83, + 0x327883, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x220ec3, + 0x211004, + 0x24c083, + 0x204703, + 0x209202, + 0x21d603, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x327883, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x24c083, + 0x204703, + 0x2ebf05, + 0x212dc2, + 0x200882, + 0x77a48, + 0x250cc3, + 0x260e41, + 0x20bd81, + 0x260e01, + 0x20bb01, + 0x275d81, + 0x275e41, + 0x262281, + 0x24b581, + 0x2f8901, + 0x301dc1, + 0x200141, + 0x200001, + 0x77a48, + 0x200481, + 0x200741, + 0x200081, + 0x201501, + 0x2007c1, + 0x200901, + 0x200041, + 0x202381, + 0x2001c1, + 0x2000c1, + 0x200341, + 0x200cc1, + 0x200fc1, + 0x200ac1, + 0x213041, + 0x200c01, + 0x200241, + 0x200a01, + 0x2002c1, + 0x200281, + 0x201d01, + 0x2041c1, + 0x200781, + 0x200641, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x200fc2, + 0x204703, + 0x142b87, + 0x1c106, + 0x18a4a, + 0x89808, + 0x51688, + 0x51a47, + 0x60f46, + 0xcdfc5, + 0x62145, + 0x72606, + 0x122706, + 0x223504, + 0x3212c7, + 0x77a48, + 0x2c8144, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x250cc3, + 0x202243, + 0x220ec3, + 0x24c083, + 0x204703, + 0x212dc2, + 0x2b6f03, + 0x214583, + 0x279643, + 0x202a82, + 0x249c83, + 0x201e03, + 0x2056c3, + 0x200001, + 0x2075c3, + 0x276844, + 0x3355c3, + 0x30da43, + 0x21eb83, + 0x378d83, + 0xa22bf83, + 0x234a44, + 0x21eb43, + 0x22e0c3, + 0x231b03, + 0x231843, + 0x211a83, + 0x2a2383, + 0x30d9c3, + 0x226083, + 0x2143c3, + 0x24ce04, + 0x23d6c2, + 0x250f43, + 0x2579c3, + 0x279003, + 0x260d83, + 0x345903, + 0x250cc3, + 0x2e87c3, + 0x2037c3, + 0x2023c3, + 0x249283, + 0x35d7c3, + 0x300b83, + 0x387883, + 0x200983, + 0x232003, + 0x220ec3, + 0x21e782, + 0x28a503, + 0x24c083, + 0x16020c3, + 0x255bc3, + 0x232943, + 0x212c03, + 0x204703, + 0x20b103, + 0x21d603, + 0x23b303, + 0x2f8183, + 0x2e9b03, + 0x303b85, + 0x2298c3, + 0x2e9b43, + 0x2eb283, + 0x2133c4, + 0x25a903, + 0x32be83, + 0x277083, + 0x232dc3, + 0x212dc2, + 0x239cc3, + 0x2fb8c4, + 0x238bc4, + 0x24cd43, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x206a82, + 0x204703, + 0xb62bf83, + 0x250cc3, + 0x220ec3, + 0x20dd02, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x6c2, + 0x201142, + 0x223342, + 0x77a48, + 0x6a82, + 0x2338c2, + 0x207082, + 0x23eac2, + 0x202402, + 0x209142, + 0x62145, + 0x202702, + 0x2018c2, + 0x207902, + 0x201702, + 0x200ac2, + 0x386d02, + 0x203a02, + 0x227d82, + 0x117c0d, + 0xed209, + 0x4a30b, + 0xd1d48, + 0x472c9, + 0x250cc3, + 0x77a48, + 0x77a48, + 0x52946, + 0x200882, + 0x223504, + 0x206a82, + 0x22bf83, + 0x200e42, + 0x231b03, + 0x20f582, + 0x2c8144, + 0x202243, + 0x20ad82, + 0x24c083, + 0x200fc2, + 0x204703, + 0x25b1c6, + 0x30e7cf, + 0x701683, + 0x77a48, + 0x206a82, + 0x20f583, + 0x250cc3, + 0x220ec3, + 0x1479b8b, + 0x206a82, + 0x22bf83, + 0x250cc3, + 0x24c083, + 0x200882, + 0x206b82, + 0x20a882, + 0xea2bf83, + 0x23e902, + 0x231b03, + 0x249242, + 0x225902, + 0x250cc3, + 0x224242, + 0x24b342, + 0x24cd02, + 0x204242, + 0x28cf02, + 0x205302, + 0x200902, + 0x210442, + 0x20b882, + 0x217e82, + 0x2ad442, + 0x23ba82, + 0x312042, + 0x24dcc2, + 0x220ec3, + 0x202ac2, + 0x24c083, + 0x243482, + 0x273342, + 0x204703, + 0x249d02, + 0x203682, + 0x24ecc2, + 0x201f82, + 0x2198c2, + 0x2d3382, + 0x21bf02, + 0x244302, + 0x222742, + 0x30464a, + 0x349bca, + 0x37f58a, + 0x3b28c2, + 0x20b642, + 0x245d02, + 0xeeaef89, + 0xf26050a, + 0xf42e107, + 0xbac2, + 0x6050a, + 0x247204, + 0xfe2bf83, + 0x231b03, + 0x248fc4, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x220ec3, + 0x24c083, + 0x2020c3, + 0x204703, + 0x2298c3, + 0x2232c3, + 0x77a48, + 0x1460ec4, + 0x60745, + 0x5f68a, + 0x10a642, + 0x17e606, + 0x106aef89, + 0x142d47, + 0x1e02, + 0x1ab7ca, + 0xda987, + 0x77a48, + 0xfff08, + 0xd8c7, + 0x1181d10b, + 0x3482, + 0x1a0947, + 0xdc0a, + 0x19f20f, + 0x124b4f, + 0x1eb82, + 0x6a82, + 0xa22c8, + 0xec94a, + 0x143f48, + 0x1582, + 0x13564b, + 0x16fcc8, + 0x7f087, + 0xdaa8a, + 0x58a4b, + 0x172cc9, + 0x16fbc7, + 0xf564c, + 0xb587, + 0xd0b0a, + 0x14bcc8, + 0xf20ce, + 0x5360e, + 0xda7cb, + 0x17664b, + 0xecf4b, + 0x1c109, + 0x1df4b, + 0x22d8d, + 0x24b0b, + 0x277cd, + 0x2b70d, + 0x12c9ca, + 0x38a0b, + 0x5910b, + 0x67505, + 0x10b510, + 0x14338f, + 0xe37cf, + 0x1e34d, + 0x76650, + 0x8b02, + 0x11f24008, + 0x142a08, + 0x122e4205, + 0x47d0b, + 0x4f508, + 0x17680a, + 0x58189, + 0x625c7, + 0x62907, + 0x62ac7, + 0x656c7, + 0x660c7, + 0x663c7, + 0x67807, + 0x68687, + 0x69007, + 0x691c7, + 0x6a487, + 0x6a647, + 0x6a807, + 0x6a9c7, + 0x6acc7, + 0x6b347, + 0x6c307, + 0x6c8c7, + 0x6d087, + 0x6d807, + 0x6d9c7, + 0x6ddc7, + 0x6e307, + 0x6e507, + 0x6e7c7, + 0x6e987, + 0x6eb47, + 0x6f087, + 0x6fa87, + 0x70547, + 0x72d47, + 0x73007, + 0x73647, + 0x73807, + 0x73b87, + 0x749c7, + 0x74c47, + 0x75047, + 0x758c7, + 0x75a87, + 0x75ec7, + 0x76c07, + 0x76f07, + 0x77147, + 0x77307, + 0x77687, + 0x78007, + 0xd502, + 0x44c4a, + 0xf8407, + 0x124c8a0b, + 0x14c8a16, + 0x1bb11, + 0xdf0ca, + 0xa214a, + 0x52946, + 0x18e90b, + 0x10702, + 0x184551, + 0x99ac9, + 0x92dc9, + 0x10442, + 0x9ec8a, + 0xa3849, + 0xa3f4f, + 0xa48ce, + 0xa5408, + 0x134c2, + 0x799c9, + 0x1779ce, + 0xac08c, + 0xd438f, + 0x194a8e, + 0x1378c, + 0x18549, + 0x19451, + 0x1ae88, + 0x13ab12, + 0x12bb8d, + 0x2f10d, + 0x398cb, + 0x43755, + 0x44b09, + 0x4540a, + 0x57b49, + 0x5bb90, + 0x6a1cb, + 0x7be8f, + 0x7ce4b, + 0x8048c, + 0x80e50, + 0x85a0a, + 0x8a3cd, + 0x13f80e, + 0x14aa0a, + 0x8f30c, + 0x97854, + 0x99751, + 0x9cc0b, + 0x9de8f, + 0xab18d, + 0xaba0e, + 0xdcc4c, + 0x15eacc, + 0xdc94b, + 0xe8a4e, + 0xeb550, + 0x12e34b, + 0x16a70d, + 0xb48cf, + 0xb83cc, + 0xb978e, + 0xb9f91, + 0xbbd0c, + 0x119e47, + 0xc174d, + 0xc60cc, + 0xd5c50, + 0xe608d, + 0xfc987, + 0xeecd0, + 0xf3d88, + 0xf494b, + 0x16f84f, + 0x15bd88, + 0xdf2cd, + 0x173dd0, + 0xafec3, + 0xac82, + 0x2bb09, + 0x5340a, + 0xfb906, + 0x128de7c9, + 0x11e03, + 0x10ad11, + 0xccf47, + 0xd36d0, + 0xd3b8c, + 0xd4d85, + 0x1189c8, + 0x19c9ca, + 0x1976c7, + 0x1042, + 0x6184a, + 0xe3b09, + 0x34aca, + 0x19ef8f, + 0x4160b, + 0x1283cc, + 0x128692, + 0xadd85, + 0x161b4a, + 0x12ee1545, + 0x1132c3, + 0x186d02, + 0xe9e4a, + 0xcfc88, + 0x124ac7, + 0x34c2, + 0xed42, + 0x2942, + 0x1a7a10, + 0x4042, + 0x2e9cf, + 0x72606, + 0x176c8e, + 0xd7c0b, + 0x14ac08, + 0xc9d49, + 0x17cbd2, + 0x404d, + 0x496c8, + 0x4a1c9, + 0x4c40d, + 0x4e7c9, + 0x52a8b, + 0x55d88, + 0x5f4c8, + 0x67f88, + 0x68209, + 0x6840a, + 0x6898c, + 0xea08a, + 0xf81c7, + 0x1684d, + 0xed84b, + 0x7a1cc, + 0x65910, + 0x1bc2, + 0xd65cd, + 0x3f02, + 0x7942, + 0xf810a, + 0xdefca, + 0xe79cb, + 0x592cc, + 0xffc8e, + 0x199fcd, + 0xf2f88, + 0x6c2, + 0x10b6778e, + 0x10c2e107, + 0x111ab089, + 0x129c3, + 0x1171b7cc, + 0xbac2, + 0x146151, + 0x1676d1, + 0x176fd1, + 0x131111, + 0x11b70f, + 0x11fdcc, + 0x124f4d, + 0x15c8cd, + 0x16da95, + 0xbacc, + 0x50b50, + 0x1091cc, + 0x10f6cc, + 0x4f2c9, + 0xbac2, + 0x14620e, + 0x16778e, + 0x17708e, + 0x1311ce, + 0x11b7cc, + 0x11fe89, + 0xbb89, + 0x50c0d, + 0x109289, + 0x10f789, + 0x158543, + 0x1892c3, + 0xbac2, + 0xd2d05, + 0x1ab7c4, + 0x135a04, + 0x181444, + 0x17e004, + 0x17a784, + 0x142d44, + 0x1424703, + 0x1416703, + 0xf2b84, + 0x8b02, + 0x199fc3, + 0x200882, + 0x206a82, + 0x200e42, + 0x209342, + 0x20f582, + 0x200fc2, + 0x202942, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c3, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x24c083, + 0x204703, + 0x39f83, + 0x250cc3, + 0x200882, + 0x327883, + 0x14a2bf83, + 0x380d87, + 0x250cc3, + 0x39a883, + 0x211004, + 0x24c083, + 0x204703, + 0x24e9ca, + 0x25b1c5, + 0x21d603, + 0x2012c2, + 0x77a48, + 0x77a48, + 0x6a82, + 0x110842, + 0x1a0a85, + 0x77a48, + 0x2bf83, + 0xf2447, + 0xcd44f, + 0xfb984, + 0x172e4a, + 0xabcc7, + 0x18908a, + 0x18ed8a, + 0xfb906, + 0x8a4d, + 0x127883, + 0x77a48, + 0x6a82, + 0x48fc4, + 0x86d83, + 0xebf05, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x201e03, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x292f83, + 0x2232c3, + 0x201e03, + 0x223504, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22a543, + 0x22bf83, + 0x231b03, + 0x210c43, + 0x20f583, + 0x250cc3, + 0x2023c4, + 0x265603, + 0x232003, + 0x220ec3, + 0x24c083, + 0x204703, + 0x21d603, + 0x200a43, + 0x16e2bf83, + 0x231b03, + 0x245e83, + 0x250cc3, + 0x2805c3, + 0x232003, + 0x204703, + 0x208583, + 0x325ec4, + 0x77a48, + 0x1762bf83, + 0x231b03, + 0x2a54c3, + 0x250cc3, + 0x220ec3, + 0x211004, + 0x24c083, + 0x204703, + 0x220303, + 0x77a48, + 0x17e2bf83, + 0x231b03, + 0x20f583, + 0x2020c3, + 0x204703, + 0x77a48, + 0x142e107, + 0x327883, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x211004, + 0x24c083, + 0x204703, + 0x175d04, + 0x340dc5, + 0x77a48, + 0x742, + 0x33303, + 0x2cf588, + 0x23ca87, + 0x223504, + 0x366b06, + 0x36d946, + 0x77a48, + 0x23bd43, + 0x2e31c9, + 0x2b3f55, + 0xb3f5f, + 0x22bf83, + 0x334fd2, + 0x1011c6, + 0x13b685, + 0x17680a, + 0x58189, + 0x334d8f, + 0x2c8144, + 0x23c485, + 0x35d590, + 0x324507, + 0x2020c3, + 0x255bc8, + 0x2d2d8a, + 0x241204, + 0x2e0f83, + 0x25b1c6, + 0x2012c2, + 0x387d0b, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x2e8283, + 0x206a82, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x39a883, + 0x206f83, + 0x204703, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x24c083, + 0x204703, + 0x200882, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x223504, + 0x22bf83, + 0x231b03, + 0x30db04, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x2037c3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2614c3, + 0x6ab03, + 0x19a883, + 0x24c083, + 0x204703, + 0x30464a, + 0x31c409, + 0x33e2cb, + 0x33e94a, + 0x349bca, + 0x356a0b, + 0x36f44a, + 0x37954a, + 0x37f58a, + 0x37f80b, + 0x39c709, + 0x39e40a, + 0x39e94b, + 0x3aab8b, + 0x3b0d4a, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x220ec3, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x2625c4, + 0x219242, + 0x211004, + 0x278b45, + 0x201e03, + 0x223504, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x248fc4, + 0x2c8144, + 0x2023c4, + 0x232003, + 0x24c083, + 0x204703, + 0x297985, + 0x22a543, + 0x21d603, + 0x25ad03, + 0x2512c4, + 0x260e04, + 0x279645, + 0x77a48, + 0x2fa644, + 0x221c46, + 0x287e44, + 0x206a82, + 0x364707, + 0x24b847, + 0x246a04, + 0x2569c5, + 0x2e6285, + 0x2a8e05, + 0x2023c4, + 0x316208, + 0x2031c6, + 0x2e6ec8, + 0x23e385, + 0x2cff85, + 0x214984, + 0x204703, + 0x2e1c44, + 0x355bc6, + 0x25b2c3, + 0x2512c4, + 0x269bc5, + 0x233504, + 0x399e44, + 0x2012c2, + 0x24ec06, + 0x392506, + 0x2f6c05, + 0x200882, + 0x327883, + 0x1d606a82, + 0x233004, + 0x20f582, + 0x220ec3, + 0x20b602, + 0x24c083, + 0x200fc2, + 0x20b803, + 0x2232c3, + 0x77a48, + 0x77a48, + 0x250cc3, + 0x200882, + 0x1e206a82, + 0x250cc3, + 0x26a783, + 0x265603, + 0x31d184, + 0x24c083, + 0x204703, + 0x77a48, + 0x200882, + 0x1ea06a82, + 0x22bf83, + 0x24c083, + 0x204703, + 0x20f042, + 0x212dc2, + 0x39a883, + 0x2d9f83, + 0x200882, + 0x77a48, + 0x206a82, + 0x231b03, + 0x248fc4, + 0x209d03, + 0x250cc3, + 0x2037c3, + 0x220ec3, + 0x24c083, + 0x21a883, + 0x204703, + 0x220283, + 0x125513, + 0x134914, + 0x145c6, + 0x1c106, + 0x514c7, + 0x7a709, + 0x141c0a, + 0x896cd, + 0x11790c, + 0x17ef0a, + 0x62145, + 0x16d408, + 0x72606, + 0x122706, + 0x208b02, + 0x1ab987, + 0x22bf83, + 0xd0a85, + 0x1bb06, + 0x8d1ca, + 0xacf83, + 0x7a6c5, + 0xd003, + 0x18e9cc, + 0x1ade48, + 0x13f348, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x200882, + 0x206a82, + 0x250cc3, + 0x20b542, + 0x24c083, + 0x204703, + 0x20b803, + 0x362fcf, + 0x36338e, + 0x77a48, + 0x22bf83, + 0x43f87, + 0x231b03, + 0x250cc3, + 0x202243, + 0x24c083, + 0x204703, + 0x21fc03, + 0x264fc7, + 0x201c42, + 0x291d49, + 0x200ec2, + 0x3a7d0b, + 0x28b2ca, + 0x28cc09, + 0x200d82, + 0x261046, + 0x254b15, + 0x3a7e55, + 0x257393, + 0x3a83d3, + 0x204a42, + 0x20c905, + 0x32178c, + 0x21b24b, + 0x2543c5, + 0x20b0c2, + 0x287302, + 0x3747c6, + 0x201e02, + 0x25f986, + 0x34be4d, + 0x36fe4c, + 0x30b584, + 0x2009c2, + 0x209ec2, + 0x33aec8, + 0x204a02, + 0x32f986, + 0x2d2944, + 0x254cd5, + 0x257513, + 0x212903, + 0x34b6ca, + 0x35af47, + 0x2e7c09, + 0x229087, + 0x305b42, + 0x200002, + 0x200006, + 0x206e82, + 0x77a48, + 0x212742, + 0x212bc2, + 0x3994c7, + 0x35bac7, + 0x21f085, + 0x203482, + 0x220247, + 0x220408, + 0x23a242, + 0x2715c2, + 0x22ce42, + 0x201482, + 0x300cc8, + 0x21a903, + 0x286f48, + 0x2c77cd, + 0x214683, + 0x2e3f48, + 0x23218f, + 0x23254e, + 0x22338a, + 0x299e51, + 0x29a2d0, + 0x2b2d0d, + 0x2b304c, + 0x20e607, + 0x34b847, + 0x366bc9, + 0x245bc2, + 0x2004c2, + 0x252ecc, + 0x2531cb, + 0x2008c2, + 0x2dcb06, + 0x2092c2, + 0x2036c2, + 0x21eb82, + 0x206a82, + 0x3929c4, + 0x23a547, + 0x208942, + 0x23fac7, + 0x241007, + 0x217442, + 0x20e542, + 0x243e45, + 0x200682, + 0x26794e, + 0x27d94d, + 0x231b03, + 0x377f8e, + 0x2dc3cd, + 0x229343, + 0x203982, + 0x209f44, + 0x245b82, + 0x201502, + 0x34a4c5, + 0x351ac7, + 0x36ed02, + 0x209342, + 0x248847, + 0x24d248, + 0x23d6c2, + 0x2ade06, + 0x252d4c, + 0x25308b, + 0x20db02, + 0x25c18f, + 0x25c550, + 0x25c94f, + 0x25cd15, + 0x25d254, + 0x25d74e, + 0x25dace, + 0x25de4f, + 0x25e20e, + 0x25e594, + 0x25ea93, + 0x25ef4d, + 0x2781c9, + 0x28a283, + 0x2007c2, + 0x31a605, + 0x209d06, + 0x20f582, + 0x270387, + 0x250cc3, + 0x210702, + 0x235e48, + 0x29a091, + 0x29a4d0, + 0x200942, + 0x21e747, + 0x203fc2, + 0x2cec87, + 0x20ac82, + 0x2cf389, + 0x374787, + 0x34aec8, + 0x2261c6, + 0x2d9e83, + 0x322945, + 0x231d82, + 0x200402, + 0x200405, + 0x22aa05, + 0x200f02, + 0x233583, + 0x233587, + 0x200f07, + 0x2013c2, + 0x301344, + 0x2025c3, + 0x2bfb89, + 0x2da648, + 0x217382, + 0x203702, + 0x222047, + 0x224605, + 0x2a4248, + 0x20c5c7, + 0x201dc3, + 0x2a1b86, + 0x2b2b8d, + 0x2b2f0c, + 0x27e146, + 0x207082, + 0x206a42, + 0x20f842, + 0x23200f, + 0x23240e, + 0x2e6307, + 0x200342, + 0x30a2c5, + 0x30a2c6, + 0x250702, + 0x202ac2, + 0x215346, + 0x291f83, + 0x2cebc6, + 0x2c1105, + 0x2c110d, + 0x2c1c55, + 0x2c240c, + 0x2c2c0d, + 0x2c32d2, + 0x203642, + 0x208b82, + 0x201842, + 0x2e4f06, + 0x2abf46, + 0x201042, + 0x209d86, + 0x207902, + 0x223d85, + 0x203202, + 0x267a89, + 0x27074c, + 0x270a8b, + 0x200fc2, + 0x24d688, + 0x20cb42, + 0x209242, + 0x21b006, + 0x3683c5, + 0x21c307, + 0x253b45, + 0x299cc5, + 0x244002, + 0x322882, + 0x200ac2, + 0x27c187, + 0x2d0e4d, + 0x2d11cc, + 0x275587, + 0x20b142, + 0x224742, + 0x242988, + 0x22bc88, + 0x2d57c8, + 0x2df284, + 0x2e8cc7, + 0x2db883, + 0x2aff02, + 0x20d102, + 0x2dfa09, + 0x3a4507, + 0x208582, + 0x273cc5, + 0x242242, + 0x22e1c2, + 0x27b6c3, + 0x27b6c6, + 0x2e8282, + 0x2e98c2, + 0x200d42, + 0x30c286, + 0x209e87, + 0x201442, + 0x203942, + 0x286d8f, + 0x377dcd, + 0x35914e, + 0x2dc24c, + 0x204742, + 0x205fc2, + 0x226005, + 0x3b1146, + 0x214442, + 0x201002, + 0x2034c2, + 0x20c544, + 0x2c7644, + 0x338546, + 0x202942, + 0x27c9c7, + 0x224d83, + 0x226708, + 0x228048, + 0x32ba07, + 0x22ed46, + 0x202742, + 0x238f03, + 0x23ce07, + 0x26e186, + 0x2e4e45, + 0x3497c8, + 0x209642, + 0x321e87, + 0x20b702, + 0x2eab42, + 0x204002, + 0x2df7c9, + 0x200242, + 0x200a02, + 0x275803, + 0x3a0007, + 0x201f02, + 0x2708cc, + 0x270bcb, + 0x27e1c6, + 0x20cf45, + 0x21c642, + 0x205702, + 0x2b2886, + 0x26ba43, + 0x357a07, + 0x249842, + 0x205a02, + 0x254995, + 0x3a8015, + 0x257253, + 0x3a8553, + 0x269cc7, + 0x277c08, + 0x277c10, + 0x278c4f, + 0x28b093, + 0x28c9d2, + 0x291910, + 0x2a248f, + 0x2a8992, + 0x2fcb11, + 0x2f4bd3, + 0x353a92, + 0x320a0f, + 0x2bb04e, + 0x2c0c92, + 0x2c8f51, + 0x2cb48f, + 0x2cc20e, + 0x2cd9d1, + 0x2fbb90, + 0x2db252, + 0x2df5d1, + 0x2e5346, + 0x2e6b07, + 0x2f9347, + 0x202c42, + 0x281b85, + 0x3471c7, + 0x212dc2, + 0x206d02, + 0x229585, + 0x2212c3, + 0x2798c6, + 0x2d100d, + 0x2d134c, + 0x201242, + 0x32160b, + 0x21b10a, + 0x2eae8a, + 0x2b1649, + 0x2dde0b, + 0x20c70d, + 0x362b4c, + 0x224f0a, + 0x22a18c, + 0x24470b, + 0x33bc8c, + 0x25424b, + 0x2706c3, + 0x277806, + 0x2ce482, + 0x2ea342, + 0x221f83, + 0x204102, + 0x204c03, + 0x2562c6, + 0x25cec7, + 0x26d686, + 0x2ecb08, + 0x22b988, + 0x2f3906, + 0x20c402, + 0x2f65cd, + 0x2f690c, + 0x2c8207, + 0x2fa507, + 0x214602, + 0x2342c2, + 0x23cd82, + 0x266dc2, + 0x206a82, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x211004, + 0x24c083, + 0x204703, + 0x20b803, + 0x200882, + 0x200702, + 0x21a8f085, + 0x21e07f05, + 0x2230bf46, + 0x77a48, + 0x226ae4c5, + 0x206a82, + 0x200e42, + 0x22b41485, + 0x22e80385, + 0x23281247, + 0x23615009, + 0x23a58804, + 0x20f582, + 0x210702, + 0x23f6ed45, + 0x24291589, + 0x24772b48, + 0x24aac5c5, + 0x24ebf307, + 0x2521f7c8, + 0x256d8045, + 0x25a01c06, + 0x25e71249, + 0x263ac248, + 0x266b9dc8, + 0x26a981ca, + 0x26e4a044, + 0x272c96c5, + 0x276b5708, + 0x27a6b485, + 0x21a982, + 0x27e00343, + 0x282a14c6, + 0x28645248, + 0x28a067c6, + 0x28ece688, + 0x29321ac6, + 0x29731b84, + 0x202b42, + 0x29a3bf07, + 0x29ea6f84, + 0x2a27bc47, + 0x2a713c87, + 0x200fc2, + 0x2aa98f45, + 0x2af24244, + 0x2b2fc647, + 0x2b623747, + 0x2ba85546, + 0x2be5b885, + 0x2c293d47, + 0x2c6d5388, + 0x2cb1a987, + 0x2cf6ab09, + 0x2d38e705, + 0x2d75e547, + 0x2da8e7c6, + 0x2de61248, + 0x33a60d, + 0x244189, + 0x2e430b, + 0x24b38b, + 0x275c0b, + 0x2a3a4b, + 0x30220b, + 0x3024cb, + 0x302d49, + 0x3048cb, + 0x304b8b, + 0x3053cb, + 0x305eca, + 0x30640a, + 0x306a0c, + 0x309b0b, + 0x30a44a, + 0x3199ca, + 0x32aa8e, + 0x32dace, + 0x32de4a, + 0x33188a, + 0x3323cb, + 0x33268b, + 0x33320b, + 0x34e64b, + 0x34ec4a, + 0x34f90b, + 0x34fbca, + 0x34fe4a, + 0x3500ca, + 0x37110b, + 0x37a88b, + 0x37c1ce, + 0x37c54b, + 0x38618b, + 0x3874cb, + 0x38ad4a, + 0x38afc9, + 0x38b20a, + 0x38c88a, + 0x39d0cb, + 0x39ec0b, + 0x39fa8a, + 0x3a120b, + 0x3a728b, + 0x3b078b, + 0x2e283308, + 0x2e688e49, + 0x2eb61e09, + 0x2eed0348, + 0x3382c5, + 0x207503, + 0x202d44, + 0x3996c5, + 0x258546, + 0x266545, + 0x288644, + 0x270288, + 0x218d45, + 0x290444, + 0x205c87, + 0x29c18a, + 0x3411ca, + 0x387307, + 0x2078c7, + 0x2f47c7, + 0x327dc7, + 0x2b6085, + 0x323d06, + 0x33f687, + 0x26dcc4, + 0x320686, + 0x3a6bc6, + 0x2017c5, + 0x24fa04, + 0x2c0406, + 0x29b587, + 0x32c646, + 0x305107, + 0x27f203, + 0x24e386, + 0x230705, + 0x281347, + 0x2bda0a, + 0x235f44, + 0x21b888, + 0x2eb949, + 0x2d1b07, + 0x330c06, + 0x327b88, + 0x314009, + 0x2396c4, + 0x3619c4, + 0x2fb3c5, + 0x210f08, + 0x2be207, + 0x2a9209, + 0x231548, + 0x2feb46, + 0x243586, + 0x2965c8, + 0x3739c6, + 0x207f05, + 0x285606, + 0x27c348, + 0x231f06, + 0x251f0b, + 0x2343c6, + 0x297d4d, + 0x3a26c5, + 0x2a6e46, + 0x2065c5, + 0x29ae89, + 0x32a347, + 0x3825c8, + 0x2d5046, + 0x296cc9, + 0x3a0486, + 0x2bd985, + 0x237446, + 0x2a8406, + 0x2c47c9, + 0x2394c6, + 0x248547, + 0x2d9045, + 0x203203, + 0x252085, + 0x298007, + 0x327706, + 0x3a25c9, + 0x30bf46, + 0x285846, + 0x205149, + 0x285009, + 0x29f347, + 0x322b08, + 0x28dc89, + 0x281808, + 0x31ce86, + 0x2cc985, + 0x30b24a, + 0x2858c6, + 0x380c06, + 0x2a1685, + 0x3843c8, + 0x2109c7, + 0x22f98a, + 0x249406, + 0x2f9a85, + 0x330e86, + 0x263ec7, + 0x330ac7, + 0x2ef245, + 0x2bdb45, + 0x29f6c6, + 0x2ad006, + 0x383a06, + 0x333b84, + 0x2840c9, + 0x289d06, + 0x35104a, + 0x21a588, + 0x35e248, + 0x3411ca, + 0x3a3505, + 0x29b4c5, + 0x385b88, + 0x2c9448, + 0x36d747, + 0x211206, + 0x312e08, + 0x2e4947, + 0x2837c8, + 0x36a5c6, + 0x286148, + 0x2b3406, + 0x23e507, + 0x297706, + 0x2c0406, + 0x233bca, + 0x392a46, + 0x2cc989, + 0x2ae7c6, + 0x2d224a, + 0x331b89, + 0x2f3a06, + 0x37ac04, + 0x31a6cd, + 0x2890c7, + 0x3157c6, + 0x2b9c85, + 0x3a0505, + 0x31abc6, + 0x274209, + 0x2b1c47, + 0x27d406, + 0x2cd2c6, + 0x2886c9, + 0x2bf4c4, + 0x22c784, + 0x2073c8, + 0x256686, + 0x273d88, + 0x2373c8, + 0x282fc7, + 0x200849, + 0x383c07, + 0x2ae38a, + 0x236d8f, + 0x2463ca, + 0x225e05, + 0x27c585, + 0x21ac05, + 0x2d2887, + 0x20e243, + 0x322d08, + 0x2f7206, + 0x2f7309, + 0x2b0106, + 0x2c3107, + 0x296a89, + 0x3824c8, + 0x2a1747, + 0x3015c3, + 0x338345, + 0x20e1c5, + 0x3339cb, + 0x26b544, + 0x2d5f04, + 0x27af06, + 0x301947, + 0x397d8a, + 0x246c47, + 0x239747, + 0x280385, + 0x2043c5, + 0x2181c9, + 0x2c0406, + 0x246acd, + 0x359c85, + 0x302803, + 0x2102c3, + 0x30c385, + 0x352545, + 0x327b88, + 0x27de47, + 0x22c506, + 0x29cf86, + 0x229cc5, + 0x231dc7, + 0x207b47, + 0x203087, + 0x2c974a, + 0x24e448, + 0x333b84, + 0x383fc7, + 0x27f347, + 0x332046, + 0x269307, + 0x2b2288, + 0x361d08, + 0x26fd46, + 0x3450c8, + 0x239544, + 0x33f686, + 0x39aa46, + 0x375986, + 0x30cd86, + 0x22ef84, + 0x327e86, + 0x2b8c06, + 0x295b86, + 0x233bc6, + 0x210186, + 0x2aeec6, + 0x22c408, + 0x320508, + 0x2ca248, + 0x266748, + 0x385b06, + 0x213585, + 0x27cb06, + 0x2ac645, + 0x38a187, + 0x231605, + 0x215a43, + 0x207645, + 0x22cd44, + 0x2102c5, + 0x21d8c3, + 0x2fd4c7, + 0x319c88, + 0x3051c6, + 0x2d600d, + 0x27c546, + 0x295045, + 0x2bc283, + 0x2b50c9, + 0x2bf646, + 0x295646, + 0x29ec04, + 0x246347, + 0x233246, + 0x384205, + 0x233b83, + 0x203f04, + 0x27f506, + 0x2b0944, + 0x30eb08, + 0x396f89, + 0x32a849, + 0x29ea0a, + 0x310d8d, + 0x32fe07, + 0x380a86, + 0x2124c4, + 0x215009, + 0x2877c8, + 0x288cc6, + 0x267d06, + 0x269307, + 0x2c2806, + 0x225546, + 0x3a3606, + 0x313d0a, + 0x21f7c8, + 0x33aa05, + 0x282d09, + 0x283cca, + 0x2d6388, + 0x29abc8, + 0x2955c8, + 0x207f4c, + 0x2e8945, + 0x29d208, + 0x30a1c6, + 0x2d5646, + 0x379787, + 0x246b45, + 0x285785, + 0x32a709, + 0x214c87, + 0x2b2745, + 0x229f87, + 0x2102c3, + 0x2beb45, + 0x3aa1c8, + 0x2d4047, + 0x29aa89, + 0x2d9545, + 0x3074c4, + 0x2a0288, + 0x20e747, + 0x2a1908, + 0x34cdc8, + 0x35e9c5, + 0x23c806, + 0x252586, + 0x2e5e89, + 0x313687, + 0x2aca46, + 0x20b247, + 0x215403, + 0x258804, + 0x29c8c5, + 0x2589c4, + 0x360104, + 0x283587, + 0x209507, + 0x22f744, + 0x29a8d0, + 0x326fc7, + 0x2043c5, + 0x2e95cc, + 0x2b6084, + 0x2c6588, + 0x23e409, + 0x302086, + 0x33f488, + 0x240544, + 0x240548, + 0x384946, + 0x32d148, + 0x29c5c6, + 0x2c84cb, + 0x204a85, + 0x2c4308, + 0x21a084, + 0x284c8a, + 0x29aa89, + 0x2e0286, + 0x2d8b48, + 0x257a45, + 0x2fdac4, + 0x2c6486, + 0x202f48, + 0x283308, + 0x349546, + 0x37ff84, + 0x30b1c6, + 0x383c87, + 0x27bb47, + 0x26930f, + 0x208607, + 0x2f3ac7, + 0x2d5505, + 0x2efcc5, + 0x29f009, + 0x272346, + 0x281f05, + 0x285307, + 0x2d8e08, + 0x295c85, + 0x297706, + 0x21a3c8, + 0x2067ca, + 0x215448, + 0x3acd07, + 0x2371c6, + 0x282cc6, + 0x20e003, + 0x20fa43, + 0x283e89, + 0x28db09, + 0x2c6386, + 0x2d9545, + 0x2a7008, + 0x2d8b48, + 0x2ba5c8, + 0x3a368b, + 0x2d6247, + 0x2ff489, + 0x269588, + 0x33c444, + 0x2c48c8, + 0x28c489, + 0x2acd45, + 0x2d2787, + 0x2f7805, + 0x283208, + 0x28ef0b, + 0x293a90, + 0x2a6c45, + 0x219fcc, + 0x22c6c5, + 0x207203, + 0x2a7d46, + 0x2b7204, + 0x3397c6, + 0x29b587, + 0x215444, + 0x2422c8, + 0x322bcd, + 0x2d8a05, + 0x298f84, + 0x218404, + 0x282789, + 0x2a4e08, + 0x30bdc7, + 0x3849c8, + 0x284188, + 0x27d705, + 0x342607, + 0x27d687, + 0x2e2f87, + 0x2bdb49, + 0x2330c9, + 0x23fc46, + 0x2b3246, + 0x269546, + 0x26c105, + 0x3b0044, + 0x201b06, + 0x203c86, + 0x27d748, + 0x263b8b, + 0x26b987, + 0x2124c4, + 0x315c46, + 0x207047, + 0x2aeac5, + 0x316dc5, + 0x20f484, + 0x233046, + 0x201b88, + 0x215009, + 0x248446, + 0x287148, + 0x3842c6, + 0x332908, + 0x3ae14c, + 0x27d5c6, + 0x294d0d, + 0x29518b, + 0x248605, + 0x207c87, + 0x2395c6, + 0x330988, + 0x23fcc9, + 0x2e5ac8, + 0x2043c5, + 0x2f0807, + 0x281908, + 0x366909, + 0x23c0c6, + 0x24834a, + 0x330708, + 0x2e590b, + 0x2c6dcc, + 0x240648, + 0x27ec46, + 0x342008, + 0x208747, + 0x233349, + 0x29148d, + 0x29ba46, + 0x3a6cc8, + 0x3203c9, + 0x2b5ac8, + 0x286248, + 0x2b94cc, + 0x2ba7c7, + 0x2bb3c7, + 0x2bd985, + 0x2ee287, + 0x2d8cc8, + 0x2c6506, + 0x256acc, + 0x2e6808, + 0x2c5808, + 0x266a06, + 0x20df47, + 0x23fe44, + 0x266748, + 0x2dc68c, + 0x21c68c, + 0x225e85, + 0x393e07, + 0x37ff06, + 0x20dec6, + 0x29b048, + 0x3a4984, + 0x32c64b, + 0x2263cb, + 0x2371c6, + 0x322a47, + 0x328b05, + 0x273145, + 0x32c786, + 0x257a05, + 0x26b505, + 0x379a47, + 0x27b509, + 0x2344c4, + 0x3621c5, + 0x2d71c5, + 0x25b748, + 0x376005, + 0x2a7849, + 0x370587, + 0x37058b, + 0x2d1546, + 0x22c149, + 0x24f948, + 0x280d45, + 0x2e3088, + 0x233108, + 0x211807, + 0x282b87, + 0x283609, + 0x320447, + 0x38cf09, + 0x2aa34c, + 0x36aa08, + 0x2b5ec9, + 0x2b8247, + 0x284249, + 0x209647, + 0x2c6ec8, + 0x25ba85, + 0x33f606, + 0x2b9cc8, + 0x2d6a88, + 0x283b89, + 0x26b547, + 0x273205, + 0x216c49, + 0x28e046, + 0x28e7c4, + 0x2e5786, + 0x2450c8, + 0x248e07, + 0x263d88, + 0x345189, + 0x364f87, + 0x29c346, + 0x207d44, + 0x2076c9, + 0x342488, + 0x2668c7, + 0x323e06, + 0x20e286, + 0x380b84, + 0x326186, + 0x210243, + 0x2cf889, + 0x204a46, + 0x2a4485, + 0x29cf86, + 0x2a1a45, + 0x281d88, + 0x240387, + 0x35b546, + 0x3414c6, + 0x35e248, + 0x29f187, + 0x29ba85, + 0x29d488, + 0x38cc48, + 0x330708, + 0x22c585, + 0x33f686, + 0x32a609, + 0x252404, + 0x373acb, + 0x22524b, + 0x33a909, + 0x2102c3, + 0x2546c5, + 0x20ff46, + 0x267608, + 0x236d04, + 0x3051c6, + 0x2c9889, + 0x2c6845, + 0x379986, + 0x20e746, + 0x211184, + 0x2a064a, + 0x2a43c8, + 0x2d6a86, + 0x329185, + 0x20d707, + 0x378e07, + 0x23c804, + 0x225487, + 0x2315c4, + 0x2315c6, + 0x21a503, + 0x2bdb45, + 0x36fb05, + 0x20eac8, + 0x258905, + 0x27d309, + 0x266587, + 0x26658b, + 0x2a12cc, + 0x2a1eca, + 0x2bf307, + 0x202003, + 0x2e6408, + 0x22c745, + 0x295d05, + 0x338404, + 0x2c6dc6, + 0x23e406, + 0x3261c7, + 0x39998b, + 0x22ef84, + 0x382744, + 0x26fec4, + 0x2c4046, + 0x215444, + 0x211008, + 0x338205, + 0x29d545, + 0x2ba507, + 0x207d89, + 0x352545, + 0x31abca, + 0x2d8f49, + 0x2a104a, + 0x313e49, + 0x39cc04, + 0x2cd385, + 0x2c2908, + 0x2fc70b, + 0x2fb3c5, + 0x237546, + 0x214904, + 0x27d846, + 0x364e09, + 0x315d07, + 0x30c108, + 0x311106, + 0x383c07, + 0x283308, + 0x38fbc6, + 0x244a44, + 0x3636c7, + 0x34a905, + 0x350a47, + 0x201c04, + 0x239546, + 0x21fa48, + 0x295348, + 0x2ee007, + 0x378288, + 0x2b34c5, + 0x210104, + 0x3410c8, + 0x3321c4, + 0x211805, + 0x2efe04, + 0x2e4a47, + 0x289dc7, + 0x284388, + 0x2a1a86, + 0x258885, + 0x27d108, + 0x215648, + 0x29e949, + 0x225546, + 0x22fa08, + 0x284b0a, + 0x2aeb48, + 0x2d8045, + 0x27cd06, + 0x2740c8, + 0x2f08ca, + 0x24fb47, + 0x287bc5, + 0x294288, + 0x2ad9c4, + 0x384446, + 0x2bbb48, + 0x210186, + 0x264308, + 0x252247, + 0x205b86, + 0x37ac04, + 0x37e907, + 0x2fd904, + 0x364dc7, + 0x33924d, + 0x288b05, + 0x2d3e4b, + 0x29c6c6, + 0x24d788, + 0x242284, + 0x278906, + 0x27f506, + 0x342347, + 0x2949cd, + 0x2ab007, + 0x302748, + 0x24c9c5, + 0x288248, + 0x2be186, + 0x2b3548, + 0x217086, + 0x3448c7, + 0x345349, + 0x33ff07, + 0x288f88, + 0x276005, + 0x21f108, + 0x20de05, + 0x242b45, + 0x35a545, + 0x226103, + 0x285684, + 0x282d05, + 0x271249, + 0x2ffa06, + 0x2b2388, + 0x24bc05, + 0x32e087, + 0x24ba0a, + 0x3798c9, + 0x2a830a, + 0x2ca2c8, + 0x229dcc, + 0x28538d, + 0x334603, + 0x264208, + 0x203ec5, + 0x206586, + 0x382346, + 0x2d7b45, + 0x20b349, + 0x264745, + 0x27d108, + 0x255ac6, + 0x33cac6, + 0x2a0149, + 0x38f3c7, + 0x28f1c6, + 0x24b988, + 0x375888, + 0x2d0547, + 0x32d2ce, + 0x2be3c5, + 0x366805, + 0x210088, + 0x3978c7, + 0x20ca82, + 0x2b9044, + 0x3396ca, + 0x266988, + 0x207146, + 0x296bc8, + 0x252586, + 0x323708, + 0x2aca48, + 0x242b04, + 0x333805, + 0x687e44, + 0x687e44, + 0x687e44, + 0x204b03, + 0x20e106, + 0x27d5c6, + 0x29bd0c, + 0x205243, + 0x283cc6, + 0x21a4c4, + 0x2bf5c8, + 0x2c96c5, + 0x3397c6, + 0x2b5808, + 0x2cb1c6, + 0x35b4c6, + 0x327988, + 0x29c947, + 0x32ce49, + 0x306f8a, + 0x264944, + 0x231605, + 0x2a91c5, + 0x214e06, + 0x32fe46, + 0x2a7406, + 0x2eeb86, + 0x32cf84, + 0x32cf8b, + 0x2313c4, + 0x20d785, + 0x2ab905, + 0x283086, + 0x3b0588, + 0x285247, + 0x30bec4, + 0x259b83, + 0x2ad4c5, + 0x2e5647, + 0x2a2849, + 0x28514b, + 0x3261c7, + 0x20e9c7, + 0x2b5708, + 0x32e1c7, + 0x2a2a86, + 0x244448, + 0x2a584b, + 0x399606, + 0x217549, + 0x2a59c5, + 0x3015c3, + 0x379986, + 0x252148, + 0x214ec3, + 0x21cf03, + 0x283306, + 0x252586, + 0x38c60a, + 0x27ec85, + 0x27f34b, + 0x29cecb, + 0x2417c3, + 0x21fe03, + 0x2ae304, + 0x344d07, + 0x240644, + 0x207f44, + 0x30a044, + 0x2aee48, + 0x3290c8, + 0x35ad89, + 0x38e788, + 0x271407, + 0x233bc6, + 0x2b1fcf, + 0x2be506, + 0x2c9644, + 0x328f0a, + 0x2e5547, + 0x201846, + 0x28e809, + 0x35ad05, + 0x20ec05, + 0x35ae46, + 0x21f243, + 0x2ada09, + 0x21f946, + 0x344f49, + 0x397d86, + 0x2bdb45, + 0x226285, + 0x208603, + 0x344e48, + 0x3a5ac7, + 0x2f7204, + 0x2bf448, + 0x2c0184, + 0x2c5686, + 0x2a7d46, + 0x23ec06, + 0x2c41c9, + 0x295c85, + 0x2c0406, + 0x2697c9, + 0x3ad4c6, + 0x2aeec6, + 0x3895c6, + 0x215105, + 0x2efe06, + 0x3448c4, + 0x25ba85, + 0x2b9cc4, + 0x309f46, + 0x359c44, + 0x202c43, + 0x287885, + 0x232e08, + 0x22b547, + 0x2b3dc9, + 0x287ac8, + 0x296391, + 0x20e7ca, + 0x237107, + 0x2bc046, + 0x21a4c4, + 0x2b9dc8, + 0x22f488, + 0x29654a, + 0x2a760d, + 0x237446, + 0x327a86, + 0x37e9c6, + 0x2ef0c7, + 0x302805, + 0x261107, + 0x2bf505, + 0x3706c4, + 0x2a5286, + 0x326007, + 0x2ad70d, + 0x274007, + 0x270188, + 0x27d409, + 0x27cc06, + 0x23c045, + 0x21d904, + 0x2451c6, + 0x23c706, + 0x266b06, + 0x299108, + 0x215d03, + 0x210603, + 0x323ac5, + 0x376b86, + 0x2aca05, + 0x311308, + 0x29b74a, + 0x2ce804, + 0x2bf5c8, + 0x2955c8, + 0x282ec7, + 0x24bcc9, + 0x2b5408, + 0x215087, + 0x269ec6, + 0x21018a, + 0x245248, + 0x2c6c09, + 0x2a4ec8, + 0x221649, + 0x2e5bc7, + 0x349945, + 0x361f86, + 0x2c6388, + 0x24d908, + 0x28eb48, + 0x21acc8, + 0x20d785, + 0x200884, + 0x3a57c8, + 0x201944, + 0x313c44, + 0x2bdb45, + 0x290487, + 0x207b49, + 0x342147, + 0x2051c5, + 0x27b106, + 0x33f0c6, + 0x206944, + 0x2a0486, + 0x383f44, + 0x288146, + 0x3a4a46, + 0x219206, + 0x2043c5, + 0x3111c7, + 0x202003, + 0x3670c9, + 0x35e048, + 0x214f04, + 0x214f0d, + 0x295448, + 0x2f3f48, + 0x2c6b86, + 0x345449, + 0x3798c9, + 0x364b05, + 0x29b84a, + 0x28224a, + 0x289f8c, + 0x28a106, + 0x27b9c6, + 0x2bea86, + 0x26db09, + 0x2067c6, + 0x261146, + 0x264806, + 0x266748, + 0x215446, + 0x2c450b, + 0x290605, + 0x29d545, + 0x27bc45, + 0x202106, + 0x210143, + 0x23eb86, + 0x273f87, + 0x2b9c85, + 0x243645, + 0x3a0505, + 0x335f46, + 0x31abc4, + 0x372a46, + 0x299489, + 0x201f8c, + 0x370408, + 0x202ec4, + 0x2efbc6, + 0x29c7c6, + 0x252148, + 0x2d8b48, + 0x201e89, + 0x20d707, + 0x2563c9, + 0x24cf86, + 0x22cf44, + 0x20f184, + 0x288bc4, + 0x283308, + 0x20798a, + 0x3524c6, + 0x356387, + 0x236087, + 0x22c245, + 0x2a9184, + 0x28c446, + 0x302846, + 0x233303, + 0x35de87, + 0x34ccc8, + 0x364c4a, + 0x2cbb88, + 0x2ce688, + 0x359c85, + 0x248705, + 0x26ba85, + 0x22c606, + 0x37ed86, + 0x209445, + 0x2cfac9, + 0x2a8f8c, + 0x26bb47, + 0x2965c8, + 0x257d45, + 0x687e44, + 0x247884, + 0x2d4184, + 0x2c1606, + 0x29da4e, + 0x20ec87, + 0x2edfc5, + 0x25238c, + 0x2c0047, + 0x325f87, + 0x35bf49, + 0x21b949, + 0x287bc5, + 0x35e048, + 0x32a609, + 0x2f2ec5, + 0x2b9bc8, + 0x2c4ac6, + 0x341346, + 0x331b84, + 0x2a46c8, + 0x249e83, + 0x342c84, + 0x2ad545, + 0x335407, + 0x20f4c5, + 0x2849c9, + 0x28d60d, + 0x2a6246, + 0x32c004, + 0x211188, + 0x27b34a, + 0x20cb87, + 0x239d85, + 0x206d03, + 0x29d08e, + 0x25258c, + 0x2fb707, + 0x29dc07, + 0x201c43, + 0x206805, + 0x2d4185, + 0x296f88, + 0x2940c9, + 0x202dc6, + 0x240644, + 0x237046, + 0x37564b, + 0x3a0b8c, + 0x341ec7, + 0x2c9385, + 0x38cb48, + 0x2d0305, + 0x328f07, + 0x23bf07, + 0x249e85, + 0x210143, + 0x2af184, + 0x20f945, + 0x2ad0c5, + 0x2ad0c6, + 0x2927c8, + 0x326007, + 0x382646, + 0x206486, + 0x35a486, + 0x263a09, + 0x342707, + 0x202c46, + 0x3a0d06, + 0x249f46, + 0x2a6f45, + 0x20aa06, + 0x399385, + 0x376088, + 0x2936cb, + 0x28c246, + 0x2360c4, + 0x2f0689, + 0x266584, + 0x2c4a48, + 0x2961c7, + 0x286144, + 0x2b4708, + 0x2bad84, + 0x2a6f84, + 0x2889c5, + 0x2d8a46, + 0x2aed87, + 0x2643c3, + 0x29c405, + 0x2f7784, + 0x366846, + 0x364b88, + 0x327885, + 0x28ff09, + 0x216e45, + 0x2e2b48, + 0x263747, + 0x38a2c8, + 0x2b3c07, + 0x2f3b89, + 0x327d06, + 0x36bd06, + 0x264804, + 0x269e05, + 0x2f5e4c, + 0x27bc47, + 0x27c447, + 0x235f48, + 0x2a6246, + 0x273ec4, + 0x2ead84, + 0x283489, + 0x2beb86, + 0x218247, + 0x30cd04, + 0x2ffb06, + 0x325b85, + 0x2a15c7, + 0x2c4486, + 0x248209, + 0x282087, + 0x269307, + 0x29ffc6, + 0x310c85, + 0x280a08, + 0x21f7c8, + 0x23d906, + 0x3278c5, + 0x261c86, + 0x205d03, + 0x296e09, + 0x2a718e, + 0x2b2a08, + 0x2c0288, + 0x23d70b, + 0x290146, + 0x321ac4, + 0x284f84, + 0x2a728a, + 0x219ec7, + 0x202d05, + 0x217549, + 0x2b8cc5, + 0x313c87, + 0x301e84, + 0x397107, + 0x2372c8, + 0x2d1bc6, + 0x3a6e49, + 0x2b550a, + 0x219e46, + 0x294f86, + 0x2ab885, + 0x37cb05, + 0x357f47, + 0x2456c8, + 0x325ac8, + 0x242b06, + 0x226305, + 0x32fbce, + 0x333b84, + 0x23d885, + 0x27aa89, + 0x272148, + 0x3acc46, + 0x298d8c, + 0x29b350, + 0x29d68f, + 0x29ef08, + 0x2bf307, + 0x2043c5, + 0x282d05, + 0x2aec09, + 0x294489, + 0x30b2c6, + 0x2fb447, + 0x393d85, + 0x36d749, + 0x3320c6, + 0x20660d, + 0x288a89, + 0x207f44, + 0x2b2788, + 0x3a5889, + 0x352686, + 0x27b205, + 0x36bd06, + 0x30bfc9, + 0x2381c8, + 0x213585, + 0x284c04, + 0x298f4b, + 0x352545, + 0x267686, + 0x2856c6, + 0x26b006, + 0x3a388b, + 0x290009, + 0x209785, + 0x38a087, + 0x20e746, + 0x339506, + 0x284888, + 0x269fc9, + 0x26ff4c, + 0x2e5448, + 0x352786, + 0x349543, + 0x2d2986, + 0x2829c5, + 0x27f688, + 0x225d06, + 0x2a1808, + 0x246cc5, + 0x215185, + 0x2a0848, + 0x378f47, + 0x382287, + 0x3261c7, + 0x33f488, + 0x28e9c8, + 0x24de06, + 0x309d87, + 0x2586c7, + 0x28288a, + 0x24ce83, + 0x202106, + 0x203005, + 0x324244, + 0x27d409, + 0x2f3b04, + 0x22b5c4, + 0x29c644, + 0x29dc0b, + 0x3a5a07, + 0x32fe05, + 0x293548, + 0x27b106, + 0x27b108, + 0x27ebc6, + 0x28adc5, + 0x28b545, + 0x28d046, + 0x28e488, + 0x28e748, + 0x27d5c6, + 0x29338f, + 0x2968d0, + 0x3a26c5, + 0x202003, + 0x24c905, + 0x2ff3c8, + 0x294389, + 0x330708, + 0x263888, + 0x380648, + 0x3a5ac7, + 0x27adc9, + 0x2a1a08, + 0x2b0684, + 0x29c4c8, + 0x25b809, + 0x30b8c7, + 0x298144, + 0x342208, + 0x310f8a, + 0x2c3ec6, + 0x237446, + 0x225409, + 0x29b587, + 0x2c4e48, + 0x209fc8, + 0x30cb88, + 0x355ec5, + 0x37da85, + 0x29d545, + 0x2d4145, + 0x2f1807, + 0x210145, + 0x2b9c85, + 0x212ec6, + 0x330647, + 0x2fc647, + 0x311286, + 0x2ca805, + 0x267686, + 0x240405, + 0x2bfec8, + 0x2ff984, + 0x3ad546, + 0x2e7dc4, + 0x2fdac8, + 0x3ad64a, + 0x27de4c, + 0x399b85, + 0x2ef186, + 0x270106, + 0x34c5c6, + 0x2ff5c4, + 0x325e45, + 0x27ea07, + 0x29b609, + 0x2a2947, + 0x687e44, + 0x687e44, + 0x30bd45, + 0x229144, + 0x29874a, + 0x27af86, + 0x2e5884, + 0x2017c5, + 0x2eb445, + 0x302744, + 0x285307, + 0x216dc7, + 0x2c4048, + 0x317048, + 0x213589, + 0x3321c8, + 0x29890b, + 0x214e04, + 0x361905, + 0x281f85, + 0x326149, + 0x269fc9, + 0x2f0588, + 0x2313c8, + 0x283084, + 0x29c805, + 0x207503, + 0x214dc5, + 0x2c0486, + 0x293f0c, + 0x21f846, + 0x240446, + 0x2940c5, + 0x335fc8, + 0x3a0e06, + 0x2bc1c6, + 0x237446, + 0x22d6cc, + 0x266cc4, + 0x35a5ca, + 0x3ace08, + 0x293d47, + 0x244946, + 0x202e87, + 0x2e0845, + 0x323e06, + 0x354906, + 0x382147, + 0x22b604, + 0x2e4b45, + 0x27aa84, + 0x370747, + 0x27acc8, + 0x27b84a, + 0x281787, + 0x23da87, + 0x2bf287, + 0x2d0449, + 0x293f0a, + 0x22cf03, + 0x22b505, + 0x219243, + 0x30a089, + 0x2f1108, + 0x2d5507, + 0x330809, + 0x21f8c6, + 0x2b0208, + 0x2fd445, + 0x21574a, + 0x326dc9, + 0x26fc09, + 0x379787, + 0x22f589, + 0x219108, + 0x2eff86, + 0x2ef348, + 0x215e47, + 0x320447, + 0x2d8f47, + 0x2d5388, + 0x2efa46, + 0x310d45, + 0x27ea07, + 0x294a88, + 0x35a404, + 0x350f04, + 0x28f0c7, + 0x2acdc7, + 0x32a48a, + 0x2eff06, + 0x2fb58a, + 0x2b8f87, + 0x333947, + 0x242c04, + 0x38cfc4, + 0x227a06, + 0x264d04, + 0x264d0c, + 0x3b1f45, + 0x21ab09, + 0x2e2cc4, + 0x302805, + 0x27b2c8, + 0x28e805, + 0x31abc6, + 0x2115c4, + 0x2a0a8a, + 0x2b0846, + 0x29574a, + 0x31a987, + 0x263ec5, + 0x21f245, + 0x22c28a, + 0x2a0585, + 0x29ea06, + 0x201944, + 0x2ae486, + 0x358005, + 0x225dc6, + 0x2ee00c, + 0x2c4fca, + 0x269ec4, + 0x233bc6, + 0x29b587, + 0x2c8984, + 0x266748, + 0x38e606, + 0x32fa49, + 0x2c5ec9, + 0x36ab09, + 0x373c86, + 0x215f46, + 0x2ef487, + 0x2cfa08, + 0x215d49, + 0x3a5a07, + 0x2b3346, + 0x383c87, + 0x37e885, + 0x333b84, + 0x2ef047, + 0x2f7805, + 0x288905, + 0x300687, + 0x249d48, + 0x38cac6, + 0x2959cd, + 0x29718f, + 0x29cecd, + 0x205204, + 0x232f06, + 0x2cbec8, + 0x2647c5, + 0x282a48, + 0x2116ca, + 0x207f44, + 0x3a7006, + 0x39f8c7, + 0x22ef87, + 0x29ca09, + 0x2ef305, + 0x302744, + 0x33374a, + 0x2b4fc9, + 0x22f687, + 0x26cbc6, + 0x352686, + 0x29c746, + 0x363786, + 0x2cb84f, + 0x2cbd89, + 0x215446, + 0x22f386, + 0x27a409, + 0x309e87, + 0x21d943, + 0x22d846, + 0x20fa43, + 0x2d7a08, + 0x383ac7, + 0x29f109, + 0x2a7bc8, + 0x3823c8, + 0x26b686, + 0x23c549, + 0x2c7a85, + 0x244944, + 0x349a07, + 0x26db85, + 0x205204, + 0x32fec8, + 0x21a184, + 0x305647, + 0x319c06, + 0x29f785, + 0x2a4ec8, + 0x35254b, + 0x35e547, + 0x22c506, + 0x2be584, + 0x321a46, + 0x2bdb45, + 0x2f7805, + 0x280789, + 0x284f09, + 0x2a2a04, + 0x3204c5, + 0x233c05, + 0x2155c6, + 0x35e148, + 0x2b7586, + 0x34cb0b, + 0x301f0a, + 0x2fda05, + 0x28b5c6, + 0x2f6f05, + 0x209845, + 0x29ad47, + 0x2073c8, + 0x2563c4, + 0x364a06, + 0x28e7c6, + 0x2192c7, + 0x301584, + 0x27f506, + 0x300e05, + 0x300e09, + 0x216144, + 0x2a9309, + 0x27d5c6, + 0x2ba888, + 0x233c05, + 0x236185, + 0x225dc6, + 0x26fe49, + 0x21b949, + 0x2404c6, + 0x272248, + 0x252488, + 0x2f6ec4, + 0x363c84, + 0x363c88, + 0x3158c8, + 0x2564c9, + 0x2c0406, + 0x237446, + 0x312ccd, + 0x3051c6, + 0x3ae009, + 0x2022c5, + 0x35ae46, + 0x261248, + 0x30fc45, + 0x258704, + 0x2bdb45, + 0x284588, + 0x298509, + 0x27ab44, + 0x239546, + 0x2e5d0a, + 0x2d6388, + 0x32a609, + 0x35b64a, + 0x330786, + 0x297348, + 0x328cc5, + 0x326c48, + 0x2b3d05, + 0x21f789, + 0x368809, + 0x202e02, + 0x2a59c5, + 0x272e86, + 0x27d507, + 0x324245, + 0x2f9986, + 0x30fd08, + 0x2a6246, + 0x2c27c9, + 0x27c546, + 0x284708, + 0x2a8645, + 0x24ae86, + 0x3449c8, + 0x283308, + 0x3a4ac8, + 0x2febc8, + 0x20aa04, + 0x22a783, + 0x2c2a04, + 0x236fc6, + 0x37e8c4, + 0x2c01c7, + 0x2bc0c9, + 0x2bdd85, + 0x209fc6, + 0x22d846, + 0x29260b, + 0x2fd946, + 0x316406, + 0x2c2f88, + 0x243586, + 0x263cc3, + 0x20a383, + 0x333b84, + 0x22f905, + 0x384107, + 0x27acc8, + 0x27accf, + 0x27e90b, + 0x35df48, + 0x2395c6, + 0x35e24e, + 0x225dc3, + 0x2b1d84, + 0x2fd8c5, + 0x33d746, + 0x28c54b, + 0x290546, + 0x21a449, + 0x29f785, + 0x38b708, + 0x212088, + 0x21b80c, + 0x29dc46, + 0x214e06, + 0x2d9545, + 0x288d48, + 0x27de45, + 0x33c448, + 0x29d30a, + 0x361e09, + 0x687e44, + 0x2f606a82, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x327883, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x24c083, + 0x204703, + 0x223503, + 0x223504, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x2c8144, + 0x250cc3, + 0x324507, + 0x220ec3, + 0x2020c3, + 0x255bc8, + 0x204703, + 0x2d2d8b, + 0x2e0f83, + 0x25b1c6, + 0x2012c2, + 0x387d0b, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x204703, + 0x29dfc3, + 0x205a03, + 0x200882, + 0x77a48, + 0x343145, + 0x2d4e88, + 0x2da008, + 0x206a82, + 0x330f85, + 0x357bc7, + 0x200202, + 0x2424c7, + 0x20f582, + 0x23d4c7, + 0x265249, + 0x3167c8, + 0x30ca09, + 0x3345c2, + 0x26ab07, + 0x240244, + 0x357c87, + 0x301e07, + 0x244d02, + 0x220ec3, + 0x203642, + 0x202b42, + 0x200fc2, + 0x200ac2, + 0x203942, + 0x203682, + 0x2a81c5, + 0x2477c5, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x481, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x24c083, + 0x204703, + 0x20b743, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0xa9c2, + 0x77a48, + 0x45684, + 0xd0705, + 0x200882, + 0x2bb844, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x37f383, + 0x2a8e05, + 0x202243, + 0x39a883, + 0x24c083, + 0x20f543, + 0x204703, + 0x20b803, + 0x223583, + 0x2232c3, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x206a82, + 0x204703, + 0x77a48, + 0x250cc3, + 0x77a48, + 0x2cd683, + 0x22bf83, + 0x22ff84, + 0x231b03, + 0x250cc3, + 0x20b542, + 0x220ec3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x20b542, + 0x232003, + 0x24c083, + 0x204703, + 0x2d9f83, + 0x20b803, + 0x200882, + 0x206a82, + 0x250cc3, + 0x24c083, + 0x204703, + 0x25b1c5, + 0xad186, + 0x223504, + 0x2012c2, + 0x77a48, + 0x200882, + 0x20048, + 0x206a82, + 0xf206, + 0x143f44, + 0x10844b, + 0x18986, + 0x142b87, + 0x231b03, + 0x250cc3, + 0x159b85, + 0x14d4c4, + 0x24dd43, + 0x4ce47, + 0xcd204, + 0x24c083, + 0x14c104, + 0x204703, + 0x2e1c44, + 0x10c888, + 0x122706, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x2020c3, + 0x204703, + 0x2e0f83, + 0x2012c2, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c3, + 0x211004, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x2c8144, + 0x250cc3, + 0x24c083, + 0x204703, + 0x25b1c6, + 0x231b03, + 0x250cc3, + 0x178d03, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x142b87, + 0x77a48, + 0x250cc3, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x3822bf83, + 0x231b03, + 0x24c083, + 0x204703, + 0x77a48, + 0x200882, + 0x206a82, + 0x22bf83, + 0x250cc3, + 0x24c083, + 0x200fc2, + 0x204703, + 0x30abc7, + 0x2e330b, + 0x208883, + 0x23a8c8, + 0x2cf787, + 0x2b7b46, + 0x2bc885, + 0x2f9509, + 0x25af48, + 0x31b349, + 0x31b350, + 0x35d24b, + 0x2ec7c9, + 0x206103, + 0x2130c9, + 0x230a86, + 0x230a8c, + 0x31b548, + 0x3ad308, + 0x279709, + 0x29e40e, + 0x37b34b, + 0x237bcc, + 0x201e03, + 0x268d0c, + 0x208349, + 0x375287, + 0x231a4c, + 0x39c18a, + 0x247204, + 0x3a4d8d, + 0x268bc8, + 0x3a52cd, + 0x26e086, + 0x290ccb, + 0x375b49, + 0x3162c7, + 0x31eb06, + 0x321c09, + 0x34b9ca, + 0x304f48, + 0x2e0b84, + 0x362087, + 0x278a07, + 0x30cf04, + 0x228dc4, + 0x262f09, + 0x2ce4c9, + 0x323148, + 0x212905, + 0x392845, + 0x20d546, + 0x3a4c49, + 0x21194d, + 0x237648, + 0x20d447, + 0x2bc908, + 0x32cc06, + 0x3a2444, + 0x37dd45, + 0x204946, + 0x205884, + 0x208247, + 0x20a60a, + 0x214bc4, + 0x219d86, + 0x21a789, + 0x21a78f, + 0x21b50d, + 0x21ca86, + 0x21fc50, + 0x220046, + 0x220787, + 0x221047, + 0x22104f, + 0x221889, + 0x2256c6, + 0x227e87, + 0x227e88, + 0x228249, + 0x290248, + 0x2d7547, + 0x20ce83, + 0x386a86, + 0x2e4c88, + 0x29e6ca, + 0x214689, + 0x212383, + 0x357ac6, + 0x36484a, + 0x2f7d07, + 0x3750ca, + 0x2028ce, + 0x2219c6, + 0x2a5bc7, + 0x217306, + 0x208406, + 0x37d88b, + 0x3038ca, + 0x22704d, + 0x216007, + 0x264988, + 0x264989, + 0x26498f, + 0x20e34c, + 0x27f909, + 0x3af74e, + 0x32460a, + 0x329546, + 0x37a686, + 0x306ccc, + 0x3108cc, + 0x32adc8, + 0x33fe07, + 0x2b0585, + 0x206a84, + 0x345b4e, + 0x34bc44, + 0x22adc7, + 0x265e4a, + 0x382ad4, + 0x384e4f, + 0x221208, + 0x386948, + 0x36d10d, + 0x36d10e, + 0x390509, + 0x22e108, + 0x22e10f, + 0x23174c, + 0x23174f, + 0x232c47, + 0x2352ca, + 0x21f50b, + 0x239c08, + 0x23aac7, + 0x25a64d, + 0x35c546, + 0x3a4f46, + 0x23ea09, + 0x250248, + 0x243048, + 0x24304e, + 0x2e3407, + 0x2aabc5, + 0x244ec5, + 0x200e84, + 0x2b7e06, + 0x323048, + 0x25ff83, + 0x2de30e, + 0x25aa08, + 0x308dcb, + 0x367487, + 0x3a4485, + 0x22f246, + 0x2a9b47, + 0x2e8448, + 0x330489, + 0x35c7c5, + 0x2878c8, + 0x214006, + 0x37e50a, + 0x345a49, + 0x231b09, + 0x231b0b, + 0x31f608, + 0x30cdc9, + 0x2129c6, + 0x35a8ca, + 0x2b898a, + 0x2354cc, + 0x35c307, + 0x291e8a, + 0x2af68b, + 0x2af699, + 0x2dd788, + 0x25b245, + 0x25a806, + 0x2dad89, + 0x316cc6, + 0x211e4a, + 0x342a06, + 0x2143c4, + 0x2c098d, + 0x24fd07, + 0x2143c9, + 0x245e85, + 0x245fc8, + 0x2467c9, + 0x246a04, + 0x247107, + 0x247108, + 0x2479c7, + 0x2687c8, + 0x24d447, + 0x23c285, + 0x25520c, + 0x2558c9, + 0x36bf0a, + 0x38f249, + 0x2131c9, + 0x27450c, + 0x259a4b, + 0x259d08, + 0x25bf88, + 0x25f344, + 0x285e08, + 0x286bc9, + 0x39c247, + 0x21a9c6, + 0x2413c7, + 0x3af509, + 0x2af2cb, + 0x325947, + 0x204787, + 0x2e2d47, + 0x3a5244, + 0x3a5245, + 0x2a6d05, + 0x337a0b, + 0x398604, + 0x317e88, + 0x2aa7ca, + 0x2140c7, + 0x34a107, + 0x28bdd2, + 0x288046, + 0x22fb86, + 0x32728e, + 0x34ae06, + 0x291308, + 0x29210f, + 0x3a5688, + 0x377c48, + 0x2b4b8a, + 0x2b4b91, + 0x2a0d0e, + 0x23adca, + 0x23adcc, + 0x22e307, + 0x22e310, + 0x203d08, + 0x2a0f05, + 0x2aa10a, + 0x2058cc, + 0x2b368d, + 0x2abe06, + 0x2abe07, + 0x2abe0c, + 0x2f338c, + 0x2d988c, + 0x28f4cb, + 0x287284, + 0x225584, + 0x371389, + 0x2d8447, + 0x32c449, + 0x2b87c9, + 0x367f07, + 0x39c006, + 0x39c009, + 0x3a6b43, + 0x2a634a, + 0x206cc7, + 0x3624cb, + 0x226eca, + 0x23d604, + 0x3564c6, + 0x281a09, + 0x20b504, + 0x3b200a, + 0x2f9b45, + 0x2b6285, + 0x2b628d, + 0x2b65ce, + 0x3146c5, + 0x3942c6, + 0x25adc7, + 0x2dc04a, + 0x2e8646, + 0x2fc484, + 0x2f5987, + 0x220d8b, + 0x32ccc7, + 0x3a34c4, + 0x374206, + 0x37420d, + 0x23918c, + 0x380406, + 0x23784a, + 0x217b06, + 0x21da08, + 0x228507, + 0x37f14a, + 0x2310c6, + 0x215f03, + 0x2613c6, + 0x201308, + 0x298b0a, + 0x26c447, + 0x26c448, + 0x2732c4, + 0x2863c7, + 0x28e0c8, + 0x2151c8, + 0x285c08, + 0x32630a, + 0x2cff85, + 0x2c76c7, + 0x23ac13, + 0x22c006, + 0x2b09c8, + 0x223ac9, + 0x242388, + 0x26b70b, + 0x2b8d88, + 0x220ec4, + 0x2a0946, + 0x3b11c6, + 0x2d8889, + 0x387747, + 0x255308, + 0x3acf86, + 0x21c444, + 0x2c4d05, + 0x2bf0c8, + 0x2bf98a, + 0x2c0608, + 0x2c5446, + 0x29920a, + 0x234548, + 0x2c8788, + 0x2c9bc8, + 0x2ca4c6, + 0x2cc0c6, + 0x31f00c, + 0x2cc590, + 0x28a505, + 0x2f9f88, + 0x2f9f90, + 0x3a5490, + 0x31b1ce, + 0x31ec8e, + 0x31ec94, + 0x31f7cf, + 0x31fb86, + 0x250751, + 0x3086d3, + 0x308b48, + 0x321585, + 0x359ec8, + 0x20f3c5, + 0x22964c, + 0x256789, + 0x22ac09, + 0x241147, + 0x214989, + 0x24ff47, + 0x2b6106, + 0x37db47, + 0x2605c5, + 0x310b83, + 0x260149, + 0x227409, + 0x378d03, + 0x3abb84, + 0x38004d, + 0x3810cf, + 0x3005c5, + 0x3188c6, + 0x20d147, + 0x303d07, + 0x289946, + 0x28994b, + 0x2a2085, + 0x257ec6, + 0x209247, + 0x273949, + 0x3358c6, + 0x210805, + 0x22400b, + 0x37f406, + 0x249885, + 0x39f588, + 0x2b5cc8, + 0x2b6b4c, + 0x2b6b50, + 0x2ca9c9, + 0x2f8587, + 0x2de9cb, + 0x2d59c6, + 0x2d740a, + 0x2d860b, + 0x2d918a, + 0x2d9406, + 0x2d9e45, + 0x2cf686, + 0x27c708, + 0x24120a, + 0x36cd9c, + 0x2e104c, + 0x2e1348, + 0x25b1c5, + 0x2e51c7, + 0x29e046, + 0x399445, + 0x21ea46, + 0x289b08, + 0x2b5247, + 0x29e308, + 0x2a5cca, + 0x321f8c, + 0x322209, + 0x20a147, + 0x20c544, + 0x245846, + 0x3777ca, + 0x2b88c5, + 0x3a2c8c, + 0x3a5088, + 0x350b48, + 0x20da4c, + 0x213c4c, + 0x2162c9, + 0x216507, + 0x2c7e0c, + 0x32f644, + 0x39080a, + 0x20b80c, + 0x274d8b, + 0x23a28b, + 0x23b346, + 0x23df07, + 0x22e547, + 0x22e54f, + 0x2f4311, + 0x3b1ad2, + 0x23eecd, + 0x23eece, + 0x23f20e, + 0x31f988, + 0x31f992, + 0x242e48, + 0x2fc287, + 0x24a88a, + 0x20fd88, + 0x34adc5, + 0x2f164a, + 0x220587, + 0x2e6e04, + 0x24ddc3, + 0x376a45, + 0x2b4e07, + 0x2fa347, + 0x2b388e, + 0x38708d, + 0x39b189, + 0x216845, + 0x2ea903, + 0x25f8c6, + 0x36ba85, + 0x309008, + 0x2eb049, + 0x25a845, + 0x25a84f, + 0x2d9c87, + 0x2f9445, + 0x271d8a, + 0x3a2986, + 0x21db89, + 0x2ec3cc, + 0x2ee449, + 0x203f46, + 0x2aa5cc, + 0x2eea06, + 0x2f19c8, + 0x2f1bc6, + 0x2dd906, + 0x24fa84, + 0x25a083, + 0x35efca, + 0x31e391, + 0x27faca, + 0x327f85, + 0x38ec47, + 0x251b47, + 0x28e1c4, + 0x28e1cb, + 0x316648, + 0x2b2886, + 0x235fc5, + 0x265904, + 0x269ac9, + 0x27a984, + 0x3041c7, + 0x2ee645, + 0x2ee647, + 0x3274c5, + 0x2a8283, + 0x2fc148, + 0x325c0a, + 0x2643c3, + 0x34318a, + 0x274386, + 0x25a5cf, + 0x358f89, + 0x2de290, + 0x2e1848, + 0x2c5909, + 0x298347, + 0x37418f, + 0x330bc4, + 0x2c81c4, + 0x21b386, + 0x275746, + 0x2ff74a, + 0x32b746, + 0x33e787, + 0x2f8b48, + 0x2f8d47, + 0x2f9747, + 0x34da8a, + 0x2fbf8b, + 0x238845, + 0x3b1708, + 0x22aec3, + 0x36524c, + 0x38d68f, + 0x2b038d, + 0x2ef707, + 0x39b2c9, + 0x22cb47, + 0x240008, + 0x382ccc, + 0x272988, + 0x2511c8, + 0x30d64e, + 0x31d014, + 0x31d524, + 0x33ee8a, + 0x35d98b, + 0x250004, + 0x250009, + 0x3a7088, + 0x245a05, + 0x25fa8a, + 0x265107, + 0x2cf584, + 0x327883, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x220ec3, + 0x2cc586, + 0x211004, + 0x24c083, + 0x204703, + 0x21d603, + 0x200882, + 0x327883, + 0x206a82, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x250cc3, + 0x202243, + 0x2cc586, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x211004, + 0x24c083, + 0x204703, + 0x722f48, + 0x201482, + 0x200482, + 0x206a82, + 0x22bf83, + 0x200d02, + 0x202002, + 0x2023c4, + 0x30db04, + 0x21ee82, + 0x211004, + 0x200fc2, + 0x204703, + 0x21d603, + 0x23b346, + 0x212dc2, + 0x203f02, + 0x214a02, + 0x3aa23a03, + 0x3ae095c3, + 0x52886, + 0x52886, + 0x223504, + 0xe3d4c, + 0x19a1cc, + 0x8390d, + 0xda987, + 0x1cc08, + 0x22408, + 0x1a9f8a, + 0x3bb1cb45, + 0x11cb49, + 0x142c08, + 0x16b1ca, + 0x170bce, + 0x144218b, + 0x143f44, + 0x16fcc8, + 0x7f087, + 0x12c47, + 0x172cc9, + 0xb587, + 0x14bcc8, + 0x1a4249, + 0xda4c5, + 0x6098e, + 0xa868d, + 0x142a08, + 0x3be6b1c6, + 0x62c87, + 0x65d07, + 0x6bf07, + 0x72b87, + 0xd502, + 0x14d247, + 0x103a8c, + 0xed107, + 0x90906, + 0xa3849, + 0xa5408, + 0x134c2, + 0x2002, + 0x1808cb, + 0x18549, + 0x44b09, + 0x15bd88, + 0xafcc2, + 0x3c909, + 0x120809, + 0xcd808, + 0xcde07, + 0xcff09, + 0xd32c5, + 0xd36d0, + 0x1a2ac6, + 0x62145, + 0x22f4d, + 0xb146, + 0xdb947, + 0xe1c58, + 0xcfc88, + 0x19110a, + 0x185e4d, + 0x4042, + 0x72606, + 0x8c808, + 0x14ac08, + 0x77909, + 0x496c8, + 0x56f0e, + 0xe9f85, + 0x4ef08, + 0x1bc2, + 0x122706, + 0x6c2, + 0xc01, + 0x3c2e24c4, + 0x3c692f43, + 0x141, + 0x4e86, + 0x141, + 0x1, + 0x4e86, + 0x1570305, + 0x247204, + 0x22bf83, + 0x248fc4, + 0x2023c4, + 0x24c083, + 0x223985, + 0x20b743, + 0x2298c3, + 0x2ebf05, + 0x2232c3, + 0x3d62bf83, + 0x231b03, + 0x250cc3, + 0x200041, + 0x220ec3, + 0x30db04, + 0x211004, + 0x24c083, + 0x204703, + 0x20b803, + 0x77a48, + 0x200882, + 0x327883, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x202002, + 0x2023c4, + 0x202243, + 0x220ec3, + 0x24c083, + 0x2020c3, + 0x204703, + 0x2232c3, + 0x77a48, + 0x38d402, + 0x6a82, + 0xf8f0e, + 0x3e600142, + 0x27a048, + 0x225f46, + 0x2bc3c6, + 0x2258c7, + 0x3ea06b82, + 0x3ef58e08, + 0x20628a, + 0x262708, + 0x200ec2, + 0x206b09, + 0x238887, + 0x21a946, + 0x208d89, + 0x25ba04, + 0x2b7a46, + 0x2e2884, + 0x27b484, + 0x254709, + 0x343886, + 0x247885, + 0x20eec5, + 0x3a7607, + 0x2b9207, + 0x36ee44, + 0x225b06, + 0x2f2945, + 0x2e48c5, + 0x2f6e45, + 0x392607, + 0x3672c5, + 0x3098c9, + 0x2644c5, + 0x2d0cc4, + 0x2e8587, + 0x2cee0e, + 0x31ae09, + 0x327149, + 0x35c146, + 0x31bf08, + 0x2ae58b, + 0x2d1fcc, + 0x26c186, + 0x37b207, + 0x20ae05, + 0x228dca, + 0x31a489, + 0x24f6c9, + 0x388f86, + 0x2f0f05, + 0x282145, + 0x366349, + 0x2f6fcb, + 0x27ed46, + 0x333e06, + 0x20d444, + 0x28ba86, + 0x2aac48, + 0x201186, + 0x203786, + 0x209988, + 0x20a887, + 0x20ab89, + 0x20bdc5, + 0x77a48, + 0x212bc4, + 0x37ee84, + 0x213a85, + 0x395589, + 0x222b07, + 0x222b0b, + 0x2243ca, + 0x228ac5, + 0x3f20ce82, + 0x226d87, + 0x3f629408, + 0x287607, + 0x343bc5, + 0x238f8a, + 0x6a82, + 0x266d4b, + 0x383dca, + 0x223c86, + 0x3a4483, + 0x338f8d, + 0x35b24c, + 0x36654d, + 0x385a45, + 0x23e645, + 0x25ffc7, + 0x200d09, + 0x206186, + 0x32b5c5, + 0x2a9f08, + 0x28b983, + 0x2da308, + 0x28b988, + 0x2bd387, + 0x3b00c8, + 0x200b09, + 0x233a47, + 0x2e2e87, + 0x2f74c8, + 0x24c0c4, + 0x24c0c7, + 0x26df88, + 0x204bc6, + 0x39a48f, + 0x218747, + 0x2d76c6, + 0x240185, + 0x36e8c3, + 0x36e8c7, + 0x36a503, + 0x247b86, + 0x249b86, + 0x24b006, + 0x28fd05, + 0x2687c3, + 0x389f48, + 0x36c709, + 0x3817cb, + 0x24b188, + 0x24d105, + 0x24e185, + 0x3fa3d6c2, + 0x37dc09, + 0x202447, + 0x257f45, + 0x254607, + 0x256dc6, + 0x363645, + 0x36b8cb, + 0x259d04, + 0x2622c5, + 0x262407, + 0x278406, + 0x278845, + 0x286007, + 0x286587, + 0x274344, + 0x28a70a, + 0x28abc8, + 0x328d49, + 0x3a0805, + 0x34c306, + 0x2aae0a, + 0x20edc6, + 0x266f87, + 0x31694d, + 0x227b09, + 0x329805, + 0x345fc7, + 0x344108, + 0x344788, + 0x323487, + 0x366f86, + 0x215b47, + 0x249503, + 0x337a04, + 0x360585, + 0x38dd07, + 0x392009, + 0x227608, + 0x22ccc5, + 0x3afa84, + 0x382f85, + 0x2474cd, + 0x204242, + 0x302bc6, + 0x272546, + 0x2a3cca, + 0x365a86, + 0x377705, + 0x317145, + 0x317147, + 0x37e34c, + 0x27648a, + 0x28b746, + 0x206945, + 0x28b8c6, + 0x28bc07, + 0x28d946, + 0x28fc0c, + 0x208ec9, + 0x3fe05307, + 0x2924c5, + 0x2924c6, + 0x2929c8, + 0x2b1285, + 0x2a2c05, + 0x2a2e48, + 0x2a304a, + 0x4020b882, + 0x4060f802, + 0x3827c5, + 0x2d7643, + 0x267348, + 0x21dcc3, + 0x2a32c4, + 0x21dccb, + 0x2ae948, + 0x2a6088, + 0x40b40cc9, + 0x2a7ec9, + 0x2a8586, + 0x2a97c8, + 0x2a99c9, + 0x2ab6c6, + 0x2ab845, + 0x383646, + 0x2ac389, + 0x341607, + 0x24ad46, + 0x238c87, + 0x206007, + 0x23bc44, + 0x40efa889, + 0x2c3d08, + 0x358d08, + 0x360187, + 0x2bed46, + 0x3007c9, + 0x2f7a07, + 0x32a14a, + 0x2be708, + 0x34c447, + 0x357e06, + 0x21ce8a, + 0x280b88, + 0x271fc5, + 0x22d185, + 0x2be8c7, + 0x2d1789, + 0x2d6d4b, + 0x2ede48, + 0x264549, + 0x24b747, + 0x3adc4c, + 0x2b0e4c, + 0x2b114a, + 0x2b13cc, + 0x2bc348, + 0x2bc548, + 0x2bc744, + 0x2bcb09, + 0x2bcd49, + 0x2bcf8a, + 0x2bd209, + 0x2bd547, + 0x20010c, + 0x242886, + 0x2794c8, + 0x20ee86, + 0x388a46, + 0x329707, + 0x31b008, + 0x261a4b, + 0x2874c7, + 0x2f0bc9, + 0x249149, + 0x253dc7, + 0x2e2ac4, + 0x363b07, + 0x34c986, + 0x2179c6, + 0x237a05, + 0x2ccd48, + 0x20f2c4, + 0x20f2c6, + 0x27634b, + 0x2a6649, + 0x31e946, + 0x35ab09, + 0x392786, + 0x301348, + 0x2025c3, + 0x209185, + 0x2038c9, + 0x20cb05, + 0x2fd284, + 0x277506, + 0x26bdc5, + 0x2db706, + 0x2fe047, + 0x2af586, + 0x2974cb, + 0x35a7c7, + 0x2d1646, + 0x371506, + 0x3a76c6, + 0x36ee09, + 0x24df0a, + 0x2b5985, + 0x22d94d, + 0x2a3146, + 0x391306, + 0x2e1746, + 0x21d985, + 0x2d39c7, + 0x29bb47, + 0x29fb0e, + 0x220ec3, + 0x2bed09, + 0x316e89, + 0x2291c7, + 0x27e2c7, + 0x2a7505, + 0x323f05, + 0x4126304f, + 0x2c5b47, + 0x2c5d08, + 0x2c6784, + 0x2c6a46, + 0x41629382, + 0x2ca746, + 0x2cc586, + 0x261d8e, + 0x2da14a, + 0x226886, + 0x22ee4a, + 0x205d89, + 0x314e85, + 0x393c08, + 0x3adb06, + 0x31e788, + 0x326ac8, + 0x24090b, + 0x2259c5, + 0x367348, + 0x209acc, + 0x343a87, + 0x24a7c6, + 0x27fd08, + 0x2b7cc8, + 0x41a09142, + 0x3700cb, + 0x376209, + 0x2d2b49, + 0x3a3347, + 0x20af88, + 0x41f5b088, + 0x20bfcb, + 0x35bc09, + 0x221d4d, + 0x378388, + 0x29bf88, + 0x422018c2, + 0x201084, + 0x4260dd02, + 0x2edbc6, + 0x42a02482, + 0x21c48a, + 0x322806, + 0x32c808, + 0x31c208, + 0x2b7946, + 0x388086, + 0x2e8046, + 0x308f85, + 0x23a584, + 0x42f012c4, + 0x338446, + 0x33be87, + 0x432e9287, + 0x35e7cb, + 0x2cf1c9, + 0x23e68a, + 0x261644, + 0x317288, + 0x24ab0d, + 0x2dfd49, + 0x2dff88, + 0x2e06c9, + 0x2e1c44, + 0x208c84, + 0x281645, + 0x36228b, + 0x2ae8c6, + 0x338285, + 0x343d49, + 0x225bc8, + 0x29f3c4, + 0x228f49, + 0x330045, + 0x2b9248, + 0x2e3547, + 0x327548, + 0x281c06, + 0x226c47, + 0x2910c9, + 0x224189, + 0x249905, + 0x339605, + 0x436284c2, + 0x2e8344, + 0x33b285, + 0x291c46, + 0x335e85, + 0x24e247, + 0x26ccc5, + 0x26cd44, + 0x35c206, + 0x32b647, + 0x244f86, + 0x3af445, + 0x37fd48, + 0x226145, + 0x39a807, + 0x3b2509, + 0x2a678a, + 0x236987, + 0x23698c, + 0x247846, + 0x22b289, + 0x340105, + 0x370f08, + 0x212983, + 0x212985, + 0x2e90c5, + 0x255707, + 0x43a17482, + 0x23e287, + 0x2e5046, + 0x2fa7c6, + 0x303146, + 0x2b7c06, + 0x3302c8, + 0x35a005, + 0x2d7787, + 0x2d778d, + 0x24ddc3, + 0x3a4885, + 0x271b47, + 0x387bc8, + 0x271705, + 0x228808, + 0x32c346, + 0x31cd07, + 0x2bdf45, + 0x225a46, + 0x2d3005, + 0x2bb8ca, + 0x2fc546, + 0x233dc7, + 0x2c6905, + 0x2f5207, + 0x2f5904, + 0x2fd206, + 0x331ac5, + 0x34368b, + 0x34c809, + 0x243bca, + 0x249988, + 0x336448, + 0x337c8c, + 0x3556c7, + 0x35dd48, + 0x361308, + 0x36bc05, + 0x3a024a, + 0x2ea909, + 0x43e04582, + 0x204586, + 0x20c984, + 0x2de009, + 0x362d89, + 0x2250c7, + 0x254447, + 0x2b8649, + 0x326508, + 0x32650f, + 0x270f06, + 0x241b0b, + 0x2ebd45, + 0x2ebd47, + 0x2ec189, + 0x21de06, + 0x228ec7, + 0x3b1e45, + 0x2305c4, + 0x26bc86, + 0x200c44, + 0x30ba07, + 0x2ee808, + 0x442f0e08, + 0x2f1305, + 0x2f1447, + 0x256149, + 0x201904, + 0x201908, + 0x4476d588, + 0x28e1c4, + 0x230f08, + 0x31ebc4, + 0x21bf09, + 0x22dc45, + 0x44a012c2, + 0x270f45, + 0x220885, + 0x24cb48, + 0x232a87, + 0x44e05a02, + 0x2c8405, + 0x2518c6, + 0x266246, + 0x2e8308, + 0x2e9c48, + 0x335e46, + 0x2eac86, + 0x21e589, + 0x2fa706, + 0x3081cb, + 0x28edc5, + 0x20fcc6, + 0x3abd88, + 0x3906c6, + 0x35c646, + 0x21d30a, + 0x258dca, + 0x24dac5, + 0x35a0c7, + 0x349746, + 0x45201242, + 0x271c87, + 0x236445, + 0x2aad84, + 0x2aad85, + 0x261546, + 0x276d47, + 0x20c705, + 0x258f44, + 0x26d548, + 0x35c705, + 0x28af07, + 0x293245, + 0x219805, + 0x24a284, + 0x28f709, + 0x2f2788, + 0x2cea06, + 0x212e06, + 0x28dec6, + 0x457a8c08, + 0x2f5087, + 0x2f53cd, + 0x2f5b4c, + 0x2f6149, + 0x2f6389, + 0x45b54382, + 0x3a6903, + 0x20c403, + 0x34ca45, + 0x38de0a, + 0x318e06, + 0x2fab45, + 0x2fe584, + 0x2fe58b, + 0x30e4cc, + 0x30ed0c, + 0x30f015, + 0x30f9cd, + 0x31150f, + 0x3118d2, + 0x311d4f, + 0x312112, + 0x312593, + 0x312a4d, + 0x31300d, + 0x31338e, + 0x31384e, + 0x31448c, + 0x31480c, + 0x314c4b, + 0x314fce, + 0x318092, + 0x318bcc, + 0x319110, + 0x32d652, + 0x32e60c, + 0x32eccd, + 0x32f00c, + 0x332dd1, + 0x333f8d, + 0x33664d, + 0x336c4a, + 0x336ecc, + 0x3377cc, + 0x337f8c, + 0x33880c, + 0x33c653, + 0x33cc50, + 0x33d050, + 0x33d8cd, + 0x33decc, + 0x33ebc9, + 0x34024d, + 0x340593, + 0x346891, + 0x346cd3, + 0x34738f, + 0x34774c, + 0x347a4f, + 0x347e0d, + 0x34840f, + 0x3487d0, + 0x34924e, + 0x34d5ce, + 0x34dd10, + 0x34e90d, + 0x34f28e, + 0x34f60c, + 0x3505d3, + 0x3521ce, + 0x352910, + 0x352d11, + 0x35314f, + 0x353513, + 0x353f0d, + 0x35424f, + 0x35460e, + 0x354f10, + 0x355309, + 0x356010, + 0x35664f, + 0x356ccf, + 0x357092, + 0x35860e, + 0x3594cd, + 0x35cc0d, + 0x35cf4d, + 0x35f24d, + 0x35f58d, + 0x35f8d0, + 0x35fccb, + 0x36034c, + 0x3606cc, + 0x3609cc, + 0x360cce, + 0x36f050, + 0x371692, + 0x371b0b, + 0x3720ce, + 0x37244e, + 0x3736ce, + 0x37454b, + 0x45f74b16, + 0x37740d, + 0x378594, + 0x37920d, + 0x37ad55, + 0x37be8d, + 0x37c80f, + 0x37d04f, + 0x381a8f, + 0x381e4e, + 0x3830cd, + 0x3855d1, + 0x38820c, + 0x38850c, + 0x38880b, + 0x38938c, + 0x38974f, + 0x389b12, + 0x38a4cd, + 0x38b48c, + 0x38b90c, + 0x38bc0d, + 0x38bf4f, + 0x38c30e, + 0x38dacc, + 0x38e08d, + 0x38e3cb, + 0x38f00c, + 0x38f58d, + 0x38f8ce, + 0x38fd49, + 0x390a93, + 0x39148d, + 0x3917cd, + 0x391dcc, + 0x39224e, + 0x392bcf, + 0x392f8c, + 0x39328d, + 0x3935cf, + 0x39398c, + 0x39408c, + 0x39444c, + 0x39474c, + 0x394e0d, + 0x395152, + 0x3957cc, + 0x395acc, + 0x395dd1, + 0x39620f, + 0x3965cf, + 0x396993, + 0x397a8e, + 0x39800f, + 0x3983cc, + 0x4639870e, + 0x398a8f, + 0x398e56, + 0x39ad12, + 0x39c40c, + 0x39cd0f, + 0x39d38d, + 0x39d6cf, + 0x39da8c, + 0x39dd8d, + 0x39e0cd, + 0x39fd0e, + 0x3a14cc, + 0x3a17cc, + 0x3a1ad0, + 0x3a5c91, + 0x3a60cb, + 0x3a650c, + 0x3a680e, + 0x3a9111, + 0x3a954e, + 0x3a98cd, + 0x3ad8cb, + 0x3ae8cf, + 0x3afb94, + 0x224242, + 0x224242, + 0x204c83, + 0x224242, + 0x204c83, + 0x224242, + 0x20c942, + 0x383685, + 0x3a8e0c, + 0x224242, + 0x224242, + 0x20c942, + 0x224242, + 0x293045, + 0x2a6785, + 0x224242, + 0x224242, + 0x212bc2, + 0x293045, + 0x30ff09, + 0x34658c, + 0x224242, + 0x224242, + 0x224242, + 0x224242, + 0x383685, + 0x224242, + 0x224242, + 0x224242, + 0x224242, + 0x212bc2, + 0x30ff09, + 0x224242, + 0x224242, + 0x224242, + 0x2a6785, + 0x224242, + 0x2a6785, + 0x34658c, + 0x3a8e0c, + 0x327883, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x24c083, + 0x204703, + 0x4fdc8, + 0x57044, + 0x4bf48, + 0x200882, + 0x47206a82, + 0x240bc3, + 0x244c44, + 0x209d03, + 0x2db184, + 0x22fb86, + 0x203b43, + 0x379084, + 0x27bd85, + 0x220ec3, + 0x24c083, + 0x204703, + 0x24e9ca, + 0x23b346, + 0x3727cc, + 0x77a48, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x232003, + 0x2cc586, + 0x24c083, + 0x204703, + 0x21d603, + 0x8ac2, + 0xda987, + 0xb7008, + 0xf60e, + 0x89352, + 0x6e0b, + 0x47f1cb45, + 0x48375d8c, + 0x3c347, + 0x117a4a, + 0x3b4d0, + 0x16fcc8, + 0x7f087, + 0x58a4b, + 0x172cc9, + 0x16fbc7, + 0xb587, + 0x7ef87, + 0x188c6, + 0x14bcc8, + 0x4881c106, + 0xa868d, + 0x117410, + 0x48c08b02, + 0x142a08, + 0x6ca87, + 0x88349, + 0x52946, + 0x92bc8, + 0x10442, + 0x9ec8a, + 0xf2347, + 0xed107, + 0xa3849, + 0xa5408, + 0x159b85, + 0xe0c0e, + 0x1224e, + 0x171cf, + 0x18549, + 0x44b09, + 0x6f38b, + 0x8248f, + 0x8f90c, + 0xac74b, + 0x16be48, + 0x15e6c7, + 0xf02c8, + 0x11bd0b, + 0x13e54c, + 0x149e0c, + 0x151ecc, + 0x154a4d, + 0x15bd88, + 0x3c909, + 0x14e38b, + 0xbef46, + 0xcdfc5, + 0xd36d0, + 0x197586, + 0x62145, + 0xd6908, + 0xdb947, + 0xdcfc7, + 0x142e47, + 0xeda0a, + 0xb6e8a, + 0x72606, + 0x906cd, + 0x14ac08, + 0x496c8, + 0x4a1c9, + 0xed54c, + 0x154c4b, + 0x120304, + 0x16e409, + 0xd7e86, + 0x3f02, + 0x122706, + 0x6c2, + 0xc2ec5, + 0x481, + 0xb7c3, + 0x4878cd86, + 0x92f43, + 0xf582, + 0x3a004, + 0xec2, + 0x23504, + 0x9c2, + 0x8f02, + 0x70c2, + 0x105b42, + 0x1482, + 0x107ac2, + 0x8c2, + 0x1eb82, + 0x35542, + 0x682, + 0x1582, + 0xb042, + 0x31b03, + 0x4142, + 0x202, + 0x9342, + 0xdb02, + 0x10702, + 0x30842, + 0x134c2, + 0x42, + 0x4982, + 0x2002, + 0x2243, + 0x3fc2, + 0x7382, + 0xafcc2, + 0xac82, + 0x17382, + 0x3702, + 0x33a82, + 0x6a42, + 0xf842, + 0x16f542, + 0x8b82, + 0xb602, + 0x4c083, + 0xdc2, + 0x9142, + 0x1042, + 0x12f42, + 0x49885, + 0xa742, + 0x42242, + 0x3e943, + 0x34c2, + 0xed42, + 0x4042, + 0x2742, + 0x3a02, + 0x5a02, + 0x1bc2, + 0x3f02, + 0x74747, + 0x213f03, + 0x200882, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x215ac3, + 0x232003, + 0x24c083, + 0x2020c3, + 0x204703, + 0x292f83, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x220ec3, + 0x24c083, + 0x2020c3, + 0x204703, + 0x22bf83, + 0x231b03, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x200041, + 0x220ec3, + 0x24c083, + 0x20f543, + 0x204703, + 0x327883, + 0x22bf83, + 0x231b03, + 0x2aa943, + 0x20f583, + 0x376b83, + 0x285843, + 0x2a4543, + 0x240383, + 0x250cc3, + 0x2023c4, + 0x24c083, + 0x204703, + 0x2232c3, + 0x341bc4, + 0x22b683, + 0x1e03, + 0x201283, + 0x330d48, + 0x21cec4, + 0x315e4a, + 0x3807c6, + 0xdd704, + 0x3a4107, + 0x22134a, + 0x270dc9, + 0x3b15c7, + 0x20054a, + 0x327883, + 0x38284b, + 0x3292c9, + 0x28dfc5, + 0x2ca587, + 0x6a82, + 0x22bf83, + 0x3583c7, + 0x21e2c5, + 0x2e2989, + 0x231b03, + 0x2257c6, + 0x2b1e83, + 0xe50c3, + 0xfd786, + 0x60346, + 0x3ac7, + 0x214246, + 0x21a385, + 0x20be87, + 0x338647, + 0x4ae50cc3, + 0x32e847, + 0x363a03, + 0x238785, + 0x2023c4, + 0x222788, + 0x2ae00c, + 0x2ad305, + 0x3a30c6, + 0x358287, + 0x20a207, + 0x3b0407, + 0x205688, + 0x27ffcf, + 0x2d2a85, + 0x240cc7, + 0x39f787, + 0x2a340a, + 0x2a9d49, + 0x2d8305, + 0x2dbe4a, + 0x1225c6, + 0x2bb605, + 0x371d44, + 0x2b7886, + 0x300b87, + 0x23b987, + 0x341908, + 0x2025c5, + 0x21e1c6, + 0x203705, + 0x267105, + 0x21e104, + 0x31c107, + 0x33010a, + 0x399d08, + 0x2f0006, + 0x32003, + 0x2cff85, + 0x22b046, + 0x200346, + 0x262046, + 0x220ec3, + 0x38a747, + 0x39f705, + 0x24c083, + 0x3b184d, + 0x2020c3, + 0x341a08, + 0x3abc04, + 0x278705, + 0x2a3306, + 0x2347c6, + 0x20fbc7, + 0x2a4587, + 0x26c785, + 0x204703, + 0x3977c7, + 0x33b749, + 0x258349, + 0x26cd8a, + 0x244002, + 0x238744, + 0x2d7304, + 0x220c47, + 0x23e148, + 0x2dda89, + 0x3a4749, + 0x2ded47, + 0x2d2586, + 0xe0986, + 0x2e1c44, + 0x2e224a, + 0x2e7808, + 0x2e7f09, + 0x29b1c6, + 0x3028c5, + 0x399bc8, + 0x2c070a, + 0x25ad03, + 0x239406, + 0x2dee47, + 0x2115c5, + 0x3abac5, + 0x25b2c3, + 0x2512c4, + 0x22d145, + 0x286687, + 0x2f28c5, + 0x2edd06, + 0x135d45, + 0x226943, + 0x226949, + 0x2784cc, + 0x2ab3cc, + 0x2c7308, + 0x2995c7, + 0x2f1d48, + 0x2f318a, + 0x2f414b, + 0x329408, + 0x3a31c8, + 0x2032c6, + 0x34d3c5, + 0x31f40a, + 0x217cc5, + 0x2012c2, + 0x2bde07, + 0x26ed46, + 0x355b45, + 0x329f89, + 0x237f45, + 0x2be645, + 0x238349, + 0x22aec6, + 0x3650c8, + 0x35b843, + 0x35b8c6, + 0x277446, + 0x300285, + 0x300289, + 0x2b1989, + 0x244347, + 0x100104, + 0x300107, + 0x3a4649, + 0x221545, + 0x3a688, + 0x366d05, + 0x357885, + 0x22a889, + 0x20b0c2, + 0x22b484, + 0x202882, + 0x203fc2, + 0x33f285, + 0x2dd488, + 0x373085, + 0x2bd703, + 0x2bd705, + 0x2ca943, + 0x212602, + 0x269704, + 0x2344c3, + 0x209242, + 0x35a344, + 0x2d8003, + 0x20d102, + 0x2bd783, + 0x28c784, + 0x2b5c43, + 0x23d444, + 0x202942, + 0x275183, + 0x203a03, + 0x209642, + 0x2eab42, + 0x2b17c9, + 0x207e02, + 0x289ec4, + 0x208b42, + 0x399a44, + 0x2d2544, + 0x2e69c4, + 0x203f02, + 0x202f02, + 0x216483, + 0x2e3c43, + 0x310c04, + 0x262e44, + 0x2b1b84, + 0x2c5584, + 0x2ff383, + 0x2af143, + 0x322544, + 0x301544, + 0x301846, + 0x25b3c2, + 0x206a82, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x200882, + 0x327883, + 0x22bf83, + 0x231b03, + 0x204543, + 0x250cc3, + 0x2023c4, + 0x2b1a84, + 0x211004, + 0x24c083, + 0x204703, + 0x21d603, + 0x2e4144, + 0x27a003, + 0x2b3003, + 0x347104, + 0x366b06, + 0x208143, + 0x21afc3, + 0x211a83, + 0x2b0d83, + 0x2387c3, + 0x232003, + 0x2298c5, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x2da603, + 0x22e9c3, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x202243, + 0x24c083, + 0x232704, + 0x204703, + 0x29e044, + 0x2b7685, + 0x206a82, + 0x200e42, + 0x20f582, + 0x202b42, + 0x200fc2, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x211004, + 0x24c083, + 0x204703, + 0x20b803, + 0x223504, + 0x77a48, + 0x22bf83, + 0x2020c3, + 0x247204, + 0x77a48, + 0x22bf83, + 0x248fc4, + 0x2023c4, + 0x2020c3, + 0x2018c2, + 0x204703, + 0x2298c3, + 0x2ebf05, + 0x2012c2, + 0x301683, + 0x200882, + 0x77a48, + 0x206a82, + 0x231b03, + 0x250cc3, + 0x202002, + 0x204703, + 0x200882, + 0x200707, + 0x25ba05, + 0x2ba684, + 0x387ac6, + 0x20540b, + 0x267b89, + 0x3a3006, + 0x340a09, + 0x2b2508, + 0x208243, + 0x77a48, + 0x2286c7, + 0x328148, + 0x345883, + 0x3038c4, + 0x32c10b, + 0x266545, + 0x2f7888, + 0x2ea389, + 0x25a0c3, + 0x22bf83, + 0x204488, + 0x2f0fc7, + 0x345e86, + 0x231b03, + 0x345987, + 0x250cc3, + 0x2598c6, + 0x202243, + 0x22d007, + 0x235947, + 0x390f47, + 0x31c085, + 0x20a8c3, + 0x21038b, + 0x265448, + 0x227c88, + 0x33b906, + 0x344b49, + 0x323887, + 0x2fae85, + 0x3af704, + 0x271008, + 0x234e4a, + 0x235089, + 0x26d4c3, + 0x281485, + 0x28da83, + 0x22c806, + 0x2ba4c4, + 0x300488, + 0x388b8b, + 0x33f145, + 0x2b7406, + 0x2ba3c5, + 0x2baa88, + 0x2bb747, + 0x3b0287, + 0x315a47, + 0x2151c4, + 0x30b3c7, + 0x296746, + 0x220ec3, + 0x2c3b08, + 0x24e2c3, + 0x2cac08, + 0x2d42c5, + 0x3ac0c8, + 0x231d07, + 0x24c083, + 0x245c83, + 0x28ae44, + 0x323b87, + 0x209d83, + 0x235a0b, + 0x2039c3, + 0x24e284, + 0x2ebf88, + 0x204703, + 0x2f2f05, + 0x376a05, + 0x3abfc6, + 0x215c45, + 0x2d4684, + 0x209202, + 0x2e81c3, + 0x371dca, + 0x3a24c3, + 0x271549, + 0x30b0c6, + 0x217f88, + 0x28c2c6, + 0x224d87, + 0x2e8788, + 0x2f2d08, + 0x319043, + 0x373143, + 0x22a3c9, + 0x2f61c3, + 0x349646, + 0x25b686, + 0x2445c6, + 0x397389, + 0x2ffd44, + 0x216c43, + 0x2dbd45, + 0x30c709, + 0x22d103, + 0x2fc404, + 0x362ac4, + 0x212dc4, + 0x294846, + 0x20a403, + 0x20a408, + 0x255448, + 0x2eb306, + 0x2fac8b, + 0x2fafc8, + 0x2fb1cb, + 0x2fdd89, + 0x2fd687, + 0x2fe208, + 0x2fedc3, + 0x2e94c6, + 0x39ab47, + 0x297445, + 0x34d8c9, + 0x34448d, + 0x217dd1, + 0x234905, + 0x200882, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x2c8144, + 0x250cc3, + 0x202243, + 0x220ec3, + 0x24c083, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x232003, + 0x24c083, + 0x204703, + 0x263c83, + 0x20b803, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x232003, + 0x24c083, + 0x204703, + 0x212dc2, + 0x200141, + 0x200882, + 0x200001, + 0x311602, + 0x77a48, + 0x21fc45, + 0x200481, + 0x2bf83, + 0x200741, + 0x200081, + 0x201501, + 0x234382, + 0x36a504, + 0x383603, + 0x2007c1, + 0x200901, + 0x200041, + 0x2001c1, + 0x388e07, + 0x2d49cf, + 0x2cadc6, + 0x2000c1, + 0x26c046, + 0x200341, + 0x200cc1, + 0x25040e, + 0x200fc1, + 0x204703, + 0x200ac1, + 0x26f285, + 0x209202, + 0x25b1c5, + 0x200c01, + 0x200241, + 0x200a01, + 0x2012c2, + 0x2002c1, + 0x201d01, + 0x2041c1, + 0x200781, + 0x200641, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x20b743, + 0x22bf83, + 0x250cc3, + 0x8ce48, + 0x220ec3, + 0x24c083, + 0x204703, + 0x14d9688, + 0x77a48, + 0x45684, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x24c083, + 0x204703, + 0x201e03, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x2c8144, + 0x204703, + 0x297985, + 0x325c04, + 0x22bf83, + 0x24c083, + 0x204703, + 0x206a82, + 0x22bf83, + 0x230509, + 0x231b03, + 0x23db49, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x2e1a48, + 0x21d847, + 0x2ebf05, + 0x200707, + 0x20540b, + 0x204f48, + 0x340a09, + 0x2286c7, + 0x204488, + 0x2598c6, + 0x235947, + 0x227c88, + 0x33b906, + 0x323887, + 0x235089, + 0x37ab09, + 0x2b7406, + 0x2b9385, + 0x2c3b08, + 0x24e2c3, + 0x2cac08, + 0x231d07, + 0x209d83, + 0x358107, + 0x215c45, + 0x2dd2c8, + 0x264905, + 0x373143, + 0x2c7b49, + 0x2a9bc7, + 0x2fc404, + 0x362ac4, + 0x2fac8b, + 0x2fafc8, + 0x2fd687, + 0x22bf83, + 0x231b03, + 0x20f583, + 0x204703, + 0x22d3c3, + 0x250cc3, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x200882, + 0x206a82, + 0x204703, + 0x77a48, + 0x200882, + 0x206a82, + 0x20f582, + 0x202002, + 0x200342, + 0x24c083, + 0x200fc2, + 0x200882, + 0x327883, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x20f582, + 0x250cc3, + 0x202243, + 0x220ec3, + 0x211004, + 0x24c083, + 0x21a883, + 0x204703, + 0x2ffd44, + 0x2232c3, + 0x250cc3, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x2020c3, + 0x204703, + 0x39c8c7, + 0x22bf83, + 0x2555c7, + 0x263506, + 0x203983, + 0x210c43, + 0x250cc3, + 0x2037c3, + 0x2023c4, + 0x377844, + 0x2d4746, + 0x250403, + 0x24c083, + 0x204703, + 0x297985, + 0x20d644, + 0x317f43, + 0x2273c3, + 0x2bde07, + 0x2e34c5, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x209ec2, + 0x34ad43, + 0x237643, + 0x327883, + 0x5522bf83, + 0x200d02, + 0x231b03, + 0x209d03, + 0x250cc3, + 0x2023c4, + 0x265603, + 0x2d2a83, + 0x220ec3, + 0x211004, + 0x5560dbc2, + 0x24c083, + 0x204703, + 0x22a543, + 0x2468c3, + 0x212dc2, + 0x2232c3, + 0x77a48, + 0x250cc3, + 0x2cf584, + 0x327883, + 0x206a82, + 0x22bf83, + 0x234a44, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x2ce884, + 0x30db04, + 0x2cc586, + 0x211004, + 0x24c083, + 0x204703, + 0x21d603, + 0x26ed46, + 0x18b4b, + 0x1c106, + 0x2310a, + 0xfee8a, + 0x77a48, + 0x2036c4, + 0x22bf83, + 0x327844, + 0x231b03, + 0x24a304, + 0x250cc3, + 0x2614c3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x32104b, + 0x39e40a, + 0x3b0a4c, + 0x200882, + 0x206a82, + 0x20f582, + 0x2a8e05, + 0x2023c4, + 0x20f842, + 0x220ec3, + 0x30db04, + 0x202b42, + 0x200fc2, + 0x203682, + 0x212dc2, + 0x127883, + 0x35ecc9, + 0x25b508, + 0x33a1c9, + 0x235789, + 0x23cc0a, + 0x255f4a, + 0x20a1c2, + 0x21eb82, + 0x6a82, + 0x22bf83, + 0x208942, + 0x240e86, + 0x356b42, + 0x218982, + 0x27184e, + 0x2751ce, + 0x27f787, + 0x3804c7, + 0x274802, + 0x231b03, + 0x250cc3, + 0x201b42, + 0x202002, + 0x233fcf, + 0x205482, + 0x23bb07, + 0x33bb07, + 0x365587, + 0x24dbcc, + 0x253f4c, + 0x204b44, + 0x28148a, + 0x28da82, + 0x20ac82, + 0x2b1f04, + 0x2266c2, + 0x2bc342, + 0x254184, + 0x21a982, + 0x217382, + 0x33b987, + 0x27fec5, + 0x233a82, + 0x233f44, + 0x36f542, + 0x2ce2c8, + 0x24c083, + 0x3b2248, + 0x201082, + 0x232fc5, + 0x324146, + 0x204703, + 0x20a742, + 0x2ddcc7, + 0x9202, + 0x274b05, + 0x393f45, + 0x2040c2, + 0x22b382, + 0x31650a, + 0x26c60a, + 0x20b5c2, + 0x320784, + 0x201f02, + 0x238608, + 0x20a302, + 0x33b148, + 0x2f7bc7, + 0x2f7ec9, + 0x274b82, + 0x2fdfc5, + 0x25b9c5, + 0x2c13cb, + 0x2c210c, + 0x22ce88, + 0x2fe388, + 0x25b3c2, + 0x20fc82, + 0x200882, + 0x77a48, + 0x206a82, + 0x22bf83, + 0x20f582, + 0x202b42, + 0x200fc2, + 0x204703, + 0x203682, + 0x200882, + 0x57606a82, + 0x57a50cc3, + 0x39a883, + 0x20f842, + 0x24c083, + 0x3a2c03, + 0x204703, + 0x2d9f83, + 0x274846, + 0x160b803, + 0x77a48, + 0x62145, + 0x6ae47, + 0x58200182, + 0x58600ec2, + 0x58a01e02, + 0x58e02902, + 0x592136c2, + 0x59601482, + 0x59a06a82, + 0x59e0e542, + 0x5a221982, + 0x5a601582, + 0x2751c3, + 0x201503, + 0x5aa17982, + 0x5ae01c82, + 0x49507, + 0x5b233602, + 0x5b600902, + 0x5ba048c2, + 0x5be0b542, + 0x5c204982, + 0x5c602002, + 0xbac45, + 0x226103, + 0x20b504, + 0x5ca266c2, + 0x5ce35c82, + 0x5d200102, + 0x7c80b, + 0x5d600982, + 0x5de0ad82, + 0x5e20f842, + 0x5e600342, + 0x5ea50702, + 0x5ee02ac2, + 0x5f203642, + 0x5f608b82, + 0x5fa0dbc2, + 0x5fe00cc2, + 0x60202b42, + 0x606353c2, + 0x60a02d82, + 0x60e43482, + 0x14c104, + 0x2d2fc3, + 0x61211382, + 0x61619d02, + 0x61a052c2, + 0x61e03502, + 0x62200fc2, + 0x62609242, + 0xdbc07, + 0x62a08582, + 0x62e05fc2, + 0x63203682, + 0x6364ecc2, + 0xed54c, + 0x63a1c642, + 0x63e75bc2, + 0x642076c2, + 0x64601242, + 0x64a0c402, + 0x64e3cd82, + 0x65201d02, + 0x65603b82, + 0x65a777c2, + 0x65e4ffc2, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x5da65603, + 0x2805c3, + 0x229944, + 0x25b406, + 0x2e8283, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x265603, + 0x2805c3, + 0x200482, + 0x200482, + 0x265603, + 0x2805c3, + 0x6662bf83, + 0x231b03, + 0x331043, + 0x220ec3, + 0x24c083, + 0x204703, + 0x77a48, + 0x206a82, + 0x22bf83, + 0x24c083, + 0x204703, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x220ec3, + 0x24c083, + 0x204703, + 0x247204, + 0x206a82, + 0x22bf83, + 0x2cfe43, + 0x231b03, + 0x248fc4, + 0x20f583, + 0x250cc3, + 0x2023c4, + 0x202243, + 0x220ec3, + 0x24c083, + 0x204703, + 0x2298c3, + 0x2ebf05, + 0x237d03, + 0x2232c3, + 0x206a82, + 0x22bf83, + 0x265603, + 0x24c083, + 0x204703, + 0x200882, + 0x327883, + 0x77a48, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x22fb86, + 0x2023c4, + 0x202243, + 0x211004, + 0x24c083, + 0x204703, + 0x21d603, + 0x22bf83, + 0x231b03, + 0x24c083, + 0x204703, + 0x22bf83, + 0x1c106, + 0x231b03, + 0x250cc3, + 0xd19c6, + 0x24c083, + 0x204703, + 0x309748, + 0x30d009, + 0x319509, + 0x329dc8, + 0x37d6c8, + 0x37d6c9, + 0x34385, + 0x200882, + 0x2e3305, + 0x22fc03, + 0x69206a82, + 0x231b03, + 0x250cc3, + 0x22c947, + 0x2387c3, + 0x220ec3, + 0x24c083, + 0x20f543, + 0x213583, + 0x2020c3, + 0x204703, + 0x23b346, + 0x2012c2, + 0x2232c3, + 0x77a48, + 0x200882, + 0x327883, + 0x206a82, + 0x22bf83, + 0x231b03, + 0x250cc3, + 0x2023c4, + 0x220ec3, + 0x24c083, + 0x204703, + 0x20b803, } // children is the list of nodes' children, the parent's wildcard bit and the @@ -8520,428 +8542,432 @@ var nodes = [...]uint32{ // [14 bits] high nodes index (exclusive) of children // [14 bits] low nodes index (inclusive) of children var children = [...]uint32{ - 0x00000000, + 0x0, 0x10000000, 0x20000000, 0x40000000, 0x50000000, 0x60000000, - 0x01858610, - 0x0185c616, - 0x0187c617, - 0x019d861f, - 0x019ec676, - 0x01a0067b, - 0x01a10680, - 0x01a2c684, - 0x01a3068b, - 0x01a4868c, - 0x01a6c692, - 0x01a7069b, - 0x01a8869c, - 0x01a8c6a2, - 0x01aa86a3, - 0x01aac6aa, - 0x01af46ab, - 0x01af86bd, - 0x01b186be, - 0x01b2c6c6, - 0x01b306cb, - 0x01b606cc, - 0x01b8c6d8, - 0x01bb46e3, - 0x01bbc6ed, - 0x01bc06ef, - 0x01c546f0, - 0x01c68715, - 0x01c7c71a, - 0x01ca871f, - 0x01cb872a, - 0x01ccc72e, - 0x01cf0733, - 0x01e0873c, - 0x01e0c782, - 0x01e20783, - 0x01e34788, - 0x01e3c78d, - 0x01e4c78f, - 0x01e50793, - 0x01e68794, - 0x01eb079a, - 0x01ec47ac, - 0x01ec87b1, - 0x01ecc7b2, - 0x01ed47b3, - 0x01f107b5, - 0x61f147c4, - 0x01f287c5, - 0x01f387ca, - 0x01fec7ce, - 0x21ff07fb, - 0x01ff47fc, - 0x01ff87fd, - 0x21ffc7fe, - 0x220007ff, - 0x02034800, - 0x0203880d, - 0x0244880e, + 0x1858610, + 0x185c616, + 0x187c617, + 0x19d861f, + 0x19ec676, + 0x1a0067b, + 0x1a10680, + 0x1a2c684, + 0x1a3068b, + 0x1a4868c, + 0x1a6c692, + 0x1a7069b, + 0x1a8869c, + 0x1a8c6a2, + 0x1aa86a3, + 0x1aac6aa, + 0x1af46ab, + 0x1af86bd, + 0x1b186be, + 0x1b2c6c6, + 0x1b306cb, + 0x1b606cc, + 0x1b7c6d8, + 0x1ba46df, + 0x1bac6e9, + 0x1bb06eb, + 0x1c446ec, + 0x1c58711, + 0x1c6c716, + 0x1c9871b, + 0x1ca8726, + 0x1cbc72a, + 0x1ce072f, + 0x1df8738, + 0x1dfc77e, + 0x1e1077f, + 0x1e24784, + 0x1e2c789, + 0x1e3c78b, + 0x1e4078f, + 0x1e58790, + 0x1ea0796, + 0x1eb47a8, + 0x1eb87ad, + 0x1ebc7ae, + 0x1ec47af, + 0x1f007b1, + 0x61f047c0, + 0x1f187c1, + 0x1f1c7c6, + 0x1f2c7c7, + 0x1fdc7cb, + 0x1fe07f7, + 0x21fe87f8, + 0x21fec7fa, + 0x1ff07fb, + 0x20247fc, + 0x2028809, + 0x244880a, 0x22498912, 0x2249c926, - 0x024c4927, - 0x024cc931, + 0x24c4927, + 0x24cc931, 0x224d0933, - 0x024d8934, - 0x224dc936, - 0x024e8937, + 0x24d8934, + 0x224e8936, 0x224ec93a, - 0x0250893b, - 0x02520942, - 0x02524948, - 0x02534949, - 0x0253c94d, - 0x2257094f, - 0x0257495c, - 0x0258095d, - 0x025a8960, - 0x025c096a, - 0x025d4970, - 0x025fc975, - 0x0261c97f, - 0x0264c987, - 0x02674993, - 0x0267899d, - 0x0269c99e, - 0x026a09a7, - 0x026b49a8, - 0x026b89ad, - 0x026bc9ae, - 0x026dc9af, - 0x026ec9b7, - 0x027609bb, - 0x0277c9d8, - 0x027889df, - 0x0279c9e2, - 0x027b49e7, - 0x027c89ed, - 0x027e09f2, - 0x027f89f8, - 0x028109fe, - 0x0282ca04, - 0x02844a0b, - 0x028a4a11, - 0x028bca29, - 0x028d0a2f, - 0x02914a34, - 0x02994a45, - 0x029c0a65, - 0x029c4a70, - 0x029cca71, - 0x029eca73, - 0x029f0a7b, - 0x02a0ca7c, - 0x02a14a83, - 0x02a48a85, - 0x02a80a92, - 0x02a84aa0, - 0x02aa8aa1, - 0x02ac0aaa, - 0x02ae4ab0, - 0x02b04ab9, - 0x030c8ac1, - 0x030d4c32, - 0x030f4c35, - 0x032b0c3d, - 0x03380cac, - 0x033f0ce0, - 0x03448cfc, - 0x03530d12, - 0x03588d4c, - 0x035c4d62, - 0x036c0d71, - 0x0378cdb0, - 0x03824de3, - 0x038b4e09, - 0x03918e2d, - 0x03b50e46, - 0x03c08ed4, - 0x03cd4f02, - 0x03d20f35, - 0x03da8f48, - 0x03de4f6a, - 0x03e34f79, - 0x03eacf8d, - 0x63eb0fab, - 0x63eb4fac, - 0x63eb8fad, - 0x03f34fae, - 0x03f9cfcd, - 0x04018fe7, - 0x04091006, - 0x04111024, - 0x0417d044, - 0x042a905f, - 0x043010aa, - 0x643050c0, - 0x0439d0c1, - 0x044250e7, - 0x04471109, - 0x044d911c, - 0x04581136, - 0x04649160, - 0x046b1192, - 0x047c51ac, - 0x647c91f1, - 0x647cd1f2, - 0x048291f3, - 0x0488520a, - 0x04915221, - 0x04991245, - 0x049d5264, - 0x04ab9275, - 0x04aed2ae, - 0x04b4d2bb, - 0x04bc12d3, - 0x04c492f0, - 0x04c89312, - 0x04cf9322, - 0x64cfd33e, - 0x64d0133f, - 0x24d05340, - 0x04d1d341, - 0x04d39347, - 0x04d7d34e, - 0x04d8d35f, - 0x04da5363, - 0x04e1d369, - 0x04e31387, - 0x04e4938c, - 0x04e6d392, - 0x04e8139b, - 0x04e9d3a0, - 0x04ea13a7, - 0x04ea93a8, - 0x04ee53aa, - 0x04ef93b9, - 0x04f013be, - 0x04f093c0, - 0x04f0d3c2, - 0x04f313c3, - 0x04f553cc, - 0x04f6d3d5, - 0x04f713db, - 0x04f793dc, - 0x04f7d3de, - 0x04fd13df, - 0x04ff53f4, - 0x050153fd, - 0x05031405, - 0x0504140c, - 0x05055410, - 0x05059415, - 0x05061416, - 0x05075418, - 0x0508541d, - 0x05089421, - 0x050a5422, - 0x05935429, - 0x0596d64d, - 0x0599965b, - 0x059b1666, - 0x059d166c, - 0x659d5674, - 0x05a19675, - 0x05a21686, - 0x25a25688, - 0x25a29689, - 0x05a2d68a, - 0x05b4968b, - 0x25b4d6d2, - 0x25b556d3, - 0x25b5d6d5, - 0x25b696d7, - 0x05b6d6da, - 0x05b956db, - 0x05bbd6e5, - 0x05bc16ef, - 0x25bf96f0, - 0x05c056fe, - 0x0675d701, - 0x067619d7, - 0x067659d8, - 0x267699d9, - 0x0676d9da, - 0x267719db, - 0x067759dc, - 0x267819dd, - 0x067859e0, - 0x067899e1, - 0x2678d9e2, - 0x067919e3, - 0x267999e4, - 0x0679d9e6, - 0x067a19e7, - 0x267b19e8, - 0x067b59ec, - 0x067b99ed, - 0x067bd9ee, - 0x067c19ef, - 0x267c59f0, - 0x067c99f1, - 0x067cd9f2, - 0x067d19f3, - 0x067d59f4, - 0x267dd9f5, - 0x067e19f7, - 0x067e59f8, - 0x067e99f9, - 0x267ed9fa, - 0x067f19fb, - 0x267f99fc, - 0x267fd9fe, - 0x068199ff, - 0x06825a06, - 0x06865a09, - 0x06869a19, - 0x0688da1a, - 0x069b5a23, - 0x269bda6d, - 0x269c1a6f, - 0x269c5a70, - 0x069cda71, - 0x06aa9a73, - 0x06aadaaa, - 0x06ad9aab, - 0x06af9ab6, - 0x06b05abe, - 0x06b25ac1, - 0x06b5dac9, - 0x06df1ad7, - 0x06eadb7c, - 0x06ec1bab, - 0x06ef5bb0, - 0x06f21bbd, - 0x06f3dbc8, - 0x06f61bcf, - 0x06f79bd8, - 0x06f95bde, - 0x06fb9be5, - 0x06fc9bee, - 0x06ff9bf2, - 0x07015bfe, - 0x07221c05, - 0x07245c88, - 0x07265c91, - 0x07279c99, - 0x0728dc9e, - 0x072adca3, - 0x07351cab, - 0x0736dcd4, - 0x07389cdb, - 0x0738dce2, - 0x07391ce3, - 0x07395ce4, - 0x073a9ce5, - 0x073c9cea, - 0x073d5cf2, - 0x07405cf5, - 0x07485d01, - 0x07499d21, - 0x0749dd26, - 0x074b5d27, - 0x074c1d2d, - 0x074c5d30, - 0x074e1d31, - 0x0751dd38, - 0x07521d47, - 0x07541d48, - 0x07591d50, - 0x075a9d64, - 0x075fdd6a, - 0x07601d7f, - 0x07605d80, - 0x07649d81, - 0x07659d92, - 0x07691d96, - 0x076c1da4, - 0x077fddb0, - 0x07821dff, - 0x0784de08, - 0x07855e13, - 0x07859e15, - 0x07961e16, - 0x0796de58, - 0x07979e5b, - 0x07985e5e, - 0x07991e61, - 0x0799de64, - 0x079a9e67, - 0x079b5e6a, - 0x079c1e6d, - 0x079cde70, - 0x079d9e73, - 0x079e5e76, - 0x079f1e79, - 0x079fde7c, - 0x07a05e7f, - 0x07a11e81, - 0x07a1de84, - 0x07a29e87, - 0x07a35e8a, - 0x07a41e8d, - 0x07a4de90, - 0x07a59e93, - 0x07a65e96, - 0x07a71e99, - 0x07a7de9c, - 0x07a89e9f, - 0x07a95ea2, - 0x07aa1ea5, - 0x07aadea8, - 0x07ab9eab, - 0x07ac5eae, - 0x07ad1eb1, - 0x07ad9eb4, - 0x07ae5eb6, - 0x07af1eb9, - 0x07afdebc, - 0x07b09ebf, - 0x07b15ec2, - 0x07b21ec5, - 0x07b2dec8, - 0x07b39ecb, - 0x07b45ece, - 0x07b51ed1, - 0x07b5ded4, - 0x07b69ed7, - 0x07b75eda, - 0x07b7dedd, - 0x07b89edf, - 0x07b95ee2, - 0x07ba1ee5, - 0x07badee8, - 0x07bb9eeb, - 0x07bc5eee, - 0x07bd1ef1, - 0x07bddef4, - 0x07be1ef7, - 0x07bedef8, - 0x07c05efb, - 0x07c09f01, - 0x07c19f02, - 0x07c31f06, - 0x07c75f0c, - 0x07c89f1d, - 0x07cbdf22, - 0x07ccdf2f, - 0x07ce9f33, - 0x07d01f3a, - 0x27d45f40, - 0x07d49f51, - 0x07d75f52, + 0x24f893b, + 0x24fc93e, + 0x2250093f, + 0x251c940, + 0x2534947, + 0x253894d, + 0x254894e, + 0x2550952, + 0x22584954, + 0x2588961, + 0x2598962, + 0x25c4966, + 0x25dc971, + 0x25f0977, + 0x261897c, + 0x2638986, + 0x266898e, + 0x269099a, + 0x26949a4, + 0x26b89a5, + 0x26bc9ae, + 0x26d09af, + 0x26d49b4, + 0x26d89b5, + 0x26f89b6, + 0x26fc9be, + 0x270c9bf, + 0x27809c3, + 0x279c9e0, + 0x27a89e7, + 0x27bc9ea, + 0x27d49ef, + 0x27e89f5, + 0x28009fa, + 0x2818a00, + 0x2830a06, + 0x284ca0c, + 0x2864a13, + 0x28c4a19, + 0x28dca31, + 0x28f0a37, + 0x2934a3c, + 0x29b4a4d, + 0x29e0a6d, + 0x29e4a78, + 0x29eca79, + 0x2a0ca7b, + 0x2a10a83, + 0x2a2ca84, + 0x2a34a8b, + 0x2a68a8d, + 0x2aa0a9a, + 0x2aa4aa8, + 0x2ad0aa9, + 0x2ae8ab4, + 0x2b0caba, + 0x2b2cac3, + 0x30f0acb, + 0x30fcc3c, + 0x311cc3f, + 0x32d8c47, + 0x33a8cb6, + 0x3418cea, + 0x3470d06, + 0x3558d1c, + 0x35b0d56, + 0x35ecd6c, + 0x36e8d7b, + 0x37b4dba, + 0x384cded, + 0x38dce13, + 0x3940e37, + 0x3b78e50, + 0x3c30ede, + 0x3cfcf0c, + 0x3d48f3f, + 0x3dd0f52, + 0x3e0cf74, + 0x3e5cf83, + 0x3ed4f97, + 0x63ed8fb5, + 0x63edcfb6, + 0x63ee0fb7, + 0x3f5cfb8, + 0x3fc0fd7, + 0x403cff0, + 0x40b500f, + 0x413502d, + 0x41a104d, + 0x42cd068, + 0x43250b3, + 0x643290c9, + 0x43c10ca, + 0x44490f0, + 0x4495112, + 0x44fd125, + 0x45a513f, + 0x466d169, + 0x46d519b, + 0x47e91b5, + 0x647ed1fa, + 0x647f11fb, + 0x484d1fc, + 0x48a9213, + 0x493922a, + 0x49b524e, + 0x49f926d, + 0x4add27e, + 0x4b112b7, + 0x4b712c4, + 0x4be52dc, + 0x4c6d2f9, + 0x4cad31b, + 0x4d1d32b, + 0x64d21347, + 0x64d25348, + 0x24d29349, + 0x4d4134a, + 0x4d5d350, + 0x4da1357, + 0x4db1368, + 0x4dc936c, + 0x4e41372, + 0x4e55390, + 0x4e6d395, + 0x4e9139b, + 0x4ea53a4, + 0x4ec13a9, + 0x4ec53b0, + 0x4ecd3b1, + 0x4f093b3, + 0x4f1d3c2, + 0x4f253c7, + 0x4f2d3c9, + 0x4f313cb, + 0x4f553cc, + 0x4f793d5, + 0x4f913de, + 0x4f953e4, + 0x4f9d3e5, + 0x4fa13e7, + 0x4ff53e8, + 0x50193fd, + 0x5039406, + 0x505540e, + 0x5065415, + 0x5079419, + 0x507d41e, + 0x508541f, + 0x5099421, + 0x50a9426, + 0x50ad42a, + 0x50c942b, + 0x5959432, + 0x5991656, + 0x59bd664, + 0x59d566f, + 0x59f5675, + 0x659f967d, + 0x5a3d67e, + 0x5a4568f, + 0x25a49691, + 0x25a4d692, + 0x5a51693, + 0x5b71694, + 0x25b756dc, + 0x25b7d6dd, + 0x25b856df, + 0x25b916e1, + 0x5b956e4, + 0x5bbd6e5, + 0x5be56ef, + 0x5be96f9, + 0x25c216fa, + 0x5c31708, + 0x678970c, + 0x678d9e2, + 0x67919e3, + 0x267959e4, + 0x67999e5, + 0x2679d9e6, + 0x67a19e7, + 0x267ad9e8, + 0x67b19eb, + 0x67b59ec, + 0x267b99ed, + 0x67bd9ee, + 0x267c59ef, + 0x67c99f1, + 0x67cd9f2, + 0x267dd9f3, + 0x67e19f7, + 0x67e59f8, + 0x67e99f9, + 0x67ed9fa, + 0x267f19fb, + 0x67f59fc, + 0x67f99fd, + 0x67fd9fe, + 0x68019ff, + 0x26809a00, + 0x680da02, + 0x6811a03, + 0x6815a04, + 0x26819a05, + 0x681da06, + 0x26825a07, + 0x26829a09, + 0x6845a0a, + 0x6851a11, + 0x6891a14, + 0x6895a24, + 0x68b9a25, + 0x69fda2e, + 0x26a05a7f, + 0x26a09a81, + 0x26a0da82, + 0x6a15a83, + 0x6af1a85, + 0x6af5abc, + 0x6b21abd, + 0x6b41ac8, + 0x6b4dad0, + 0x6b6dad3, + 0x6ba5adb, + 0x6e3dae9, + 0x6ef9b8f, + 0x6f0dbbe, + 0x6f41bc3, + 0x6f6dbd0, + 0x6f89bdb, + 0x6fadbe2, + 0x6fc5beb, + 0x6fe1bf1, + 0x7005bf8, + 0x7015c01, + 0x7045c05, + 0x7061c11, + 0x726dc18, + 0x7291c9b, + 0x72b1ca4, + 0x72c5cac, + 0x72d9cb1, + 0x72f9cb6, + 0x739dcbe, + 0x73b9ce7, + 0x73d5cee, + 0x73d9cf5, + 0x73ddcf6, + 0x73e1cf7, + 0x73f5cf8, + 0x7415cfd, + 0x7421d05, + 0x7451d08, + 0x74d1d14, + 0x74e5d34, + 0x74e9d39, + 0x7501d3a, + 0x750dd40, + 0x7511d43, + 0x752dd44, + 0x7569d4b, + 0x756dd5a, + 0x758dd5b, + 0x75ddd63, + 0x75f5d77, + 0x7649d7d, + 0x764dd92, + 0x7651d93, + 0x7695d94, + 0x76a5da5, + 0x76ddda9, + 0x770ddb7, + 0x7849dc3, + 0x786de12, + 0x7899e1b, + 0x78a1e26, + 0x78a5e28, + 0x79ade29, + 0x79b9e6b, + 0x79c5e6e, + 0x79d1e71, + 0x79dde74, + 0x79e9e77, + 0x79f5e7a, + 0x7a01e7d, + 0x7a0de80, + 0x7a19e83, + 0x7a25e86, + 0x7a31e89, + 0x7a3de8c, + 0x7a49e8f, + 0x7a51e92, + 0x7a5de94, + 0x7a69e97, + 0x7a75e9a, + 0x7a81e9d, + 0x7a8dea0, + 0x7a99ea3, + 0x7aa5ea6, + 0x7ab1ea9, + 0x7abdeac, + 0x7ac9eaf, + 0x7ad5eb2, + 0x7ae1eb5, + 0x7aedeb8, + 0x7af9ebb, + 0x7b05ebe, + 0x7b11ec1, + 0x7b1dec4, + 0x7b25ec7, + 0x7b31ec9, + 0x7b3decc, + 0x7b49ecf, + 0x7b55ed2, + 0x7b61ed5, + 0x7b6ded8, + 0x7b79edb, + 0x7b85ede, + 0x7b91ee1, + 0x7b9dee4, + 0x7ba9ee7, + 0x7bb5eea, + 0x7bc1eed, + 0x7bc9ef0, + 0x7bd5ef2, + 0x7be1ef5, + 0x7bedef8, + 0x7bf9efb, + 0x7c05efe, + 0x7c11f01, + 0x7c1df04, + 0x7c29f07, + 0x7c2df0a, + 0x7c39f0b, + 0x7c51f0e, + 0x7c55f14, + 0x7c65f15, + 0x7c7df19, + 0x7cc1f1f, + 0x7cd5f30, + 0x7d09f35, + 0x7d19f42, + 0x7d35f46, + 0x7d4df4d, + 0x7d51f53, + 0x27d95f54, + 0x7d99f65, + 0x7dc5f66, } -// max children 417 (capacity 511) -// max text offset 27680 (capacity 32767) +// max children 421 (capacity 511) +// max text offset 27811 (capacity 32767) // max text length 36 (capacity 63) -// max hi 8029 (capacity 16383) -// max lo 8018 (capacity 16383) +// max hi 8049 (capacity 16383) +// max lo 8038 (capacity 16383) diff --git a/vendor/golang.org/x/net/publicsuffix/table_test.go b/vendor/golang.org/x/net/publicsuffix/table_test.go index 8830b09f..2c974762 100644 --- a/vendor/golang.org/x/net/publicsuffix/table_test.go +++ b/vendor/golang.org/x/net/publicsuffix/table_test.go @@ -215,16 +215,12 @@ var rules = [...]string{ "pro.az", "biz.az", "ba", - "org.ba", - "net.ba", + "com.ba", "edu.ba", "gov.ba", "mil.ba", - "unsa.ba", - "unbi.ba", - "co.ba", - "com.ba", - "rs.ba", + "net.ba", + "org.ba", "bb", "biz.bb", "co.bb", @@ -2215,7 +2211,6 @@ var rules = [...]string{ "kamiamakusa.kumamoto.jp", "kashima.kumamoto.jp", "kikuchi.kumamoto.jp", - "kosa.kumamoto.jp", "kumamoto.kumamoto.jp", "mashiki.kumamoto.jp", "mifune.kumamoto.jp", @@ -7286,26 +7281,27 @@ var rules = [...]string{ "zippo", "zone", "zuerich", + "beep.pl", "*.compute.estate", "*.alces.network", "cloudfront.net", + "compute.amazonaws.com", "ap-northeast-1.compute.amazonaws.com", "ap-northeast-2.compute.amazonaws.com", "ap-southeast-1.compute.amazonaws.com", "ap-southeast-2.compute.amazonaws.com", - "cn-north-1.compute.amazonaws.cn", - "compute-1.amazonaws.com", - "compute.amazonaws.cn", - "compute.amazonaws.com", "eu-central-1.compute.amazonaws.com", "eu-west-1.compute.amazonaws.com", "sa-east-1.compute.amazonaws.com", - "us-east-1.amazonaws.com", "us-gov-west-1.compute.amazonaws.com", "us-west-1.compute.amazonaws.com", "us-west-2.compute.amazonaws.com", + "us-east-1.amazonaws.com", + "compute-1.amazonaws.com", "z-1.compute-1.amazonaws.com", "z-2.compute-1.amazonaws.com", + "compute.amazonaws.com.cn", + "cn-north-1.compute.amazonaws.com.cn", "elasticbeanstalk.com", "elb.amazonaws.com", "s3.amazonaws.com", @@ -7326,8 +7322,14 @@ var rules = [...]string{ "s3.cn-north-1.amazonaws.com.cn", "s3.eu-central-1.amazonaws.com", "on-aptible.com", + "potager.org", + "poivron.org", + "sweetpepper.org", + "pimienta.org", "myfritz.net", "betainabox.com", + "boxfuse.io", + "mycd.eu", "ae.org", "ar.com", "br.com", @@ -7362,7 +7364,9 @@ var rules = [...]string{ "us.org", "co.com", "c.la", + "certmgr.org", "xenapponazure.com", + "virtueeldomein.nl", "cloudcontrolled.com", "cloudcontrolapp.com", "co.ca", @@ -7375,6 +7379,8 @@ var rules = [...]string{ "co.nl", "co.no", "*.platform.sh", + "realm.cz", + "*.cryptonomic.net", "cupcake.is", "cyon.link", "cyon.site", @@ -7728,12 +7734,17 @@ var rules = [...]string{ "tr.eu.org", "uk.eu.org", "us.eu.org", + "eu-1.evennode.com", + "eu-2.evennode.com", + "us-1.evennode.com", + "us-2.evennode.com", "apps.fbsbx.com", "a.ssl.fastly.net", "b.ssl.fastly.net", "global.ssl.fastly.net", "a.prod.fastly.net", "global.prod.fastly.net", + "fhapp.xyz", "firebaseapp.com", "flynnhub.com", "freebox-os.com", @@ -7836,11 +7847,16 @@ var rules = [...]string{ "withgoogle.com", "withyoutube.com", "hashbang.sh", + "hasura-app.io", + "hepforge.org", "herokuapp.com", "herokussl.com", "iki.fi", "biz.at", "info.at", + "*.magentosite.cloud", + "meteorapp.com", + "eu.meteorapp.com", "co.pl", "azurewebsites.net", "azure-mobile.net", @@ -7962,9 +7978,12 @@ var rules = [...]string{ "rhcloud.com", "hzc.io", "sandcats.io", + "logoip.de", + "logoip.com", "biz.ua", "co.ua", "pp.ua", + "myshopblocks.com", "sinaapp.com", "vipsinaapp.com", "1kapp.com", @@ -7992,6 +8011,7 @@ var rules = [...]string{ "sopot.pl", "bloxcms.com", "townnews-staging.com", + "tuxfamily.org", "hk.com", "hk.org", "ltd.hk", @@ -9756,16 +9776,12 @@ var nodeLabels = [...]string{ "pp", "pro", "blogspot", - "co", "com", "edu", "gov", "mil", "net", "org", - "rs", - "unbi", - "unsa", "biz", "co", "com", @@ -9997,13 +10013,13 @@ var nodeLabels = [...]string{ "gob", "gov", "mil", + "magentosite", "co", "com", "gov", "net", "ac", "ah", - "amazonaws", "bj", "com", "cq", @@ -10046,11 +10062,11 @@ var nodeLabels = [...]string{ "xz", "yn", "zj", - "compute", - "cn-north-1", "amazonaws", "cn-north-1", + "compute", "s3", + "cn-north-1", "arts", "com", "edu", @@ -10122,6 +10138,7 @@ var nodeLabels = [...]string{ "est-le-patron", "est-mon-blogueur", "eu", + "evennode", "familyds", "fbsbx", "firebaseapp", @@ -10259,10 +10276,13 @@ var nodeLabels = [...]string{ "kr", "likes-pie", "likescandy", + "logoip", + "meteorapp", "mex", "myactivedirectory", "mydrobo", "mysecuritycamera", + "myshopblocks", "myvnc", "neat-url", "net-freaks", @@ -10361,10 +10381,15 @@ var nodeLabels = [...]string{ "s3", "alpha", "beta", + "eu-1", + "eu-2", + "us-1", + "us-2", "apps", "api", "ext", "gist", + "eu", "xen", "ac", "co", @@ -10403,6 +10428,7 @@ var nodeLabels = [...]string{ "blogspot", "co", "e4", + "realm", "blogspot", "com", "dnshome", @@ -10412,6 +10438,7 @@ var nodeLabels = [...]string{ "istmein", "lebtimnetz", "leitungsen", + "logoip", "traeumtgerade", "biz", "blogspot", @@ -10490,6 +10517,7 @@ var nodeLabels = [...]string{ "name", "net", "org", + "mycd", "aland", "blogspot", "dy", @@ -10724,9 +10752,11 @@ var nodeLabels = [...]string{ "selfip", "webhop", "eu", + "boxfuse", "com", "dedyn", "github", + "hasura-app", "hzc", "ngrok", "nid", @@ -12057,7 +12087,6 @@ var nodeLabels = [...]string{ "kamiamakusa", "kashima", "kikuchi", - "kosa", "kumamoto", "mashiki", "mifune", @@ -13786,6 +13815,7 @@ var nodeLabels = [...]string{ "cloudapp", "cloudfront", "cloudfunctions", + "cryptonomic", "ddns", "dnsalias", "dnsdojo", @@ -13892,6 +13922,7 @@ var nodeLabels = [...]string{ "blogspot", "bv", "co", + "virtueeldomein", "aa", "aarborte", "aejrie", @@ -14702,6 +14733,7 @@ var nodeLabels = [...]string{ "cable-modem", "cdn77", "cdn77-secure", + "certmgr", "collegefan", "couchpotatofries", "dnsalias", @@ -14721,6 +14753,7 @@ var nodeLabels = [...]string{ "from-me", "game-host", "gotdns", + "hepforge", "hk", "hobby-site", "homedns", @@ -14753,7 +14786,10 @@ var nodeLabels = [...]string{ "mysecuritycamera", "nflfan", "no-ip", + "pimienta", "podzone", + "poivron", + "potager", "read-books", "readmyblog", "selfip", @@ -14762,7 +14798,9 @@ var nodeLabels = [...]string{ "serveftp", "servegame", "stuff-4-sale", + "sweetpepper", "tunk", + "tuxfamily", "ufcfan", "us", "webhop", @@ -14882,6 +14920,7 @@ var nodeLabels = [...]string{ "auto", "babia-gora", "bedzin", + "beep", "beskidy", "bialowieza", "bialystok", @@ -16003,6 +16042,7 @@ var nodeLabels = [...]string{ "xn--d1at", "xn--o1ac", "xn--o1ach", + "fhapp", "ac", "agric", "alt", diff --git a/vendor/golang.org/x/net/route/address.go b/vendor/golang.org/x/net/route/address.go index 206a8371..a56909c1 100644 --- a/vendor/golang.org/x/net/route/address.go +++ b/vendor/golang.org/x/net/route/address.go @@ -234,7 +234,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] case sysAF_INET, sysAF_INET6: af = int(b[1]) a, err := parseInetAddr(af, b) @@ -242,7 +246,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] default: l, a, err := fn(af, b) if err != nil { @@ -262,7 +270,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] } } return as[:], nil diff --git a/vendor/golang.org/x/net/route/interface_freebsd.go b/vendor/golang.org/x/net/route/interface_freebsd.go index c8305391..9f6f50c0 100644 --- a/vendor/golang.org/x/net/route/interface_freebsd.go +++ b/vendor/golang.org/x/net/route/interface_freebsd.go @@ -13,12 +13,12 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro extOff = int(nativeEndian.Uint16(b[18:20])) bodyOff = int(nativeEndian.Uint16(b[16:18])) } else { - if len(b) < w.bodyOff { - return nil, errMessageTooShort - } extOff = w.extOff bodyOff = w.bodyOff } + if len(b) < extOff || len(b) < bodyOff { + return nil, errInvalidMessage + } l := int(nativeEndian.Uint16(b[:2])) if len(b) < l { return nil, errInvalidMessage @@ -53,11 +53,11 @@ func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, } bodyOff = int(nativeEndian.Uint16(b[16:18])) } else { - if len(b) < w.bodyOff { - return nil, errMessageTooShort - } bodyOff = w.bodyOff } + if len(b) < bodyOff { + return nil, errInvalidMessage + } l := int(nativeEndian.Uint16(b[:2])) if len(b) < l { return nil, errInvalidMessage diff --git a/vendor/golang.org/x/net/route/interface_openbsd.go b/vendor/golang.org/x/net/route/interface_openbsd.go index 24451d8c..e4a143c1 100644 --- a/vendor/golang.org/x/net/route/interface_openbsd.go +++ b/vendor/golang.org/x/net/route/interface_openbsd.go @@ -24,7 +24,11 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { Addrs: make([]Addr, sysRTAX_MAX), raw: b[:l], } - a, err := parseLinkAddr(b[int(nativeEndian.Uint16(b[4:6])):]) + ll := int(nativeEndian.Uint16(b[4:6])) + if len(b) < ll { + return nil, errInvalidMessage + } + a, err := parseLinkAddr(b[ll:]) if err != nil { return nil, err } @@ -42,6 +46,9 @@ func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, erro return nil, errInvalidMessage } bodyOff := int(nativeEndian.Uint16(b[4:6])) + if len(b) < bodyOff { + return nil, errInvalidMessage + } m := &InterfaceAddrMessage{ Version: int(b[2]), Type: int(b[3]), diff --git a/vendor/golang.org/x/net/route/message.go b/vendor/golang.org/x/net/route/message.go index 27cbf6b7..d7ae0eb5 100644 --- a/vendor/golang.org/x/net/route/message.go +++ b/vendor/golang.org/x/net/route/message.go @@ -42,6 +42,12 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) { for len(b) > 4 { nmsgs++ l := int(nativeEndian.Uint16(b[:2])) + if l == 0 { + return nil, errInvalidMessage + } + if len(b) < l { + return nil, errMessageTooShort + } if b[2] != sysRTM_VERSION { b = b[l:] continue diff --git a/vendor/golang.org/x/net/route/message_test.go b/vendor/golang.org/x/net/route/message_test.go index a1263d8f..c0c7c57a 100644 --- a/vendor/golang.org/x/net/route/message_test.go +++ b/vendor/golang.org/x/net/route/message_test.go @@ -93,3 +93,26 @@ func TestMonitorAndParseRIB(t *testing.T) { time.Sleep(200 * time.Millisecond) } } + +func TestParseRIBWithFuzz(t *testing.T) { + for _, fuzz := range []string{ + "0\x00\x05\x050000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "0000000000000\x02000000" + + "00000000", + "\x02\x00\x05\f0000000000000000" + + "0\x0200000000000000", + "\x02\x00\x05\x100000000000000\x1200" + + "0\x00\xff\x00", + "\x02\x00\x05\f0000000000000000" + + "0\x12000\x00\x02\x0000", + "\x00\x00\x00\x01\x00", + "00000", + } { + for typ := RIBType(0); typ < 256; typ++ { + ParseRIB(typ, []byte(fuzz)) + } + } +} diff --git a/vendor/golang.org/x/net/route/route_openbsd.go b/vendor/golang.org/x/net/route/route_openbsd.go index b07862f0..76eae40d 100644 --- a/vendor/golang.org/x/net/route/route_openbsd.go +++ b/vendor/golang.org/x/net/route/route_openbsd.go @@ -19,7 +19,11 @@ func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) { Index: int(nativeEndian.Uint16(b[6:8])), raw: b[:l], } - as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[int(nativeEndian.Uint16(b[4:6])):]) + ll := int(nativeEndian.Uint16(b[4:6])) + if len(b) < ll { + return nil, errInvalidMessage + } + as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:]) if err != nil { return nil, err } diff --git a/vendor/golang.org/x/net/webdav/file_test.go b/vendor/golang.org/x/net/webdav/file_test.go index 7ce6c127..cbd0240a 100644 --- a/vendor/golang.org/x/net/webdav/file_test.go +++ b/vendor/golang.org/x/net/webdav/file_test.go @@ -786,6 +786,9 @@ func TestMemFile(t *testing.T) { // memFile doesn't allocate a new buffer for each of those N times. Otherwise, // calling io.Copy(aMemFile, src) is likely to have quadratic complexity. func TestMemFileWriteAllocs(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gccgo allocates here") + } fs := NewMemFS() f, err := fs.OpenFile("/xxx", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { diff --git a/vendor/google.golang.org/grpc/.travis.yml b/vendor/google.golang.org/grpc/.travis.yml new file mode 100644 index 00000000..9bc2c127 --- /dev/null +++ b/vendor/google.golang.org/grpc/.travis.yml @@ -0,0 +1,17 @@ +language: go + +go: + - 1.5.3 + - 1.6 + +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover + +install: + - mkdir -p "$GOPATH/src/google.golang.org" + - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/google.golang.org/grpc" + +script: + - make test testrace diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md new file mode 100644 index 00000000..36cd6f75 --- /dev/null +++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# How to contribute + +We definitely welcome patches and contribution to grpc! Here are some guidelines +and information about how to do so. + +## Sending patches + +### Getting started + +1. Check out the code: + + $ go get google.golang.org/grpc + $ cd $GOPATH/src/google.golang.org/grpc + +1. Create a fork of the grpc-go repository. +1. Add your fork as a remote: + + $ git remote add fork git@github.com:$YOURGITHUBUSERNAME/grpc-go.git + +1. Make changes, commit them. +1. Run the test suite: + + $ make test + +1. Push your changes to your fork: + + $ git push fork ... + +1. Open a pull request. + +## Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +## Filing Issues +When filing an issue, make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +### Contributing code +Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. diff --git a/vendor/google.golang.org/grpc/Documentation/grpc-auth-support.md b/vendor/google.golang.org/grpc/Documentation/grpc-auth-support.md new file mode 100644 index 00000000..5312b572 --- /dev/null +++ b/vendor/google.golang.org/grpc/Documentation/grpc-auth-support.md @@ -0,0 +1,41 @@ +# Authentication + +As outlined in the [gRPC authentication guide](http://www.grpc.io/docs/guides/auth.html) there are a number of different mechanisms for asserting identity between an client and server. We'll present some code-samples here demonstrating how to provide TLS support encryption and identity assertions as well as passing OAuth2 tokens to services that support it. + +# Enabling TLS on a gRPC client + +```Go +conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""))) +``` + +# Enabling TLS on a gRPC server + +```Go +creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) +if err != nil { + log.Fatalf("Failed to generate credentials %v", err) +} +lis, err := net.Listen("tcp", ":0") +server := grpc.NewServer(grpc.Creds(creds)) +... +server.Serve(lis) +``` + +# Authenticating with Google + +## Google Compute Engine (GCE) + +```Go +conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""), grpc.WithPerRPCCredentials(oauth.NewComputeEngine()))) +``` + +## JWT + +```Go +jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope) +if err != nil { + log.Fatalf("Failed to create JWT credentials: %v", err) +} +conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""), grpc.WithPerRPCCredentials(jwtCreds))) +``` + diff --git a/vendor/google.golang.org/grpc/Documentation/grpc-metadata.md b/vendor/google.golang.org/grpc/Documentation/grpc-metadata.md new file mode 100644 index 00000000..928f5572 --- /dev/null +++ b/vendor/google.golang.org/grpc/Documentation/grpc-metadata.md @@ -0,0 +1,201 @@ +# Metadata + +gRPC supports sending metadata between client and server. +This doc shows how to send and receive metadata in gRPC-go. + +## Background + +Four kinds of service method: + +- [Unary RPC](http://www.grpc.io/docs/guides/concepts.html#unary-rpc) +- [Server streaming RPC](http://www.grpc.io/docs/guides/concepts.html#server-streaming-rpc) +- [Client streaming RPC](http://www.grpc.io/docs/guides/concepts.html#client-streaming-rpc) +- [Bidirectional streaming RPC](http://www.grpc.io/docs/guides/concepts.html#bidirectional-streaming-rpc) + +And concept of [metadata](http://www.grpc.io/docs/guides/concepts.html#metadata). + +## Constructing metadata + +A metadata can be created using package [metadata](https://godoc.org/google.golang.org/grpc/metadata). +The type MD is actually a map from string to a list of strings: + +```go +type MD map[string][]string +``` + +Metadata can be read like a normal map. +Note that the value type of this map is `[]string`, +so that users can attach multiple values using a single key. + +### Creating a new metadata + +A metadata can be created from a `map[string]string` using function `New`: + +```go +md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"}) +``` + +Another way is to use `Pairs`. +Values with the same key will be merged into a list: + +```go +md := metadata.Pairs( + "key1", "val1", + "key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"} + "key2", "val2", +) +``` + +__Note:__ all the keys will be automatically converted to lowercase, +so "key1" and "kEy1" will be the same key and their values will be merged into the same list. +This happens for both `New` and `Pairs`. + +### Storing binary data in metadata + +In metadata, keys are always strings. But values can be strings or binary data. +To store binary data value in metadata, simply add "-bin" surfix to the key. +The values with "-bin" surffixed keys will be encoded when creating the metadata: + +```go +md := metadata.Pairs( + "key", "string value", + "key-bin", string([]byte{96, 102}), // this binary data will be encoded (base64) before sending + // and will be decoded after being transferred. +) +``` + +## Retrieving metadata from context + +Metadata can be retrieved from context using `FromContext`: + +```go +func (s *server) SomeRPC(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) { + md, ok := metadata.FromContext(ctx) + // do something with metadata +} +``` + +## Sending and receiving metadata - client side + +[//]: # "TODO: uncomment next line after example source added" +[//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)." + +### Sending metadata + +To send metadata to server, the client can wrap the metadata into a context using `NewContext`, and make the RPC with this context: + +```go +md := metadata.Pairs("key", "val") + +// create a new context with this metadata +ctx := metadata.NewContext(context.Background(), md) + +// make unary RPC +response, err := client.SomeRPC(ctx, someRequest) + +// or make streaming RPC +stream, err := client.SomeStreamingRPC(ctx) +``` +### Receiving metadata + +Metadata that a client can receive includes header and trailer. + +#### Unary call + +Header and trailer sent along with a unary call can be retrieved using function [Header](https://godoc.org/google.golang.org/grpc#Header) and [Trailer](https://godoc.org/google.golang.org/grpc#Trailer) in [CallOption](https://godoc.org/google.golang.org/grpc#CallOption): + +```go +var header, trailer metadata.MD // variable to store header and trailer +r, err := client.SomeRPC( + ctx, + someRequest, + grpc.Header(&header), // will retrieve header + grpc.Trailer(&trailer), // will retrieve trailer +) + +// do something with header and trailer +``` + +#### Streaming call + +For streaming calls including: + +- Server streaming RPC +- Client streaming RPC +- Bidirectional streaming RPC + +Header and trailer can be retrieved from the returned stream using function `Header` and `Trailer` in interface [ClientStream](https://godoc.org/google.golang.org/grpc#ClientStream): + +```go +stream, err := client.SomeStreamingRPC(ctx) + +// retrieve header +header, err := stream.Header() + +// retrieve trailer +trailer := stream.Trailer() + +``` + +## Sending and receiving metadata - server side + +[//]: # "TODO: uncomment next line after example source added" +[//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)." + +### Receiving metadata + +To read metadata sent by the client, the server needs to retrieve it from RPC context. +If it is a unary call, the RPC handler's context can be used. +For streaming calls, the server needs to get context from the stream. + +#### Unary call + +```go +func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) { + md, ok := metadata.FromContext(ctx) + // do something with metadata +} +``` + +#### Streaming call + +```go +func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error { + md, ok := metadata.FromContext(stream.Context()) // get context from stream + // do something with metadata +} +``` + +### Sending metadata + +#### Unary call + +To send header and trailer to client in unary call, the server can call [SendHeader](https://godoc.org/google.golang.org/grpc#SendHeader) and [SetTrailer](https://godoc.org/google.golang.org/grpc#SetTrailer) functions in module [grpc](https://godoc.org/google.golang.org/grpc). +These two functions take a context as the first parameter. +It should be the RPC handler's context or one derived from it: + +```go +func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) { + // create and send header + header := metadata.Pairs("header-key", "val") + grpc.SendHeader(ctx, header) + // create and set trailer + trailer := metadata.Pairs("trailer-key", "val") + grpc.SetTrailer(ctx, trailer) +} +``` + +#### Streaming call + +For streaming calls, header and trailer can be sent using function `SendHeader` and `SetTrailer` in interface [ServerStream](https://godoc.org/google.golang.org/grpc#ServerStream): + +```go +func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error { + // create and send header + header := metadata.Pairs("header-key", "val") + stream.SendHeader(header) + // create and set trailer + trailer := metadata.Pairs("trailer-key", "val") + stream.SetTrailer(trailer) +} +``` diff --git a/vendor/google.golang.org/grpc/LICENSE b/vendor/google.golang.org/grpc/LICENSE new file mode 100644 index 00000000..f4988b45 --- /dev/null +++ b/vendor/google.golang.org/grpc/LICENSE @@ -0,0 +1,28 @@ +Copyright 2014, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/google.golang.org/grpc/Makefile b/vendor/google.golang.org/grpc/Makefile new file mode 100644 index 00000000..03bb01f0 --- /dev/null +++ b/vendor/google.golang.org/grpc/Makefile @@ -0,0 +1,52 @@ +all: test testrace + +deps: + go get -d -v google.golang.org/grpc/... + +updatedeps: + go get -d -v -u -f google.golang.org/grpc/... + +testdeps: + go get -d -v -t google.golang.org/grpc/... + +updatetestdeps: + go get -d -v -t -u -f google.golang.org/grpc/... + +build: deps + go build google.golang.org/grpc/... + +proto: + @ if ! which protoc > /dev/null; then \ + echo "error: protoc not installed" >&2; \ + exit 1; \ + fi + go get -u -v github.com/golang/protobuf/protoc-gen-go + # use $$dir as the root for all proto files in the same directory + for dir in $$(git ls-files '*.proto' | xargs -n1 dirname | uniq); do \ + protoc -I $$dir --go_out=plugins=grpc:$$dir $$dir/*.proto; \ + done + +test: testdeps + go test -v -cpu 1,4 google.golang.org/grpc/... + +testrace: testdeps + go test -v -race -cpu 1,4 google.golang.org/grpc/... + +clean: + go clean -i google.golang.org/grpc/... + +coverage: testdeps + ./coverage.sh --coveralls + +.PHONY: \ + all \ + deps \ + updatedeps \ + testdeps \ + updatetestdeps \ + build \ + proto \ + test \ + testrace \ + clean \ + coverage diff --git a/vendor/google.golang.org/grpc/PATENTS b/vendor/google.golang.org/grpc/PATENTS new file mode 100644 index 00000000..69b47959 --- /dev/null +++ b/vendor/google.golang.org/grpc/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the gRPC project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of gRPC, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of gRPC. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of gRPC or any code incorporated within this +implementation of gRPC constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of gRPC +shall terminate as of the date such litigation is filed. diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md new file mode 100644 index 00000000..90e9453d --- /dev/null +++ b/vendor/google.golang.org/grpc/README.md @@ -0,0 +1,32 @@ +#gRPC-Go + +[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) + +The Go implementation of [gRPC](http://www.grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start](http://www.grpc.io/docs/) guide. + +Installation +------------ + +To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run: + +``` +$ go get google.golang.org/grpc +``` + +Prerequisites +------------- + +This requires Go 1.5 or later . + +Constraints +----------- +The grpc package should only depend on standard Go packages and a small number of exceptions. If your contribution introduces new dependencies which are NOT in the [list](http://godoc.org/google.golang.org/grpc?imports), you need a discussion with gRPC-Go authors and consultants. + +Documentation +------------- +See [API documentation](https://godoc.org/google.golang.org/grpc) for package and API descriptions and find examples in the [examples directory](examples/). + +Status +------ +Beta release + diff --git a/vendor/google.golang.org/grpc/backoff.go b/vendor/google.golang.org/grpc/backoff.go new file mode 100644 index 00000000..52f4f10f --- /dev/null +++ b/vendor/google.golang.org/grpc/backoff.go @@ -0,0 +1,80 @@ +package grpc + +import ( + "math/rand" + "time" +) + +// DefaultBackoffConfig uses values specified for backoff in +// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. +var ( + DefaultBackoffConfig = BackoffConfig{ + MaxDelay: 120 * time.Second, + baseDelay: 1.0 * time.Second, + factor: 1.6, + jitter: 0.2, + } +) + +// backoffStrategy defines the methodology for backing off after a grpc +// connection failure. +// +// This is unexported until the gRPC project decides whether or not to allow +// alternative backoff strategies. Once a decision is made, this type and its +// method may be exported. +type backoffStrategy interface { + // backoff returns the amount of time to wait before the next retry given + // the number of consecutive failures. + backoff(retries int) time.Duration +} + +// BackoffConfig defines the parameters for the default gRPC backoff strategy. +type BackoffConfig struct { + // MaxDelay is the upper bound of backoff delay. + MaxDelay time.Duration + + // TODO(stevvooe): The following fields are not exported, as allowing + // changes would violate the current gRPC specification for backoff. If + // gRPC decides to allow more interesting backoff strategies, these fields + // may be opened up in the future. + + // baseDelay is the amount of time to wait before retrying after the first + // failure. + baseDelay time.Duration + + // factor is applied to the backoff after each retry. + factor float64 + + // jitter provides a range to randomize backoff delays. + jitter float64 +} + +func setDefaults(bc *BackoffConfig) { + md := bc.MaxDelay + *bc = DefaultBackoffConfig + + if md > 0 { + bc.MaxDelay = md + } +} + +func (bc BackoffConfig) backoff(retries int) (t time.Duration) { + if retries == 0 { + return bc.baseDelay + } + backoff, max := float64(bc.baseDelay), float64(bc.MaxDelay) + for backoff < max && retries > 0 { + backoff *= bc.factor + retries-- + } + if backoff > max { + backoff = max + } + // Randomize backoff delays so that if a cluster of requests start at + // the same time, they won't operate in lockstep. + backoff *= 1 + bc.jitter*(rand.Float64()*2-1) + if backoff < 0 { + return 0 + } + return time.Duration(backoff) +} diff --git a/vendor/google.golang.org/grpc/backoff_test.go b/vendor/google.golang.org/grpc/backoff_test.go new file mode 100644 index 00000000..bfca7b17 --- /dev/null +++ b/vendor/google.golang.org/grpc/backoff_test.go @@ -0,0 +1,11 @@ +package grpc + +import "testing" + +func TestBackoffConfigDefaults(t *testing.T) { + b := BackoffConfig{} + setDefaults(&b) + if b != DefaultBackoffConfig { + t.Fatalf("expected BackoffConfig to pickup default parameters: %v != %v", b, DefaultBackoffConfig) + } +} diff --git a/vendor/google.golang.org/grpc/balancer.go b/vendor/google.golang.org/grpc/balancer.go new file mode 100644 index 00000000..419e2146 --- /dev/null +++ b/vendor/google.golang.org/grpc/balancer.go @@ -0,0 +1,385 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "fmt" + "sync" + + "golang.org/x/net/context" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/naming" +) + +// Address represents a server the client connects to. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type Address struct { + // Addr is the server address on which a connection will be established. + Addr string + // Metadata is the information associated with Addr, which may be used + // to make load balancing decision. + Metadata interface{} +} + +// BalancerGetOptions configures a Get call. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type BalancerGetOptions struct { + // BlockingWait specifies whether Get should block when there is no + // connected address. + BlockingWait bool +} + +// Balancer chooses network addresses for RPCs. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type Balancer interface { + // Start does the initialization work to bootstrap a Balancer. For example, + // this function may start the name resolution and watch the updates. It will + // be called when dialing. + Start(target string) error + // Up informs the Balancer that gRPC has a connection to the server at + // addr. It returns down which is called once the connection to addr gets + // lost or closed. + // TODO: It is not clear how to construct and take advantage the meaningful error + // parameter for down. Need realistic demands to guide. + Up(addr Address) (down func(error)) + // Get gets the address of a server for the RPC corresponding to ctx. + // i) If it returns a connected address, gRPC internals issues the RPC on the + // connection to this address; + // ii) If it returns an address on which the connection is under construction + // (initiated by Notify(...)) but not connected, gRPC internals + // * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or + // Shutdown state; + // or + // * issues RPC on the connection otherwise. + // iii) If it returns an address on which the connection does not exist, gRPC + // internals treats it as an error and will fail the corresponding RPC. + // + // Therefore, the following is the recommended rule when writing a custom Balancer. + // If opts.BlockingWait is true, it should return a connected address or + // block if there is no connected address. It should respect the timeout or + // cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast + // RPCs), it should return an address it has notified via Notify(...) immediately + // instead of blocking. + // + // The function returns put which is called once the rpc has completed or failed. + // put can collect and report RPC stats to a remote load balancer. + // + // This function should only return the errors Balancer cannot recover by itself. + // gRPC internals will fail the RPC if an error is returned. + Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) + // Notify returns a channel that is used by gRPC internals to watch the addresses + // gRPC needs to connect. The addresses might be from a name resolver or remote + // load balancer. gRPC internals will compare it with the existing connected + // addresses. If the address Balancer notified is not in the existing connected + // addresses, gRPC starts to connect the address. If an address in the existing + // connected addresses is not in the notification list, the corresponding connection + // is shutdown gracefully. Otherwise, there are no operations to take. Note that + // the Address slice must be the full list of the Addresses which should be connected. + // It is NOT delta. + Notify() <-chan []Address + // Close shuts down the balancer. + Close() error +} + +// downErr implements net.Error. It is constructed by gRPC internals and passed to the down +// call of Balancer. +type downErr struct { + timeout bool + temporary bool + desc string +} + +func (e downErr) Error() string { return e.desc } +func (e downErr) Timeout() bool { return e.timeout } +func (e downErr) Temporary() bool { return e.temporary } + +func downErrorf(timeout, temporary bool, format string, a ...interface{}) downErr { + return downErr{ + timeout: timeout, + temporary: temporary, + desc: fmt.Sprintf(format, a...), + } +} + +// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch +// the name resolution updates and updates the addresses available correspondingly. +func RoundRobin(r naming.Resolver) Balancer { + return &roundRobin{r: r} +} + +type addrInfo struct { + addr Address + connected bool +} + +type roundRobin struct { + r naming.Resolver + w naming.Watcher + addrs []*addrInfo // all the addresses the client should potentially connect + mu sync.Mutex + addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to. + next int // index of the next address to return for Get() + waitCh chan struct{} // the channel to block when there is no connected address available + done bool // The Balancer is closed. +} + +func (rr *roundRobin) watchAddrUpdates() error { + updates, err := rr.w.Next() + if err != nil { + grpclog.Printf("grpc: the naming watcher stops working due to %v.\n", err) + return err + } + rr.mu.Lock() + defer rr.mu.Unlock() + for _, update := range updates { + addr := Address{ + Addr: update.Addr, + Metadata: update.Metadata, + } + switch update.Op { + case naming.Add: + var exist bool + for _, v := range rr.addrs { + if addr == v.addr { + exist = true + grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr) + break + } + } + if exist { + continue + } + rr.addrs = append(rr.addrs, &addrInfo{addr: addr}) + case naming.Delete: + for i, v := range rr.addrs { + if addr == v.addr { + copy(rr.addrs[i:], rr.addrs[i+1:]) + rr.addrs = rr.addrs[:len(rr.addrs)-1] + break + } + } + default: + grpclog.Println("Unknown update.Op ", update.Op) + } + } + // Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified. + open := make([]Address, len(rr.addrs)) + for i, v := range rr.addrs { + open[i] = v.addr + } + if rr.done { + return ErrClientConnClosing + } + rr.addrCh <- open + return nil +} + +func (rr *roundRobin) Start(target string) error { + if rr.r == nil { + // If there is no name resolver installed, it is not needed to + // do name resolution. In this case, target is added into rr.addrs + // as the only address available and rr.addrCh stays nil. + rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}}) + return nil + } + w, err := rr.r.Resolve(target) + if err != nil { + return err + } + rr.w = w + rr.addrCh = make(chan []Address) + go func() { + for { + if err := rr.watchAddrUpdates(); err != nil { + return + } + } + }() + return nil +} + +// Up sets the connected state of addr and sends notification if there are pending +// Get() calls. +func (rr *roundRobin) Up(addr Address) func(error) { + rr.mu.Lock() + defer rr.mu.Unlock() + var cnt int + for _, a := range rr.addrs { + if a.addr == addr { + if a.connected { + return nil + } + a.connected = true + } + if a.connected { + cnt++ + } + } + // addr is only one which is connected. Notify the Get() callers who are blocking. + if cnt == 1 && rr.waitCh != nil { + close(rr.waitCh) + rr.waitCh = nil + } + return func(err error) { + rr.down(addr, err) + } +} + +// down unsets the connected state of addr. +func (rr *roundRobin) down(addr Address, err error) { + rr.mu.Lock() + defer rr.mu.Unlock() + for _, a := range rr.addrs { + if addr == a.addr { + a.connected = false + break + } + } +} + +// Get returns the next addr in the rotation. +func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) { + var ch chan struct{} + rr.mu.Lock() + if rr.done { + rr.mu.Unlock() + err = ErrClientConnClosing + return + } + + if len(rr.addrs) > 0 { + if rr.next >= len(rr.addrs) { + rr.next = 0 + } + next := rr.next + for { + a := rr.addrs[next] + next = (next + 1) % len(rr.addrs) + if a.connected { + addr = a.addr + rr.next = next + rr.mu.Unlock() + return + } + if next == rr.next { + // Has iterated all the possible address but none is connected. + break + } + } + } + if !opts.BlockingWait { + if len(rr.addrs) == 0 { + rr.mu.Unlock() + err = fmt.Errorf("there is no address available") + return + } + // Returns the next addr on rr.addrs for failfast RPCs. + addr = rr.addrs[rr.next].addr + rr.next++ + rr.mu.Unlock() + return + } + // Wait on rr.waitCh for non-failfast RPCs. + if rr.waitCh == nil { + ch = make(chan struct{}) + rr.waitCh = ch + } else { + ch = rr.waitCh + } + rr.mu.Unlock() + for { + select { + case <-ctx.Done(): + err = ctx.Err() + return + case <-ch: + rr.mu.Lock() + if rr.done { + rr.mu.Unlock() + err = ErrClientConnClosing + return + } + + if len(rr.addrs) > 0 { + if rr.next >= len(rr.addrs) { + rr.next = 0 + } + next := rr.next + for { + a := rr.addrs[next] + next = (next + 1) % len(rr.addrs) + if a.connected { + addr = a.addr + rr.next = next + rr.mu.Unlock() + return + } + if next == rr.next { + // Has iterated all the possible address but none is connected. + break + } + } + } + // The newly added addr got removed by Down() again. + if rr.waitCh == nil { + ch = make(chan struct{}) + rr.waitCh = ch + } else { + ch = rr.waitCh + } + rr.mu.Unlock() + } + } +} + +func (rr *roundRobin) Notify() <-chan []Address { + return rr.addrCh +} + +func (rr *roundRobin) Close() error { + rr.mu.Lock() + defer rr.mu.Unlock() + rr.done = true + if rr.w != nil { + rr.w.Close() + } + if rr.waitCh != nil { + close(rr.waitCh) + rr.waitCh = nil + } + if rr.addrCh != nil { + close(rr.addrCh) + } + return nil +} diff --git a/vendor/google.golang.org/grpc/balancer_test.go b/vendor/google.golang.org/grpc/balancer_test.go new file mode 100644 index 00000000..d0cf0611 --- /dev/null +++ b/vendor/google.golang.org/grpc/balancer_test.go @@ -0,0 +1,322 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "fmt" + "math" + "sync" + "testing" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/naming" +) + +type testWatcher struct { + // the channel to receives name resolution updates + update chan *naming.Update + // the side channel to get to know how many updates in a batch + side chan int + // the channel to notifiy update injector that the update reading is done + readDone chan int +} + +func (w *testWatcher) Next() (updates []*naming.Update, err error) { + n := <-w.side + if n == 0 { + return nil, fmt.Errorf("w.side is closed") + } + for i := 0; i < n; i++ { + u := <-w.update + if u != nil { + updates = append(updates, u) + } + } + w.readDone <- 0 + return +} + +func (w *testWatcher) Close() { +} + +// Inject naming resolution updates to the testWatcher. +func (w *testWatcher) inject(updates []*naming.Update) { + w.side <- len(updates) + for _, u := range updates { + w.update <- u + } + <-w.readDone +} + +type testNameResolver struct { + w *testWatcher + addr string +} + +func (r *testNameResolver) Resolve(target string) (naming.Watcher, error) { + r.w = &testWatcher{ + update: make(chan *naming.Update, 1), + side: make(chan int, 1), + readDone: make(chan int), + } + r.w.side <- 1 + r.w.update <- &naming.Update{ + Op: naming.Add, + Addr: r.addr, + } + go func() { + <-r.w.readDone + }() + return r.w, nil +} + +func startServers(t *testing.T, numServers int, maxStreams uint32) ([]*server, *testNameResolver) { + var servers []*server + for i := 0; i < numServers; i++ { + s := newTestServer() + servers = append(servers, s) + go s.start(t, 0, maxStreams) + s.wait(t, 2*time.Second) + } + // Point to server[0] + addr := "127.0.0.1:" + servers[0].port + return servers, &testNameResolver{ + addr: addr, + } +} + +func TestNameDiscovery(t *testing.T) { + // Start 2 servers on 2 ports. + numServers := 2 + servers, r := startServers(t, numServers, math.MaxUint32) + cc, err := Dial("foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + req := "port" + var reply string + if err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc); err == nil || ErrorDesc(err) != servers[0].port { + t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want %s", err, servers[0].port) + } + // Inject the name resolution change to remove servers[0] and add servers[1]. + var updates []*naming.Update + updates = append(updates, &naming.Update{ + Op: naming.Delete, + Addr: "127.0.0.1:" + servers[0].port, + }) + updates = append(updates, &naming.Update{ + Op: naming.Add, + Addr: "127.0.0.1:" + servers[1].port, + }) + r.w.inject(updates) + // Loop until the rpcs in flight talks to servers[1]. + for { + if err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc); err != nil && ErrorDesc(err) == servers[1].port { + break + } + time.Sleep(10 * time.Millisecond) + } + cc.Close() + for i := 0; i < numServers; i++ { + servers[i].stop() + } +} + +func TestEmptyAddrs(t *testing.T) { + servers, r := startServers(t, 1, math.MaxUint32) + cc, err := Dial("foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + var reply string + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc); err != nil || reply != expectedResponse { + t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, reply = %q, want %q, ", err, reply, expectedResponse) + } + // Inject name resolution change to remove the server so that there is no address + // available after that. + u := &naming.Update{ + Op: naming.Delete, + Addr: "127.0.0.1:" + servers[0].port, + } + r.w.inject([]*naming.Update{u}) + // Loop until the above updates apply. + for { + time.Sleep(10 * time.Millisecond) + ctx, _ := context.WithTimeout(context.Background(), 10*time.Millisecond) + if err := Invoke(ctx, "/foo/bar", &expectedRequest, &reply, cc); err != nil { + break + } + } + cc.Close() + servers[0].stop() +} + +func TestRoundRobin(t *testing.T) { + // Start 3 servers on 3 ports. + numServers := 3 + servers, r := startServers(t, numServers, math.MaxUint32) + cc, err := Dial("foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + // Add servers[1] to the service discovery. + u := &naming.Update{ + Op: naming.Add, + Addr: "127.0.0.1:" + servers[1].port, + } + r.w.inject([]*naming.Update{u}) + req := "port" + var reply string + // Loop until servers[1] is up + for { + if err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc); err != nil && ErrorDesc(err) == servers[1].port { + break + } + time.Sleep(10 * time.Millisecond) + } + // Add server2[2] to the service discovery. + u = &naming.Update{ + Op: naming.Add, + Addr: "127.0.0.1:" + servers[2].port, + } + r.w.inject([]*naming.Update{u}) + // Loop until both servers[2] are up. + for { + if err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc); err != nil && ErrorDesc(err) == servers[2].port { + break + } + time.Sleep(10 * time.Millisecond) + } + // Check the incoming RPCs served in a round-robin manner. + for i := 0; i < 10; i++ { + if err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc); err == nil || ErrorDesc(err) != servers[i%numServers].port { + t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", i, err, servers[i%numServers].port) + } + } + cc.Close() + for i := 0; i < numServers; i++ { + servers[i].stop() + } +} + +func TestCloseWithPendingRPC(t *testing.T) { + servers, r := startServers(t, 1, math.MaxUint32) + cc, err := Dial("foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + var reply string + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); err != nil { + t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want %s", err, servers[0].port) + } + // Remove the server. + updates := []*naming.Update{&naming.Update{ + Op: naming.Delete, + Addr: "127.0.0.1:" + servers[0].port, + }} + r.w.inject(updates) + // Loop until the above update applies. + for { + ctx, _ := context.WithTimeout(context.Background(), 10*time.Millisecond) + if err := Invoke(ctx, "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); Code(err) == codes.DeadlineExceeded { + break + } + time.Sleep(10 * time.Millisecond) + } + // Issue 2 RPCs which should be completed with error status once cc is closed. + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + var reply string + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); err == nil { + t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) + } + }() + go func() { + defer wg.Done() + var reply string + time.Sleep(5 * time.Millisecond) + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); err == nil { + t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) + } + }() + time.Sleep(5 * time.Millisecond) + cc.Close() + wg.Wait() + servers[0].stop() +} + +func TestGetOnWaitChannel(t *testing.T) { + servers, r := startServers(t, 1, math.MaxUint32) + cc, err := Dial("foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + // Remove all servers so that all upcoming RPCs will block on waitCh. + updates := []*naming.Update{&naming.Update{ + Op: naming.Delete, + Addr: "127.0.0.1:" + servers[0].port, + }} + r.w.inject(updates) + for { + var reply string + ctx, _ := context.WithTimeout(context.Background(), 10*time.Millisecond) + if err := Invoke(ctx, "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); Code(err) == codes.DeadlineExceeded { + break + } + time.Sleep(10 * time.Millisecond) + } + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + var reply string + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc, FailFast(false)); err != nil { + t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want ", err) + } + }() + // Add a connected server to get the above RPC through. + updates = []*naming.Update{&naming.Update{ + Op: naming.Add, + Addr: "127.0.0.1:" + servers[0].port, + }} + r.w.inject(updates) + // Wait until the above RPC succeeds. + wg.Wait() + cc.Close() + servers[0].stop() +} diff --git a/vendor/google.golang.org/grpc/benchmark/benchmark.go b/vendor/google.golang.org/grpc/benchmark/benchmark.go new file mode 100644 index 00000000..d1143270 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/benchmark.go @@ -0,0 +1,224 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* +Package benchmark implements the building blocks to setup end-to-end gRPC benchmarks. +*/ +package benchmark + +import ( + "fmt" + "io" + "net" + + "golang.org/x/net/context" + "google.golang.org/grpc" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/grpclog" +) + +func newPayload(t testpb.PayloadType, size int) *testpb.Payload { + if size < 0 { + grpclog.Fatalf("Requested a response with invalid length %d", size) + } + body := make([]byte, size) + switch t { + case testpb.PayloadType_COMPRESSABLE: + case testpb.PayloadType_UNCOMPRESSABLE: + grpclog.Fatalf("PayloadType UNCOMPRESSABLE is not supported") + default: + grpclog.Fatalf("Unsupported payload type: %d", t) + } + return &testpb.Payload{ + Type: t, + Body: body, + } +} + +type testServer struct { +} + +func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + return &testpb.SimpleResponse{ + Payload: newPayload(in.ResponseType, int(in.ResponseSize)), + }, nil +} + +func (s *testServer) StreamingCall(stream testpb.BenchmarkService_StreamingCallServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + return nil + } + if err != nil { + return err + } + if err := stream.Send(&testpb.SimpleResponse{ + Payload: newPayload(in.ResponseType, int(in.ResponseSize)), + }); err != nil { + return err + } + } +} + +// byteBufServer is a gRPC server that sends and receives byte buffer. +// The purpose is to benchmark the gRPC performance without protobuf serialization/deserialization overhead. +type byteBufServer struct { + respSize int32 +} + +// UnaryCall is an empty function and is not used for benchmark. +// If bytebuf UnaryCall benchmark is needed later, the function body needs to be updated. +func (s *byteBufServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + return &testpb.SimpleResponse{}, nil +} + +func (s *byteBufServer) StreamingCall(stream testpb.BenchmarkService_StreamingCallServer) error { + for { + var in []byte + err := stream.(grpc.ServerStream).RecvMsg(&in) + if err == io.EOF { + return nil + } + if err != nil { + return err + } + out := make([]byte, s.respSize) + if err := stream.(grpc.ServerStream).SendMsg(&out); err != nil { + return err + } + } +} + +// ServerInfo contains the information to create a gRPC benchmark server. +type ServerInfo struct { + // Addr is the address of the server. + Addr string + + // Type is the type of the server. + // It should be "protobuf" or "bytebuf". + Type string + + // Metadata is an optional configuration. + // For "protobuf", it's ignored. + // For "bytebuf", it should be an int representing response size. + Metadata interface{} +} + +// StartServer starts a gRPC server serving a benchmark service according to info. +// It returns its listen address and a function to stop the server. +func StartServer(info ServerInfo, opts ...grpc.ServerOption) (string, func()) { + lis, err := net.Listen("tcp", info.Addr) + if err != nil { + grpclog.Fatalf("Failed to listen: %v", err) + } + s := grpc.NewServer(opts...) + switch info.Type { + case "protobuf": + testpb.RegisterBenchmarkServiceServer(s, &testServer{}) + case "bytebuf": + respSize, ok := info.Metadata.(int32) + if !ok { + grpclog.Fatalf("failed to StartServer, invalid metadata: %v, for Type: %v", info.Metadata, info.Type) + } + testpb.RegisterBenchmarkServiceServer(s, &byteBufServer{respSize: respSize}) + default: + grpclog.Fatalf("failed to StartServer, unknown Type: %v", info.Type) + } + go s.Serve(lis) + return lis.Addr().String(), func() { + s.Stop() + } +} + +// DoUnaryCall performs an unary RPC with given stub and request and response sizes. +func DoUnaryCall(tc testpb.BenchmarkServiceClient, reqSize, respSize int) error { + pl := newPayload(testpb.PayloadType_COMPRESSABLE, reqSize) + req := &testpb.SimpleRequest{ + ResponseType: pl.Type, + ResponseSize: int32(respSize), + Payload: pl, + } + if _, err := tc.UnaryCall(context.Background(), req); err != nil { + return fmt.Errorf("/BenchmarkService/UnaryCall(_, _) = _, %v, want _, ", err) + } + return nil +} + +// DoStreamingRoundTrip performs a round trip for a single streaming rpc. +func DoStreamingRoundTrip(stream testpb.BenchmarkService_StreamingCallClient, reqSize, respSize int) error { + pl := newPayload(testpb.PayloadType_COMPRESSABLE, reqSize) + req := &testpb.SimpleRequest{ + ResponseType: pl.Type, + ResponseSize: int32(respSize), + Payload: pl, + } + if err := stream.Send(req); err != nil { + return fmt.Errorf("/BenchmarkService/StreamingCall.Send(_) = %v, want ", err) + } + if _, err := stream.Recv(); err != nil { + // EOF is a valid error here. + if err == io.EOF { + return nil + } + return fmt.Errorf("/BenchmarkService/StreamingCall.Recv(_) = %v, want ", err) + } + return nil +} + +// DoByteBufStreamingRoundTrip performs a round trip for a single streaming rpc, using a custom codec for byte buffer. +func DoByteBufStreamingRoundTrip(stream testpb.BenchmarkService_StreamingCallClient, reqSize, respSize int) error { + out := make([]byte, reqSize) + if err := stream.(grpc.ClientStream).SendMsg(&out); err != nil { + return fmt.Errorf("/BenchmarkService/StreamingCall.(ClientStream).SendMsg(_) = %v, want ", err) + } + var in []byte + if err := stream.(grpc.ClientStream).RecvMsg(&in); err != nil { + // EOF is a valid error here. + if err == io.EOF { + return nil + } + return fmt.Errorf("/BenchmarkService/StreamingCall.(ClientStream).RecvMsg(_) = %v, want ", err) + } + return nil +} + +// NewClientConn creates a gRPC client connection to addr. +func NewClientConn(addr string, opts ...grpc.DialOption) *grpc.ClientConn { + conn, err := grpc.Dial(addr, opts...) + if err != nil { + grpclog.Fatalf("NewClientConn(%q) failed to create a ClientConn %v", addr, err) + } + return conn +} diff --git a/vendor/google.golang.org/grpc/benchmark/benchmark_test.go b/vendor/google.golang.org/grpc/benchmark/benchmark_test.go new file mode 100644 index 00000000..8fe3fa15 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/benchmark_test.go @@ -0,0 +1,202 @@ +package benchmark + +import ( + "os" + "sync" + "testing" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/benchmark/stats" + "google.golang.org/grpc/grpclog" +) + +func runUnary(b *testing.B, maxConcurrentCalls int) { + s := stats.AddStats(b, 38) + b.StopTimer() + target, stopper := StartServer(ServerInfo{Addr: "localhost:0", Type: "protobuf"}) + defer stopper() + conn := NewClientConn(target, grpc.WithInsecure()) + tc := testpb.NewBenchmarkServiceClient(conn) + + // Warm up connection. + for i := 0; i < 10; i++ { + unaryCaller(tc) + } + ch := make(chan int, maxConcurrentCalls*4) + var ( + mu sync.Mutex + wg sync.WaitGroup + ) + wg.Add(maxConcurrentCalls) + + // Distribute the b.N calls over maxConcurrentCalls workers. + for i := 0; i < maxConcurrentCalls; i++ { + go func() { + for range ch { + start := time.Now() + unaryCaller(tc) + elapse := time.Since(start) + mu.Lock() + s.Add(elapse) + mu.Unlock() + } + wg.Done() + }() + } + b.StartTimer() + for i := 0; i < b.N; i++ { + ch <- i + } + b.StopTimer() + close(ch) + wg.Wait() + conn.Close() +} + +func runStream(b *testing.B, maxConcurrentCalls int) { + s := stats.AddStats(b, 38) + b.StopTimer() + target, stopper := StartServer(ServerInfo{Addr: "localhost:0", Type: "protobuf"}) + defer stopper() + conn := NewClientConn(target, grpc.WithInsecure()) + tc := testpb.NewBenchmarkServiceClient(conn) + + // Warm up connection. + stream, err := tc.StreamingCall(context.Background()) + if err != nil { + b.Fatalf("%v.StreamingCall(_) = _, %v", tc, err) + } + for i := 0; i < 10; i++ { + streamCaller(stream) + } + + ch := make(chan int, maxConcurrentCalls*4) + var ( + mu sync.Mutex + wg sync.WaitGroup + ) + wg.Add(maxConcurrentCalls) + + // Distribute the b.N calls over maxConcurrentCalls workers. + for i := 0; i < maxConcurrentCalls; i++ { + go func() { + stream, err := tc.StreamingCall(context.Background()) + if err != nil { + b.Fatalf("%v.StreamingCall(_) = _, %v", tc, err) + } + for range ch { + start := time.Now() + streamCaller(stream) + elapse := time.Since(start) + mu.Lock() + s.Add(elapse) + mu.Unlock() + } + wg.Done() + }() + } + b.StartTimer() + for i := 0; i < b.N; i++ { + ch <- i + } + b.StopTimer() + close(ch) + wg.Wait() + conn.Close() +} +func unaryCaller(client testpb.BenchmarkServiceClient) { + if err := DoUnaryCall(client, 1, 1); err != nil { + grpclog.Fatalf("DoUnaryCall failed: %v", err) + } +} + +func streamCaller(stream testpb.BenchmarkService_StreamingCallClient) { + if err := DoStreamingRoundTrip(stream, 1, 1); err != nil { + grpclog.Fatalf("DoStreamingRoundTrip failed: %v", err) + } +} + +func BenchmarkClientStreamc1(b *testing.B) { + grpc.EnableTracing = true + runStream(b, 1) +} + +func BenchmarkClientStreamc8(b *testing.B) { + grpc.EnableTracing = true + runStream(b, 8) +} + +func BenchmarkClientStreamc64(b *testing.B) { + grpc.EnableTracing = true + runStream(b, 64) +} + +func BenchmarkClientStreamc512(b *testing.B) { + grpc.EnableTracing = true + runStream(b, 512) +} +func BenchmarkClientUnaryc1(b *testing.B) { + grpc.EnableTracing = true + runUnary(b, 1) +} + +func BenchmarkClientUnaryc8(b *testing.B) { + grpc.EnableTracing = true + runUnary(b, 8) +} + +func BenchmarkClientUnaryc64(b *testing.B) { + grpc.EnableTracing = true + runUnary(b, 64) +} + +func BenchmarkClientUnaryc512(b *testing.B) { + grpc.EnableTracing = true + runUnary(b, 512) +} + +func BenchmarkClientStreamNoTracec1(b *testing.B) { + grpc.EnableTracing = false + runStream(b, 1) +} + +func BenchmarkClientStreamNoTracec8(b *testing.B) { + grpc.EnableTracing = false + runStream(b, 8) +} + +func BenchmarkClientStreamNoTracec64(b *testing.B) { + grpc.EnableTracing = false + runStream(b, 64) +} + +func BenchmarkClientStreamNoTracec512(b *testing.B) { + grpc.EnableTracing = false + runStream(b, 512) +} +func BenchmarkClientUnaryNoTracec1(b *testing.B) { + grpc.EnableTracing = false + runUnary(b, 1) +} + +func BenchmarkClientUnaryNoTracec8(b *testing.B) { + grpc.EnableTracing = false + runUnary(b, 8) +} + +func BenchmarkClientUnaryNoTracec64(b *testing.B) { + grpc.EnableTracing = false + runUnary(b, 64) +} + +func BenchmarkClientUnaryNoTracec512(b *testing.B) { + grpc.EnableTracing = false + runUnary(b, 512) +} + +func TestMain(m *testing.M) { + os.Exit(stats.RunTestMain(m)) +} diff --git a/vendor/google.golang.org/grpc/benchmark/client/main.go b/vendor/google.golang.org/grpc/benchmark/client/main.go new file mode 100644 index 00000000..5dfbe6a3 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/client/main.go @@ -0,0 +1,162 @@ +package main + +import ( + "flag" + "math" + "net" + "net/http" + _ "net/http/pprof" + "sync" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/benchmark" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/benchmark/stats" + "google.golang.org/grpc/grpclog" +) + +var ( + server = flag.String("server", "", "The server address") + maxConcurrentRPCs = flag.Int("max_concurrent_rpcs", 1, "The max number of concurrent RPCs") + duration = flag.Int("duration", math.MaxInt32, "The duration in seconds to run the benchmark client") + trace = flag.Bool("trace", true, "Whether tracing is on") + rpcType = flag.Int("rpc_type", 0, + `Configure different client rpc type. Valid options are: + 0 : unary call; + 1 : streaming call.`) +) + +func unaryCaller(client testpb.BenchmarkServiceClient) { + benchmark.DoUnaryCall(client, 1, 1) +} + +func streamCaller(stream testpb.BenchmarkService_StreamingCallClient) { + benchmark.DoStreamingRoundTrip(stream, 1, 1) +} + +func buildConnection() (s *stats.Stats, conn *grpc.ClientConn, tc testpb.BenchmarkServiceClient) { + s = stats.NewStats(256) + conn = benchmark.NewClientConn(*server) + tc = testpb.NewBenchmarkServiceClient(conn) + return s, conn, tc +} + +func closeLoopUnary() { + s, conn, tc := buildConnection() + + for i := 0; i < 100; i++ { + unaryCaller(tc) + } + ch := make(chan int, *maxConcurrentRPCs*4) + var ( + mu sync.Mutex + wg sync.WaitGroup + ) + wg.Add(*maxConcurrentRPCs) + + for i := 0; i < *maxConcurrentRPCs; i++ { + go func() { + for _ = range ch { + start := time.Now() + unaryCaller(tc) + elapse := time.Since(start) + mu.Lock() + s.Add(elapse) + mu.Unlock() + } + wg.Done() + }() + } + // Stop the client when time is up. + done := make(chan struct{}) + go func() { + <-time.After(time.Duration(*duration) * time.Second) + close(done) + }() + ok := true + for ok { + select { + case ch <- 0: + case <-done: + ok = false + } + } + close(ch) + wg.Wait() + conn.Close() + grpclog.Println(s.String()) + +} + +func closeLoopStream() { + s, conn, tc := buildConnection() + ch := make(chan int, *maxConcurrentRPCs*4) + var ( + mu sync.Mutex + wg sync.WaitGroup + ) + wg.Add(*maxConcurrentRPCs) + // Distribute RPCs over maxConcurrentCalls workers. + for i := 0; i < *maxConcurrentRPCs; i++ { + go func() { + stream, err := tc.StreamingCall(context.Background()) + if err != nil { + grpclog.Fatalf("%v.StreamingCall(_) = _, %v", tc, err) + } + // Do some warm up. + for i := 0; i < 100; i++ { + streamCaller(stream) + } + for range ch { + start := time.Now() + streamCaller(stream) + elapse := time.Since(start) + mu.Lock() + s.Add(elapse) + mu.Unlock() + } + wg.Done() + }() + } + // Stop the client when time is up. + done := make(chan struct{}) + go func() { + <-time.After(time.Duration(*duration) * time.Second) + close(done) + }() + ok := true + for ok { + select { + case ch <- 0: + case <-done: + ok = false + } + } + close(ch) + wg.Wait() + conn.Close() + grpclog.Println(s.String()) +} + +func main() { + flag.Parse() + grpc.EnableTracing = *trace + go func() { + lis, err := net.Listen("tcp", ":0") + if err != nil { + grpclog.Fatalf("Failed to listen: %v", err) + } + grpclog.Println("Client profiling address: ", lis.Addr().String()) + if err := http.Serve(lis, nil); err != nil { + grpclog.Fatalf("Failed to serve: %v", err) + } + }() + switch *rpcType { + case 0: + closeLoopUnary() + case 1: + closeLoopStream() + } +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.pb.go b/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.pb.go new file mode 100644 index 00000000..8afae814 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.pb.go @@ -0,0 +1,977 @@ +// Code generated by protoc-gen-go. +// source: control.proto +// DO NOT EDIT! + +/* +Package grpc_testing is a generated protocol buffer package. + +It is generated from these files: + control.proto + messages.proto + payloads.proto + services.proto + stats.proto + +It has these top-level messages: + PoissonParams + UniformParams + DeterministicParams + ParetoParams + ClosedLoopParams + LoadParams + SecurityParams + ClientConfig + ClientStatus + Mark + ClientArgs + ServerConfig + ServerArgs + ServerStatus + CoreRequest + CoreResponse + Void + Scenario + Scenarios + Payload + EchoStatus + SimpleRequest + SimpleResponse + StreamingInputCallRequest + StreamingInputCallResponse + ResponseParameters + StreamingOutputCallRequest + StreamingOutputCallResponse + ReconnectParams + ReconnectInfo + ByteBufferParams + SimpleProtoParams + ComplexProtoParams + PayloadConfig + ServerStats + HistogramParams + HistogramData + ClientStats +*/ +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type ClientType int32 + +const ( + ClientType_SYNC_CLIENT ClientType = 0 + ClientType_ASYNC_CLIENT ClientType = 1 +) + +var ClientType_name = map[int32]string{ + 0: "SYNC_CLIENT", + 1: "ASYNC_CLIENT", +} +var ClientType_value = map[string]int32{ + "SYNC_CLIENT": 0, + "ASYNC_CLIENT": 1, +} + +func (x ClientType) String() string { + return proto.EnumName(ClientType_name, int32(x)) +} +func (ClientType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type ServerType int32 + +const ( + ServerType_SYNC_SERVER ServerType = 0 + ServerType_ASYNC_SERVER ServerType = 1 + ServerType_ASYNC_GENERIC_SERVER ServerType = 2 +) + +var ServerType_name = map[int32]string{ + 0: "SYNC_SERVER", + 1: "ASYNC_SERVER", + 2: "ASYNC_GENERIC_SERVER", +} +var ServerType_value = map[string]int32{ + "SYNC_SERVER": 0, + "ASYNC_SERVER": 1, + "ASYNC_GENERIC_SERVER": 2, +} + +func (x ServerType) String() string { + return proto.EnumName(ServerType_name, int32(x)) +} +func (ServerType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type RpcType int32 + +const ( + RpcType_UNARY RpcType = 0 + RpcType_STREAMING RpcType = 1 +) + +var RpcType_name = map[int32]string{ + 0: "UNARY", + 1: "STREAMING", +} +var RpcType_value = map[string]int32{ + "UNARY": 0, + "STREAMING": 1, +} + +func (x RpcType) String() string { + return proto.EnumName(RpcType_name, int32(x)) +} +func (RpcType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +// Parameters of poisson process distribution, which is a good representation +// of activity coming in from independent identical stationary sources. +type PoissonParams struct { + // The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + OfferedLoad float64 `protobuf:"fixed64,1,opt,name=offered_load,json=offeredLoad" json:"offered_load,omitempty"` +} + +func (m *PoissonParams) Reset() { *m = PoissonParams{} } +func (m *PoissonParams) String() string { return proto.CompactTextString(m) } +func (*PoissonParams) ProtoMessage() {} +func (*PoissonParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type UniformParams struct { + InterarrivalLo float64 `protobuf:"fixed64,1,opt,name=interarrival_lo,json=interarrivalLo" json:"interarrival_lo,omitempty"` + InterarrivalHi float64 `protobuf:"fixed64,2,opt,name=interarrival_hi,json=interarrivalHi" json:"interarrival_hi,omitempty"` +} + +func (m *UniformParams) Reset() { *m = UniformParams{} } +func (m *UniformParams) String() string { return proto.CompactTextString(m) } +func (*UniformParams) ProtoMessage() {} +func (*UniformParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type DeterministicParams struct { + OfferedLoad float64 `protobuf:"fixed64,1,opt,name=offered_load,json=offeredLoad" json:"offered_load,omitempty"` +} + +func (m *DeterministicParams) Reset() { *m = DeterministicParams{} } +func (m *DeterministicParams) String() string { return proto.CompactTextString(m) } +func (*DeterministicParams) ProtoMessage() {} +func (*DeterministicParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type ParetoParams struct { + InterarrivalBase float64 `protobuf:"fixed64,1,opt,name=interarrival_base,json=interarrivalBase" json:"interarrival_base,omitempty"` + Alpha float64 `protobuf:"fixed64,2,opt,name=alpha" json:"alpha,omitempty"` +} + +func (m *ParetoParams) Reset() { *m = ParetoParams{} } +func (m *ParetoParams) String() string { return proto.CompactTextString(m) } +func (*ParetoParams) ProtoMessage() {} +func (*ParetoParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +// Once an RPC finishes, immediately start a new one. +// No configuration parameters needed. +type ClosedLoopParams struct { +} + +func (m *ClosedLoopParams) Reset() { *m = ClosedLoopParams{} } +func (m *ClosedLoopParams) String() string { return proto.CompactTextString(m) } +func (*ClosedLoopParams) ProtoMessage() {} +func (*ClosedLoopParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +type LoadParams struct { + // Types that are valid to be assigned to Load: + // *LoadParams_ClosedLoop + // *LoadParams_Poisson + // *LoadParams_Uniform + // *LoadParams_Determ + // *LoadParams_Pareto + Load isLoadParams_Load `protobuf_oneof:"load"` +} + +func (m *LoadParams) Reset() { *m = LoadParams{} } +func (m *LoadParams) String() string { return proto.CompactTextString(m) } +func (*LoadParams) ProtoMessage() {} +func (*LoadParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +type isLoadParams_Load interface { + isLoadParams_Load() +} + +type LoadParams_ClosedLoop struct { + ClosedLoop *ClosedLoopParams `protobuf:"bytes,1,opt,name=closed_loop,json=closedLoop,oneof"` +} +type LoadParams_Poisson struct { + Poisson *PoissonParams `protobuf:"bytes,2,opt,name=poisson,oneof"` +} +type LoadParams_Uniform struct { + Uniform *UniformParams `protobuf:"bytes,3,opt,name=uniform,oneof"` +} +type LoadParams_Determ struct { + Determ *DeterministicParams `protobuf:"bytes,4,opt,name=determ,oneof"` +} +type LoadParams_Pareto struct { + Pareto *ParetoParams `protobuf:"bytes,5,opt,name=pareto,oneof"` +} + +func (*LoadParams_ClosedLoop) isLoadParams_Load() {} +func (*LoadParams_Poisson) isLoadParams_Load() {} +func (*LoadParams_Uniform) isLoadParams_Load() {} +func (*LoadParams_Determ) isLoadParams_Load() {} +func (*LoadParams_Pareto) isLoadParams_Load() {} + +func (m *LoadParams) GetLoad() isLoadParams_Load { + if m != nil { + return m.Load + } + return nil +} + +func (m *LoadParams) GetClosedLoop() *ClosedLoopParams { + if x, ok := m.GetLoad().(*LoadParams_ClosedLoop); ok { + return x.ClosedLoop + } + return nil +} + +func (m *LoadParams) GetPoisson() *PoissonParams { + if x, ok := m.GetLoad().(*LoadParams_Poisson); ok { + return x.Poisson + } + return nil +} + +func (m *LoadParams) GetUniform() *UniformParams { + if x, ok := m.GetLoad().(*LoadParams_Uniform); ok { + return x.Uniform + } + return nil +} + +func (m *LoadParams) GetDeterm() *DeterministicParams { + if x, ok := m.GetLoad().(*LoadParams_Determ); ok { + return x.Determ + } + return nil +} + +func (m *LoadParams) GetPareto() *ParetoParams { + if x, ok := m.GetLoad().(*LoadParams_Pareto); ok { + return x.Pareto + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*LoadParams) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _LoadParams_OneofMarshaler, _LoadParams_OneofUnmarshaler, _LoadParams_OneofSizer, []interface{}{ + (*LoadParams_ClosedLoop)(nil), + (*LoadParams_Poisson)(nil), + (*LoadParams_Uniform)(nil), + (*LoadParams_Determ)(nil), + (*LoadParams_Pareto)(nil), + } +} + +func _LoadParams_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*LoadParams) + // load + switch x := m.Load.(type) { + case *LoadParams_ClosedLoop: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ClosedLoop); err != nil { + return err + } + case *LoadParams_Poisson: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Poisson); err != nil { + return err + } + case *LoadParams_Uniform: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Uniform); err != nil { + return err + } + case *LoadParams_Determ: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Determ); err != nil { + return err + } + case *LoadParams_Pareto: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Pareto); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("LoadParams.Load has unexpected type %T", x) + } + return nil +} + +func _LoadParams_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*LoadParams) + switch tag { + case 1: // load.closed_loop + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ClosedLoopParams) + err := b.DecodeMessage(msg) + m.Load = &LoadParams_ClosedLoop{msg} + return true, err + case 2: // load.poisson + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PoissonParams) + err := b.DecodeMessage(msg) + m.Load = &LoadParams_Poisson{msg} + return true, err + case 3: // load.uniform + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(UniformParams) + err := b.DecodeMessage(msg) + m.Load = &LoadParams_Uniform{msg} + return true, err + case 4: // load.determ + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(DeterministicParams) + err := b.DecodeMessage(msg) + m.Load = &LoadParams_Determ{msg} + return true, err + case 5: // load.pareto + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ParetoParams) + err := b.DecodeMessage(msg) + m.Load = &LoadParams_Pareto{msg} + return true, err + default: + return false, nil + } +} + +func _LoadParams_OneofSizer(msg proto.Message) (n int) { + m := msg.(*LoadParams) + // load + switch x := m.Load.(type) { + case *LoadParams_ClosedLoop: + s := proto.Size(x.ClosedLoop) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *LoadParams_Poisson: + s := proto.Size(x.Poisson) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *LoadParams_Uniform: + s := proto.Size(x.Uniform) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *LoadParams_Determ: + s := proto.Size(x.Determ) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *LoadParams_Pareto: + s := proto.Size(x.Pareto) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// presence of SecurityParams implies use of TLS +type SecurityParams struct { + UseTestCa bool `protobuf:"varint,1,opt,name=use_test_ca,json=useTestCa" json:"use_test_ca,omitempty"` + ServerHostOverride string `protobuf:"bytes,2,opt,name=server_host_override,json=serverHostOverride" json:"server_host_override,omitempty"` +} + +func (m *SecurityParams) Reset() { *m = SecurityParams{} } +func (m *SecurityParams) String() string { return proto.CompactTextString(m) } +func (*SecurityParams) ProtoMessage() {} +func (*SecurityParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +type ClientConfig struct { + // List of targets to connect to. At least one target needs to be specified. + ServerTargets []string `protobuf:"bytes,1,rep,name=server_targets,json=serverTargets" json:"server_targets,omitempty"` + ClientType ClientType `protobuf:"varint,2,opt,name=client_type,json=clientType,enum=grpc.testing.ClientType" json:"client_type,omitempty"` + SecurityParams *SecurityParams `protobuf:"bytes,3,opt,name=security_params,json=securityParams" json:"security_params,omitempty"` + // How many concurrent RPCs to start for each channel. + // For synchronous client, use a separate thread for each outstanding RPC. + OutstandingRpcsPerChannel int32 `protobuf:"varint,4,opt,name=outstanding_rpcs_per_channel,json=outstandingRpcsPerChannel" json:"outstanding_rpcs_per_channel,omitempty"` + // Number of independent client channels to create. + // i-th channel will connect to server_target[i % server_targets.size()] + ClientChannels int32 `protobuf:"varint,5,opt,name=client_channels,json=clientChannels" json:"client_channels,omitempty"` + // Only for async client. Number of threads to use to start/manage RPCs. + AsyncClientThreads int32 `protobuf:"varint,7,opt,name=async_client_threads,json=asyncClientThreads" json:"async_client_threads,omitempty"` + RpcType RpcType `protobuf:"varint,8,opt,name=rpc_type,json=rpcType,enum=grpc.testing.RpcType" json:"rpc_type,omitempty"` + // The requested load for the entire client (aggregated over all the threads). + LoadParams *LoadParams `protobuf:"bytes,10,opt,name=load_params,json=loadParams" json:"load_params,omitempty"` + PayloadConfig *PayloadConfig `protobuf:"bytes,11,opt,name=payload_config,json=payloadConfig" json:"payload_config,omitempty"` + HistogramParams *HistogramParams `protobuf:"bytes,12,opt,name=histogram_params,json=histogramParams" json:"histogram_params,omitempty"` + // Specify the cores we should run the client on, if desired + CoreList []int32 `protobuf:"varint,13,rep,name=core_list,json=coreList" json:"core_list,omitempty"` + CoreLimit int32 `protobuf:"varint,14,opt,name=core_limit,json=coreLimit" json:"core_limit,omitempty"` +} + +func (m *ClientConfig) Reset() { *m = ClientConfig{} } +func (m *ClientConfig) String() string { return proto.CompactTextString(m) } +func (*ClientConfig) ProtoMessage() {} +func (*ClientConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *ClientConfig) GetSecurityParams() *SecurityParams { + if m != nil { + return m.SecurityParams + } + return nil +} + +func (m *ClientConfig) GetLoadParams() *LoadParams { + if m != nil { + return m.LoadParams + } + return nil +} + +func (m *ClientConfig) GetPayloadConfig() *PayloadConfig { + if m != nil { + return m.PayloadConfig + } + return nil +} + +func (m *ClientConfig) GetHistogramParams() *HistogramParams { + if m != nil { + return m.HistogramParams + } + return nil +} + +type ClientStatus struct { + Stats *ClientStats `protobuf:"bytes,1,opt,name=stats" json:"stats,omitempty"` +} + +func (m *ClientStatus) Reset() { *m = ClientStatus{} } +func (m *ClientStatus) String() string { return proto.CompactTextString(m) } +func (*ClientStatus) ProtoMessage() {} +func (*ClientStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *ClientStatus) GetStats() *ClientStats { + if m != nil { + return m.Stats + } + return nil +} + +// Request current stats +type Mark struct { + // if true, the stats will be reset after taking their snapshot. + Reset_ bool `protobuf:"varint,1,opt,name=reset" json:"reset,omitempty"` +} + +func (m *Mark) Reset() { *m = Mark{} } +func (m *Mark) String() string { return proto.CompactTextString(m) } +func (*Mark) ProtoMessage() {} +func (*Mark) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +type ClientArgs struct { + // Types that are valid to be assigned to Argtype: + // *ClientArgs_Setup + // *ClientArgs_Mark + Argtype isClientArgs_Argtype `protobuf_oneof:"argtype"` +} + +func (m *ClientArgs) Reset() { *m = ClientArgs{} } +func (m *ClientArgs) String() string { return proto.CompactTextString(m) } +func (*ClientArgs) ProtoMessage() {} +func (*ClientArgs) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +type isClientArgs_Argtype interface { + isClientArgs_Argtype() +} + +type ClientArgs_Setup struct { + Setup *ClientConfig `protobuf:"bytes,1,opt,name=setup,oneof"` +} +type ClientArgs_Mark struct { + Mark *Mark `protobuf:"bytes,2,opt,name=mark,oneof"` +} + +func (*ClientArgs_Setup) isClientArgs_Argtype() {} +func (*ClientArgs_Mark) isClientArgs_Argtype() {} + +func (m *ClientArgs) GetArgtype() isClientArgs_Argtype { + if m != nil { + return m.Argtype + } + return nil +} + +func (m *ClientArgs) GetSetup() *ClientConfig { + if x, ok := m.GetArgtype().(*ClientArgs_Setup); ok { + return x.Setup + } + return nil +} + +func (m *ClientArgs) GetMark() *Mark { + if x, ok := m.GetArgtype().(*ClientArgs_Mark); ok { + return x.Mark + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ClientArgs) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ClientArgs_OneofMarshaler, _ClientArgs_OneofUnmarshaler, _ClientArgs_OneofSizer, []interface{}{ + (*ClientArgs_Setup)(nil), + (*ClientArgs_Mark)(nil), + } +} + +func _ClientArgs_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ClientArgs) + // argtype + switch x := m.Argtype.(type) { + case *ClientArgs_Setup: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Setup); err != nil { + return err + } + case *ClientArgs_Mark: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Mark); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ClientArgs.Argtype has unexpected type %T", x) + } + return nil +} + +func _ClientArgs_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ClientArgs) + switch tag { + case 1: // argtype.setup + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ClientConfig) + err := b.DecodeMessage(msg) + m.Argtype = &ClientArgs_Setup{msg} + return true, err + case 2: // argtype.mark + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Mark) + err := b.DecodeMessage(msg) + m.Argtype = &ClientArgs_Mark{msg} + return true, err + default: + return false, nil + } +} + +func _ClientArgs_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ClientArgs) + // argtype + switch x := m.Argtype.(type) { + case *ClientArgs_Setup: + s := proto.Size(x.Setup) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ClientArgs_Mark: + s := proto.Size(x.Mark) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type ServerConfig struct { + ServerType ServerType `protobuf:"varint,1,opt,name=server_type,json=serverType,enum=grpc.testing.ServerType" json:"server_type,omitempty"` + SecurityParams *SecurityParams `protobuf:"bytes,2,opt,name=security_params,json=securityParams" json:"security_params,omitempty"` + // Port on which to listen. Zero means pick unused port. + Port int32 `protobuf:"varint,4,opt,name=port" json:"port,omitempty"` + // Only for async server. Number of threads used to serve the requests. + AsyncServerThreads int32 `protobuf:"varint,7,opt,name=async_server_threads,json=asyncServerThreads" json:"async_server_threads,omitempty"` + // Specify the number of cores to limit server to, if desired + CoreLimit int32 `protobuf:"varint,8,opt,name=core_limit,json=coreLimit" json:"core_limit,omitempty"` + // payload config, used in generic server + PayloadConfig *PayloadConfig `protobuf:"bytes,9,opt,name=payload_config,json=payloadConfig" json:"payload_config,omitempty"` + // Specify the cores we should run the server on, if desired + CoreList []int32 `protobuf:"varint,10,rep,name=core_list,json=coreList" json:"core_list,omitempty"` +} + +func (m *ServerConfig) Reset() { *m = ServerConfig{} } +func (m *ServerConfig) String() string { return proto.CompactTextString(m) } +func (*ServerConfig) ProtoMessage() {} +func (*ServerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +func (m *ServerConfig) GetSecurityParams() *SecurityParams { + if m != nil { + return m.SecurityParams + } + return nil +} + +func (m *ServerConfig) GetPayloadConfig() *PayloadConfig { + if m != nil { + return m.PayloadConfig + } + return nil +} + +type ServerArgs struct { + // Types that are valid to be assigned to Argtype: + // *ServerArgs_Setup + // *ServerArgs_Mark + Argtype isServerArgs_Argtype `protobuf_oneof:"argtype"` +} + +func (m *ServerArgs) Reset() { *m = ServerArgs{} } +func (m *ServerArgs) String() string { return proto.CompactTextString(m) } +func (*ServerArgs) ProtoMessage() {} +func (*ServerArgs) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +type isServerArgs_Argtype interface { + isServerArgs_Argtype() +} + +type ServerArgs_Setup struct { + Setup *ServerConfig `protobuf:"bytes,1,opt,name=setup,oneof"` +} +type ServerArgs_Mark struct { + Mark *Mark `protobuf:"bytes,2,opt,name=mark,oneof"` +} + +func (*ServerArgs_Setup) isServerArgs_Argtype() {} +func (*ServerArgs_Mark) isServerArgs_Argtype() {} + +func (m *ServerArgs) GetArgtype() isServerArgs_Argtype { + if m != nil { + return m.Argtype + } + return nil +} + +func (m *ServerArgs) GetSetup() *ServerConfig { + if x, ok := m.GetArgtype().(*ServerArgs_Setup); ok { + return x.Setup + } + return nil +} + +func (m *ServerArgs) GetMark() *Mark { + if x, ok := m.GetArgtype().(*ServerArgs_Mark); ok { + return x.Mark + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ServerArgs) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ServerArgs_OneofMarshaler, _ServerArgs_OneofUnmarshaler, _ServerArgs_OneofSizer, []interface{}{ + (*ServerArgs_Setup)(nil), + (*ServerArgs_Mark)(nil), + } +} + +func _ServerArgs_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ServerArgs) + // argtype + switch x := m.Argtype.(type) { + case *ServerArgs_Setup: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Setup); err != nil { + return err + } + case *ServerArgs_Mark: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Mark); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ServerArgs.Argtype has unexpected type %T", x) + } + return nil +} + +func _ServerArgs_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ServerArgs) + switch tag { + case 1: // argtype.setup + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ServerConfig) + err := b.DecodeMessage(msg) + m.Argtype = &ServerArgs_Setup{msg} + return true, err + case 2: // argtype.mark + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Mark) + err := b.DecodeMessage(msg) + m.Argtype = &ServerArgs_Mark{msg} + return true, err + default: + return false, nil + } +} + +func _ServerArgs_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ServerArgs) + // argtype + switch x := m.Argtype.(type) { + case *ServerArgs_Setup: + s := proto.Size(x.Setup) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ServerArgs_Mark: + s := proto.Size(x.Mark) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type ServerStatus struct { + Stats *ServerStats `protobuf:"bytes,1,opt,name=stats" json:"stats,omitempty"` + // the port bound by the server + Port int32 `protobuf:"varint,2,opt,name=port" json:"port,omitempty"` + // Number of cores available to the server + Cores int32 `protobuf:"varint,3,opt,name=cores" json:"cores,omitempty"` +} + +func (m *ServerStatus) Reset() { *m = ServerStatus{} } +func (m *ServerStatus) String() string { return proto.CompactTextString(m) } +func (*ServerStatus) ProtoMessage() {} +func (*ServerStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +func (m *ServerStatus) GetStats() *ServerStats { + if m != nil { + return m.Stats + } + return nil +} + +type CoreRequest struct { +} + +func (m *CoreRequest) Reset() { *m = CoreRequest{} } +func (m *CoreRequest) String() string { return proto.CompactTextString(m) } +func (*CoreRequest) ProtoMessage() {} +func (*CoreRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +type CoreResponse struct { + // Number of cores available on the server + Cores int32 `protobuf:"varint,1,opt,name=cores" json:"cores,omitempty"` +} + +func (m *CoreResponse) Reset() { *m = CoreResponse{} } +func (m *CoreResponse) String() string { return proto.CompactTextString(m) } +func (*CoreResponse) ProtoMessage() {} +func (*CoreResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +type Void struct { +} + +func (m *Void) Reset() { *m = Void{} } +func (m *Void) String() string { return proto.CompactTextString(m) } +func (*Void) ProtoMessage() {} +func (*Void) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +// A single performance scenario: input to qps_json_driver +type Scenario struct { + // Human readable name for this scenario + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Client configuration + ClientConfig *ClientConfig `protobuf:"bytes,2,opt,name=client_config,json=clientConfig" json:"client_config,omitempty"` + // Number of clients to start for the test + NumClients int32 `protobuf:"varint,3,opt,name=num_clients,json=numClients" json:"num_clients,omitempty"` + // Server configuration + ServerConfig *ServerConfig `protobuf:"bytes,4,opt,name=server_config,json=serverConfig" json:"server_config,omitempty"` + // Number of servers to start for the test + NumServers int32 `protobuf:"varint,5,opt,name=num_servers,json=numServers" json:"num_servers,omitempty"` + // Warmup period, in seconds + WarmupSeconds int32 `protobuf:"varint,6,opt,name=warmup_seconds,json=warmupSeconds" json:"warmup_seconds,omitempty"` + // Benchmark time, in seconds + BenchmarkSeconds int32 `protobuf:"varint,7,opt,name=benchmark_seconds,json=benchmarkSeconds" json:"benchmark_seconds,omitempty"` + // Number of workers to spawn locally (usually zero) + SpawnLocalWorkerCount int32 `protobuf:"varint,8,opt,name=spawn_local_worker_count,json=spawnLocalWorkerCount" json:"spawn_local_worker_count,omitempty"` +} + +func (m *Scenario) Reset() { *m = Scenario{} } +func (m *Scenario) String() string { return proto.CompactTextString(m) } +func (*Scenario) ProtoMessage() {} +func (*Scenario) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *Scenario) GetClientConfig() *ClientConfig { + if m != nil { + return m.ClientConfig + } + return nil +} + +func (m *Scenario) GetServerConfig() *ServerConfig { + if m != nil { + return m.ServerConfig + } + return nil +} + +// A set of scenarios to be run with qps_json_driver +type Scenarios struct { + Scenarios []*Scenario `protobuf:"bytes,1,rep,name=scenarios" json:"scenarios,omitempty"` +} + +func (m *Scenarios) Reset() { *m = Scenarios{} } +func (m *Scenarios) String() string { return proto.CompactTextString(m) } +func (*Scenarios) ProtoMessage() {} +func (*Scenarios) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *Scenarios) GetScenarios() []*Scenario { + if m != nil { + return m.Scenarios + } + return nil +} + +func init() { + proto.RegisterType((*PoissonParams)(nil), "grpc.testing.PoissonParams") + proto.RegisterType((*UniformParams)(nil), "grpc.testing.UniformParams") + proto.RegisterType((*DeterministicParams)(nil), "grpc.testing.DeterministicParams") + proto.RegisterType((*ParetoParams)(nil), "grpc.testing.ParetoParams") + proto.RegisterType((*ClosedLoopParams)(nil), "grpc.testing.ClosedLoopParams") + proto.RegisterType((*LoadParams)(nil), "grpc.testing.LoadParams") + proto.RegisterType((*SecurityParams)(nil), "grpc.testing.SecurityParams") + proto.RegisterType((*ClientConfig)(nil), "grpc.testing.ClientConfig") + proto.RegisterType((*ClientStatus)(nil), "grpc.testing.ClientStatus") + proto.RegisterType((*Mark)(nil), "grpc.testing.Mark") + proto.RegisterType((*ClientArgs)(nil), "grpc.testing.ClientArgs") + proto.RegisterType((*ServerConfig)(nil), "grpc.testing.ServerConfig") + proto.RegisterType((*ServerArgs)(nil), "grpc.testing.ServerArgs") + proto.RegisterType((*ServerStatus)(nil), "grpc.testing.ServerStatus") + proto.RegisterType((*CoreRequest)(nil), "grpc.testing.CoreRequest") + proto.RegisterType((*CoreResponse)(nil), "grpc.testing.CoreResponse") + proto.RegisterType((*Void)(nil), "grpc.testing.Void") + proto.RegisterType((*Scenario)(nil), "grpc.testing.Scenario") + proto.RegisterType((*Scenarios)(nil), "grpc.testing.Scenarios") + proto.RegisterEnum("grpc.testing.ClientType", ClientType_name, ClientType_value) + proto.RegisterEnum("grpc.testing.ServerType", ServerType_name, ServerType_value) + proto.RegisterEnum("grpc.testing.RpcType", RpcType_name, RpcType_value) +} + +func init() { proto.RegisterFile("control.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 1162 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0xdb, 0x46, + 0x13, 0x8d, 0x14, 0xc9, 0x96, 0x86, 0x92, 0xac, 0x6f, 0xbf, 0xa4, 0x60, 0x1c, 0x27, 0x6d, 0xd8, + 0x16, 0x0d, 0x5c, 0xc0, 0x29, 0xd4, 0x02, 0x69, 0xd1, 0x8b, 0x40, 0x56, 0x85, 0xd8, 0x80, 0xe3, + 0xba, 0x2b, 0x27, 0x45, 0xae, 0x08, 0x9a, 0x5a, 0x4b, 0x44, 0x24, 0x2e, 0xbb, 0x4b, 0xc6, 0xf0, + 0x2b, 0xf4, 0x99, 0xfa, 0x1c, 0x7d, 0x8d, 0xbe, 0x42, 0x67, 0xff, 0x64, 0x52, 0x11, 0x10, 0xb7, + 0xbd, 0xe3, 0xce, 0x9c, 0xb3, 0x3b, 0x3b, 0x67, 0x66, 0x96, 0xd0, 0x8d, 0x79, 0x9a, 0x0b, 0xbe, + 0x38, 0xc8, 0x04, 0xcf, 0x39, 0xe9, 0xcc, 0x44, 0x16, 0x1f, 0xe4, 0x4c, 0xe6, 0x49, 0x3a, 0xdb, + 0xed, 0x65, 0xd1, 0xf5, 0x82, 0x47, 0x53, 0x69, 0xbc, 0xbb, 0x9e, 0xcc, 0xa3, 0xdc, 0x2e, 0x82, + 0x01, 0x74, 0xcf, 0x78, 0x22, 0x25, 0x4f, 0xcf, 0x22, 0x11, 0x2d, 0x25, 0x79, 0x02, 0x1d, 0x7e, + 0x79, 0xc9, 0x04, 0x9b, 0x86, 0x8a, 0xe4, 0xd7, 0x3e, 0xab, 0x3d, 0xad, 0x51, 0xcf, 0xda, 0x4e, + 0xd0, 0x14, 0x44, 0xd0, 0x7d, 0x9d, 0x26, 0x97, 0x5c, 0x2c, 0x2d, 0xe7, 0x2b, 0xd8, 0x49, 0xd2, + 0x9c, 0x89, 0x48, 0x88, 0xe4, 0x7d, 0xb4, 0x40, 0xa2, 0xa5, 0xf5, 0xca, 0xe6, 0x13, 0xfe, 0x01, + 0x70, 0x9e, 0xf8, 0xf5, 0x0f, 0x81, 0x47, 0x49, 0xf0, 0x3d, 0xfc, 0xff, 0x27, 0x86, 0x96, 0x65, + 0x92, 0x26, 0x78, 0x8b, 0xf8, 0xf6, 0xc1, 0xfd, 0x02, 0x1d, 0x04, 0xb3, 0x9c, 0x5b, 0xca, 0xd7, + 0xf0, 0xbf, 0xca, 0x91, 0x17, 0x91, 0x64, 0x96, 0xd7, 0x2f, 0x3b, 0x0e, 0xd1, 0x4e, 0xee, 0x41, + 0x33, 0x5a, 0x64, 0xf3, 0xc8, 0x46, 0x65, 0x16, 0x01, 0x81, 0xfe, 0x68, 0xc1, 0xa5, 0x3a, 0x80, + 0x67, 0x66, 0xdb, 0xe0, 0x8f, 0x3a, 0x80, 0x3a, 0xcf, 0x9e, 0x32, 0x04, 0x2f, 0xd6, 0x10, 0x8c, + 0x8b, 0x67, 0x7a, 0x7f, 0x6f, 0xf0, 0xf8, 0xa0, 0xac, 0xc3, 0xc1, 0xfa, 0x1e, 0x47, 0x77, 0x28, + 0xc4, 0x2b, 0x1b, 0x79, 0x0e, 0xdb, 0x99, 0x51, 0x42, 0x9f, 0xee, 0x0d, 0x1e, 0x56, 0xe9, 0x15, + 0x99, 0x90, 0xeb, 0xd0, 0x8a, 0x58, 0x18, 0x39, 0xfc, 0xbb, 0x9b, 0x88, 0x15, 0xad, 0x14, 0xd1, + 0xa2, 0xc9, 0x8f, 0xb0, 0x35, 0xd5, 0x49, 0xf6, 0x1b, 0x9a, 0xf7, 0xa4, 0xca, 0xdb, 0x20, 0x00, + 0xb2, 0x2d, 0x85, 0x7c, 0x07, 0x5b, 0x99, 0xce, 0xb3, 0xdf, 0xd4, 0xe4, 0xdd, 0xb5, 0x68, 0x4b, + 0x1a, 0x28, 0x96, 0xc1, 0x1e, 0x6e, 0x41, 0x43, 0x09, 0x17, 0x5c, 0x40, 0x6f, 0xc2, 0xe2, 0x42, + 0x24, 0xf9, 0xb5, 0xcd, 0xe0, 0x63, 0xf0, 0x0a, 0xc9, 0x42, 0xc5, 0x0f, 0xe3, 0x48, 0x67, 0xb0, + 0x45, 0xdb, 0x68, 0x3a, 0x47, 0xcb, 0x28, 0x22, 0xdf, 0xc0, 0x3d, 0xc9, 0xc4, 0x7b, 0x26, 0xc2, + 0x39, 0x47, 0x08, 0xc7, 0x2f, 0x91, 0x4c, 0x99, 0xce, 0x55, 0x9b, 0x12, 0xe3, 0x3b, 0x42, 0xd7, + 0xcf, 0xd6, 0x13, 0xfc, 0xde, 0x84, 0xce, 0x68, 0x91, 0xb0, 0x34, 0x1f, 0xf1, 0xf4, 0x32, 0x99, + 0x91, 0x2f, 0xa1, 0x67, 0xb7, 0xc8, 0x23, 0x31, 0x63, 0xb9, 0xc4, 0x53, 0xee, 0x22, 0xb9, 0x6b, + 0xac, 0xe7, 0xc6, 0x48, 0x7e, 0x50, 0x5a, 0x2a, 0x5a, 0x98, 0x5f, 0x67, 0xe6, 0x80, 0xde, 0xc0, + 0x5f, 0xd7, 0x52, 0x01, 0xce, 0xd1, 0xaf, 0x34, 0x74, 0xdf, 0x64, 0x0c, 0x3b, 0xd2, 0x5e, 0x2b, + 0xcc, 0xf4, 0xbd, 0xac, 0x24, 0x7b, 0x55, 0x7a, 0xf5, 0xee, 0xb4, 0x27, 0xab, 0xb9, 0x78, 0x01, + 0x7b, 0xbc, 0xc8, 0xb1, 0x4d, 0xd3, 0x29, 0xa2, 0x43, 0x64, 0xca, 0x30, 0xc3, 0xb0, 0xe3, 0x79, + 0x94, 0xa6, 0x6c, 0xa1, 0xe5, 0x6a, 0xd2, 0x07, 0x25, 0x0c, 0x45, 0xc8, 0x19, 0x13, 0x23, 0x03, + 0x50, 0x7d, 0x66, 0xaf, 0x60, 0x29, 0x52, 0xab, 0xd4, 0xa4, 0x3d, 0x63, 0xb6, 0x38, 0xa9, 0xb2, + 0x1a, 0xc9, 0xeb, 0x34, 0x0e, 0xdd, 0x8d, 0xe7, 0x82, 0xe1, 0xa4, 0xf0, 0xb7, 0x35, 0x9a, 0x68, + 0x9f, 0xbd, 0xab, 0xf1, 0x20, 0xa3, 0x85, 0xf1, 0x98, 0xd4, 0xb4, 0x74, 0x6a, 0xee, 0x57, 0xef, + 0x86, 0xa1, 0xe8, 0xbc, 0x6c, 0x0b, 0xf3, 0xa1, 0xf2, 0xa9, 0x34, 0x77, 0x09, 0x01, 0x9d, 0x90, + 0xb5, 0x7c, 0xde, 0xb4, 0x12, 0x85, 0xc5, 0x4d, 0x5b, 0x1d, 0x82, 0x1b, 0x5e, 0x61, 0xac, 0x35, + 0xf4, 0xbd, 0x8d, 0xad, 0x61, 0x30, 0x46, 0x66, 0xda, 0xcd, 0xca, 0x4b, 0x72, 0x04, 0xfd, 0x39, + 0x96, 0x30, 0x9f, 0xe1, 0x8e, 0x2e, 0x86, 0x8e, 0xde, 0xe5, 0x51, 0x75, 0x97, 0x23, 0x87, 0xb2, + 0x81, 0xec, 0xcc, 0xab, 0x06, 0xf2, 0x10, 0xda, 0x31, 0x17, 0x2c, 0x5c, 0xa0, 0xdd, 0xef, 0x62, + 0xe9, 0x34, 0x69, 0x4b, 0x19, 0x4e, 0x70, 0x4d, 0x1e, 0x01, 0x58, 0xe7, 0x32, 0xc9, 0xfd, 0x9e, + 0xce, 0x5f, 0xdb, 0x78, 0xd1, 0x10, 0xbc, 0x70, 0xb5, 0x38, 0xc1, 0xe1, 0x5b, 0x48, 0xf2, 0x0c, + 0x9a, 0x7a, 0x0c, 0xdb, 0x51, 0xf1, 0x60, 0x53, 0x79, 0x29, 0xa8, 0xa4, 0x06, 0x17, 0xec, 0x41, + 0xe3, 0x55, 0x24, 0xde, 0xa9, 0x11, 0x25, 0x98, 0x64, 0xb9, 0xed, 0x10, 0xb3, 0x08, 0x0a, 0x00, + 0xc3, 0x19, 0x8a, 0x99, 0x24, 0x03, 0xdc, 0x9c, 0xe5, 0x85, 0x9b, 0x43, 0xbb, 0x9b, 0x36, 0x37, + 0xd9, 0xc1, 0xd6, 0x34, 0x50, 0xf2, 0x14, 0x1a, 0x4b, 0xdc, 0xdf, 0xce, 0x1e, 0x52, 0xa5, 0xa8, + 0x93, 0x11, 0xaa, 0x11, 0x87, 0x6d, 0xd8, 0xc6, 0x4e, 0x51, 0x05, 0x10, 0xfc, 0x59, 0x87, 0xce, + 0x44, 0x37, 0x8f, 0x4d, 0x36, 0x6a, 0xed, 0x5a, 0x4c, 0x15, 0x48, 0x6d, 0x53, 0xef, 0x18, 0x82, + 0xe9, 0x1d, 0xb9, 0xfa, 0xde, 0xd4, 0x3b, 0xf5, 0x7f, 0xd1, 0x3b, 0x04, 0x1a, 0x19, 0x17, 0xb9, + 0xed, 0x11, 0xfd, 0x7d, 0x53, 0xe5, 0x2e, 0xb6, 0x0d, 0x55, 0x6e, 0xa3, 0xb2, 0x55, 0x5e, 0x55, + 0xb3, 0xb5, 0xa6, 0xe6, 0x86, 0xba, 0x6c, 0xff, 0xe3, 0xba, 0xac, 0x54, 0x13, 0x54, 0xab, 0x49, + 0xe9, 0x69, 0x02, 0xba, 0x85, 0x9e, 0x65, 0x01, 0xfe, 0xa3, 0x9e, 0x89, 0x93, 0xf3, 0x56, 0x55, + 0x7a, 0x03, 0x75, 0x55, 0xba, 0xca, 0x7e, 0xbd, 0x94, 0x7d, 0xac, 0x58, 0x75, 0x2f, 0x33, 0x0a, + 0x9b, 0xd4, 0x2c, 0x82, 0x2e, 0x78, 0x23, 0xfc, 0xa0, 0xec, 0xb7, 0x02, 0xb7, 0x0b, 0xbe, 0xc0, + 0xfe, 0xd0, 0x4b, 0x99, 0xf1, 0xd4, 0xbc, 0xc4, 0x86, 0x54, 0x2b, 0x93, 0xf0, 0xf9, 0x78, 0xc3, + 0x93, 0x69, 0xf0, 0x57, 0x1d, 0x5a, 0x93, 0x98, 0xa5, 0x91, 0x48, 0xb8, 0x3a, 0x33, 0x8d, 0x96, + 0xa6, 0xd8, 0xda, 0x54, 0x7f, 0xe3, 0x04, 0xed, 0xba, 0x01, 0x68, 0xf4, 0xa9, 0x7f, 0xac, 0x13, + 0x68, 0x27, 0x2e, 0xbf, 0x15, 0x9f, 0x82, 0x97, 0x16, 0x4b, 0x3b, 0x16, 0x5d, 0xe8, 0x80, 0x26, + 0xc3, 0x51, 0x33, 0xda, 0x3e, 0x1b, 0xee, 0x84, 0xc6, 0xc7, 0xb4, 0xa1, 0x1d, 0x59, 0x6e, 0x15, + 0x7b, 0x82, 0xb1, 0xb9, 0xf9, 0xac, 0x4e, 0x30, 0x1c, 0xa9, 0x9e, 0xab, 0xab, 0x48, 0x2c, 0x8b, + 0x0c, 0x31, 0x78, 0x06, 0xd6, 0xeb, 0x96, 0xc6, 0x74, 0x8d, 0x75, 0x62, 0x8c, 0xea, 0x07, 0xe7, + 0x82, 0xa5, 0xf1, 0x5c, 0x69, 0xb9, 0x42, 0x9a, 0xca, 0xee, 0xaf, 0x1c, 0x0e, 0xfc, 0x1c, 0x7c, + 0x99, 0x45, 0x57, 0x29, 0xfe, 0xa6, 0xc4, 0xf8, 0x33, 0x74, 0xc5, 0xc5, 0x3b, 0x7d, 0x83, 0x22, + 0x75, 0x55, 0x7e, 0x5f, 0xfb, 0x4f, 0x94, 0xfb, 0x57, 0xed, 0x1d, 0x29, 0x67, 0x30, 0x84, 0xb6, + 0x4b, 0xb8, 0xc4, 0xb7, 0xbf, 0x2d, 0xdd, 0x42, 0xbf, 0xa1, 0xde, 0xe0, 0x93, 0xb5, 0x7b, 0x5b, + 0x37, 0xbd, 0x01, 0xee, 0x3f, 0x73, 0x33, 0x4a, 0xb7, 0xfb, 0x0e, 0x78, 0x93, 0xb7, 0xa7, 0xa3, + 0x70, 0x74, 0x72, 0x3c, 0x3e, 0x3d, 0xef, 0xdf, 0x21, 0x7d, 0xe8, 0x0c, 0xcb, 0x96, 0xda, 0xfe, + 0xb1, 0x6b, 0x82, 0x0a, 0x61, 0x32, 0xa6, 0x6f, 0xc6, 0xb4, 0x4c, 0xb0, 0x96, 0x1a, 0xf1, 0xe1, + 0x9e, 0xb1, 0xbc, 0x1c, 0x9f, 0x8e, 0xe9, 0xf1, 0xca, 0x53, 0xdf, 0xff, 0x1c, 0xb6, 0xed, 0xbb, + 0x44, 0xda, 0xd0, 0x7c, 0x7d, 0x3a, 0xa4, 0x6f, 0x71, 0x87, 0x2e, 0x5e, 0xea, 0x9c, 0x8e, 0x87, + 0xaf, 0x8e, 0x4f, 0x5f, 0xf6, 0x6b, 0x17, 0x5b, 0xfa, 0x97, 0xf8, 0xdb, 0xbf, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x75, 0x59, 0xf4, 0x03, 0x4e, 0x0b, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.proto b/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.proto new file mode 100644 index 00000000..e0fe0ec7 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/control.proto @@ -0,0 +1,201 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "payloads.proto"; +import "stats.proto"; + +package grpc.testing; + +enum ClientType { + SYNC_CLIENT = 0; + ASYNC_CLIENT = 1; +} + +enum ServerType { + SYNC_SERVER = 0; + ASYNC_SERVER = 1; + ASYNC_GENERIC_SERVER = 2; +} + +enum RpcType { + UNARY = 0; + STREAMING = 1; +} + +// Parameters of poisson process distribution, which is a good representation +// of activity coming in from independent identical stationary sources. +message PoissonParams { + // The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + double offered_load = 1; +} + +message UniformParams { + double interarrival_lo = 1; + double interarrival_hi = 2; +} + +message DeterministicParams { + double offered_load = 1; +} + +message ParetoParams { + double interarrival_base = 1; + double alpha = 2; +} + +// Once an RPC finishes, immediately start a new one. +// No configuration parameters needed. +message ClosedLoopParams { +} + +message LoadParams { + oneof load { + ClosedLoopParams closed_loop = 1; + PoissonParams poisson = 2; + UniformParams uniform = 3; + DeterministicParams determ = 4; + ParetoParams pareto = 5; + }; +} + +// presence of SecurityParams implies use of TLS +message SecurityParams { + bool use_test_ca = 1; + string server_host_override = 2; +} + +message ClientConfig { + // List of targets to connect to. At least one target needs to be specified. + repeated string server_targets = 1; + ClientType client_type = 2; + SecurityParams security_params = 3; + // How many concurrent RPCs to start for each channel. + // For synchronous client, use a separate thread for each outstanding RPC. + int32 outstanding_rpcs_per_channel = 4; + // Number of independent client channels to create. + // i-th channel will connect to server_target[i % server_targets.size()] + int32 client_channels = 5; + // Only for async client. Number of threads to use to start/manage RPCs. + int32 async_client_threads = 7; + RpcType rpc_type = 8; + // The requested load for the entire client (aggregated over all the threads). + LoadParams load_params = 10; + PayloadConfig payload_config = 11; + HistogramParams histogram_params = 12; + + // Specify the cores we should run the client on, if desired + repeated int32 core_list = 13; + int32 core_limit = 14; +} + +message ClientStatus { + ClientStats stats = 1; +} + +// Request current stats +message Mark { + // if true, the stats will be reset after taking their snapshot. + bool reset = 1; +} + +message ClientArgs { + oneof argtype { + ClientConfig setup = 1; + Mark mark = 2; + } +} + +message ServerConfig { + ServerType server_type = 1; + SecurityParams security_params = 2; + // Port on which to listen. Zero means pick unused port. + int32 port = 4; + // Only for async server. Number of threads used to serve the requests. + int32 async_server_threads = 7; + // Specify the number of cores to limit server to, if desired + int32 core_limit = 8; + // payload config, used in generic server + PayloadConfig payload_config = 9; + + // Specify the cores we should run the server on, if desired + repeated int32 core_list = 10; +} + +message ServerArgs { + oneof argtype { + ServerConfig setup = 1; + Mark mark = 2; + } +} + +message ServerStatus { + ServerStats stats = 1; + // the port bound by the server + int32 port = 2; + // Number of cores available to the server + int32 cores = 3; +} + +message CoreRequest { +} + +message CoreResponse { + // Number of cores available on the server + int32 cores = 1; +} + +message Void { +} + +// A single performance scenario: input to qps_json_driver +message Scenario { + // Human readable name for this scenario + string name = 1; + // Client configuration + ClientConfig client_config = 2; + // Number of clients to start for the test + int32 num_clients = 3; + // Server configuration + ServerConfig server_config = 4; + // Number of servers to start for the test + int32 num_servers = 5; + // Warmup period, in seconds + int32 warmup_seconds = 6; + // Benchmark time, in seconds + int32 benchmark_seconds = 7; + // Number of workers to spawn locally (usually zero) + int32 spawn_local_worker_count = 8; +} + +// A set of scenarios to be run with qps_json_driver +message Scenarios { + repeated Scenario scenarios = 1; +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.pb.go b/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.pb.go new file mode 100644 index 00000000..b3c8cff7 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.pb.go @@ -0,0 +1,347 @@ +// Code generated by protoc-gen-go. +// source: messages.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// The type of payload that should be returned. +type PayloadType int32 + +const ( + // Compressable text format. + PayloadType_COMPRESSABLE PayloadType = 0 + // Uncompressable binary format. + PayloadType_UNCOMPRESSABLE PayloadType = 1 + // Randomly chosen from all other formats defined in this enum. + PayloadType_RANDOM PayloadType = 2 +) + +var PayloadType_name = map[int32]string{ + 0: "COMPRESSABLE", + 1: "UNCOMPRESSABLE", + 2: "RANDOM", +} +var PayloadType_value = map[string]int32{ + "COMPRESSABLE": 0, + "UNCOMPRESSABLE": 1, + "RANDOM": 2, +} + +func (x PayloadType) String() string { + return proto.EnumName(PayloadType_name, int32(x)) +} +func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +// Compression algorithms +type CompressionType int32 + +const ( + // No compression + CompressionType_NONE CompressionType = 0 + CompressionType_GZIP CompressionType = 1 + CompressionType_DEFLATE CompressionType = 2 +) + +var CompressionType_name = map[int32]string{ + 0: "NONE", + 1: "GZIP", + 2: "DEFLATE", +} +var CompressionType_value = map[string]int32{ + "NONE": 0, + "GZIP": 1, + "DEFLATE": 2, +} + +func (x CompressionType) String() string { + return proto.EnumName(CompressionType_name, int32(x)) +} +func (CompressionType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +// A block of data, to simply increase gRPC message size. +type Payload struct { + // The type of data in body. + Type PayloadType `protobuf:"varint,1,opt,name=type,enum=grpc.testing.PayloadType" json:"type,omitempty"` + // Primary contents of payload. + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` +} + +func (m *Payload) Reset() { *m = Payload{} } +func (m *Payload) String() string { return proto.CompactTextString(m) } +func (*Payload) ProtoMessage() {} +func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +// A protobuf representation for grpc status. This is used by test +// clients to specify a status that the server should attempt to return. +type EchoStatus struct { + Code int32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` +} + +func (m *EchoStatus) Reset() { *m = EchoStatus{} } +func (m *EchoStatus) String() string { return proto.CompactTextString(m) } +func (*EchoStatus) ProtoMessage() {} +func (*EchoStatus) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +// Unary request. +type SimpleRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + ResponseSize int32 `protobuf:"varint,2,opt,name=response_size,json=responseSize" json:"response_size,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + // Whether SimpleResponse should include username. + FillUsername bool `protobuf:"varint,4,opt,name=fill_username,json=fillUsername" json:"fill_username,omitempty"` + // Whether SimpleResponse should include OAuth scope. + FillOauthScope bool `protobuf:"varint,5,opt,name=fill_oauth_scope,json=fillOauthScope" json:"fill_oauth_scope,omitempty"` + // Compression algorithm to be used by the server for the response (stream) + ResponseCompression CompressionType `protobuf:"varint,6,opt,name=response_compression,json=responseCompression,enum=grpc.testing.CompressionType" json:"response_compression,omitempty"` + // Whether server should return a given status + ResponseStatus *EchoStatus `protobuf:"bytes,7,opt,name=response_status,json=responseStatus" json:"response_status,omitempty"` +} + +func (m *SimpleRequest) Reset() { *m = SimpleRequest{} } +func (m *SimpleRequest) String() string { return proto.CompactTextString(m) } +func (*SimpleRequest) ProtoMessage() {} +func (*SimpleRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *SimpleRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *SimpleRequest) GetResponseStatus() *EchoStatus { + if m != nil { + return m.ResponseStatus + } + return nil +} + +// Unary response, as configured by the request. +type SimpleResponse struct { + // Payload to increase message size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + // The user the request came from, for verifying authentication was + // successful when the client expected it. + Username string `protobuf:"bytes,2,opt,name=username" json:"username,omitempty"` + // OAuth scope. + OauthScope string `protobuf:"bytes,3,opt,name=oauth_scope,json=oauthScope" json:"oauth_scope,omitempty"` +} + +func (m *SimpleResponse) Reset() { *m = SimpleResponse{} } +func (m *SimpleResponse) String() string { return proto.CompactTextString(m) } +func (*SimpleResponse) ProtoMessage() {} +func (*SimpleResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *SimpleResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Client-streaming request. +type StreamingInputCallRequest struct { + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` +} + +func (m *StreamingInputCallRequest) Reset() { *m = StreamingInputCallRequest{} } +func (m *StreamingInputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallRequest) ProtoMessage() {} +func (*StreamingInputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *StreamingInputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Client-streaming response. +type StreamingInputCallResponse struct { + // Aggregated size of payloads received from the client. + AggregatedPayloadSize int32 `protobuf:"varint,1,opt,name=aggregated_payload_size,json=aggregatedPayloadSize" json:"aggregated_payload_size,omitempty"` +} + +func (m *StreamingInputCallResponse) Reset() { *m = StreamingInputCallResponse{} } +func (m *StreamingInputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallResponse) ProtoMessage() {} +func (*StreamingInputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +// Configuration for a particular response. +type ResponseParameters struct { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + Size int32 `protobuf:"varint,1,opt,name=size" json:"size,omitempty"` + // Desired interval between consecutive responses in the response stream in + // microseconds. + IntervalUs int32 `protobuf:"varint,2,opt,name=interval_us,json=intervalUs" json:"interval_us,omitempty"` +} + +func (m *ResponseParameters) Reset() { *m = ResponseParameters{} } +func (m *ResponseParameters) String() string { return proto.CompactTextString(m) } +func (*ResponseParameters) ProtoMessage() {} +func (*ResponseParameters) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +// Server-streaming request. +type StreamingOutputCallRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Configuration for each expected response message. + ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters,json=responseParameters" json:"response_parameters,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + // Compression algorithm to be used by the server for the response (stream) + ResponseCompression CompressionType `protobuf:"varint,6,opt,name=response_compression,json=responseCompression,enum=grpc.testing.CompressionType" json:"response_compression,omitempty"` + // Whether server should return a given status + ResponseStatus *EchoStatus `protobuf:"bytes,7,opt,name=response_status,json=responseStatus" json:"response_status,omitempty"` +} + +func (m *StreamingOutputCallRequest) Reset() { *m = StreamingOutputCallRequest{} } +func (m *StreamingOutputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallRequest) ProtoMessage() {} +func (*StreamingOutputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +func (m *StreamingOutputCallRequest) GetResponseParameters() []*ResponseParameters { + if m != nil { + return m.ResponseParameters + } + return nil +} + +func (m *StreamingOutputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *StreamingOutputCallRequest) GetResponseStatus() *EchoStatus { + if m != nil { + return m.ResponseStatus + } + return nil +} + +// Server-streaming response, as configured by the request and parameters. +type StreamingOutputCallResponse struct { + // Payload to increase response size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` +} + +func (m *StreamingOutputCallResponse) Reset() { *m = StreamingOutputCallResponse{} } +func (m *StreamingOutputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallResponse) ProtoMessage() {} +func (*StreamingOutputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } + +func (m *StreamingOutputCallResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// For reconnect interop test only. +// Client tells server what reconnection parameters it used. +type ReconnectParams struct { + MaxReconnectBackoffMs int32 `protobuf:"varint,1,opt,name=max_reconnect_backoff_ms,json=maxReconnectBackoffMs" json:"max_reconnect_backoff_ms,omitempty"` +} + +func (m *ReconnectParams) Reset() { *m = ReconnectParams{} } +func (m *ReconnectParams) String() string { return proto.CompactTextString(m) } +func (*ReconnectParams) ProtoMessage() {} +func (*ReconnectParams) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } + +// For reconnect interop test only. +// Server tells client whether its reconnects are following the spec and the +// reconnect backoffs it saw. +type ReconnectInfo struct { + Passed bool `protobuf:"varint,1,opt,name=passed" json:"passed,omitempty"` + BackoffMs []int32 `protobuf:"varint,2,rep,name=backoff_ms,json=backoffMs" json:"backoff_ms,omitempty"` +} + +func (m *ReconnectInfo) Reset() { *m = ReconnectInfo{} } +func (m *ReconnectInfo) String() string { return proto.CompactTextString(m) } +func (*ReconnectInfo) ProtoMessage() {} +func (*ReconnectInfo) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } + +func init() { + proto.RegisterType((*Payload)(nil), "grpc.testing.Payload") + proto.RegisterType((*EchoStatus)(nil), "grpc.testing.EchoStatus") + proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest") + proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse") + proto.RegisterType((*StreamingInputCallRequest)(nil), "grpc.testing.StreamingInputCallRequest") + proto.RegisterType((*StreamingInputCallResponse)(nil), "grpc.testing.StreamingInputCallResponse") + proto.RegisterType((*ResponseParameters)(nil), "grpc.testing.ResponseParameters") + proto.RegisterType((*StreamingOutputCallRequest)(nil), "grpc.testing.StreamingOutputCallRequest") + proto.RegisterType((*StreamingOutputCallResponse)(nil), "grpc.testing.StreamingOutputCallResponse") + proto.RegisterType((*ReconnectParams)(nil), "grpc.testing.ReconnectParams") + proto.RegisterType((*ReconnectInfo)(nil), "grpc.testing.ReconnectInfo") + proto.RegisterEnum("grpc.testing.PayloadType", PayloadType_name, PayloadType_value) + proto.RegisterEnum("grpc.testing.CompressionType", CompressionType_name, CompressionType_value) +} + +func init() { proto.RegisterFile("messages.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 645 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x55, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x25, 0xdf, 0xe9, 0x24, 0x4d, 0xa3, 0x85, 0x82, 0x5b, 0x54, 0x51, 0x99, 0x4b, 0x55, 0x89, + 0x20, 0x15, 0x09, 0x24, 0x0e, 0xa0, 0xb4, 0x4d, 0x51, 0x50, 0x9b, 0x84, 0x75, 0x7b, 0xe1, 0x62, + 0x6d, 0x9c, 0x4d, 0x1a, 0x11, 0x7b, 0x8d, 0x77, 0x8d, 0x28, 0x07, 0xee, 0xfc, 0x60, 0xee, 0xec, + 0xae, 0xbd, 0x8e, 0xd3, 0xf6, 0xd0, 0xc2, 0x85, 0xdb, 0xce, 0xcc, 0x9b, 0x97, 0x79, 0x33, 0xcf, + 0x0a, 0xb4, 0x7c, 0xca, 0x39, 0x99, 0x51, 0xde, 0x09, 0x23, 0x26, 0x18, 0x6a, 0xce, 0xa2, 0xd0, + 0xeb, 0x08, 0xca, 0xc5, 0x3c, 0x98, 0xd9, 0xa7, 0x50, 0x1b, 0x91, 0xab, 0x05, 0x23, 0x13, 0xf4, + 0x02, 0xca, 0xe2, 0x2a, 0xa4, 0x56, 0x61, 0xb7, 0xb0, 0xd7, 0x3a, 0xd8, 0xea, 0xe4, 0x71, 0x9d, + 0x14, 0x74, 0x2e, 0x01, 0x58, 0xc3, 0x10, 0x82, 0xf2, 0x98, 0x4d, 0xae, 0xac, 0xa2, 0x84, 0x37, + 0xb1, 0x7e, 0xdb, 0x6f, 0x01, 0x7a, 0xde, 0x25, 0x73, 0x04, 0x11, 0x31, 0x57, 0x08, 0x8f, 0x4d, + 0x12, 0xc2, 0x0a, 0xd6, 0x6f, 0x64, 0x41, 0x2d, 0x9d, 0x47, 0x37, 0xae, 0x61, 0x13, 0xda, 0xbf, + 0x4a, 0xb0, 0xee, 0xcc, 0xfd, 0x70, 0x41, 0x31, 0xfd, 0x1a, 0xcb, 0x9f, 0x45, 0xef, 0x60, 0x3d, + 0xa2, 0x3c, 0x64, 0x01, 0xa7, 0xee, 0xdd, 0x26, 0x6b, 0x1a, 0xbc, 0x8a, 0xd0, 0xf3, 0x5c, 0x3f, + 0x9f, 0xff, 0x48, 0x7e, 0xb1, 0xb2, 0x04, 0x39, 0x32, 0x87, 0x5e, 0x42, 0x2d, 0x4c, 0x18, 0xac, + 0x92, 0x2c, 0x37, 0x0e, 0x36, 0x6f, 0xa5, 0xc7, 0x06, 0xa5, 0x58, 0xa7, 0xf3, 0xc5, 0xc2, 0x8d, + 0x39, 0x8d, 0x02, 0xe2, 0x53, 0xab, 0x2c, 0xdb, 0xea, 0xb8, 0xa9, 0x92, 0x17, 0x69, 0x0e, 0xed, + 0x41, 0x5b, 0x83, 0x18, 0x89, 0xc5, 0xa5, 0xcb, 0x3d, 0x26, 0xa7, 0xaf, 0x68, 0x5c, 0x4b, 0xe5, + 0x87, 0x2a, 0xed, 0xa8, 0x2c, 0x1a, 0xc1, 0xa3, 0x6c, 0x48, 0x8f, 0xf9, 0xa1, 0x0c, 0xf8, 0x9c, + 0x05, 0x56, 0x55, 0x6b, 0xdd, 0x59, 0x1d, 0xe6, 0x68, 0x09, 0xd0, 0x7a, 0x1f, 0x9a, 0xd6, 0x5c, + 0x01, 0x75, 0x61, 0x63, 0x29, 0x5b, 0x5f, 0xc2, 0xaa, 0x69, 0x65, 0xd6, 0x2a, 0xd9, 0xf2, 0x52, + 0xb8, 0x95, 0xad, 0x44, 0xc7, 0xf6, 0x4f, 0x68, 0x99, 0x53, 0x24, 0xf9, 0xfc, 0x9a, 0x0a, 0x77, + 0x5a, 0xd3, 0x36, 0xd4, 0xb3, 0x0d, 0x25, 0x97, 0xce, 0x62, 0xf4, 0x0c, 0x1a, 0xf9, 0xc5, 0x94, + 0x74, 0x19, 0x58, 0xb6, 0x14, 0xe9, 0xca, 0x2d, 0x47, 0x44, 0x94, 0xf8, 0x92, 0xba, 0x1f, 0x84, + 0xb1, 0x38, 0x22, 0x8b, 0x85, 0xb1, 0xc5, 0x7d, 0x47, 0xb1, 0xcf, 0x61, 0xfb, 0x36, 0xb6, 0x54, + 0xd9, 0x6b, 0x78, 0x42, 0x66, 0xb3, 0x88, 0xce, 0x88, 0xa0, 0x13, 0x37, 0xed, 0x49, 0xfc, 0x92, + 0x18, 0x77, 0x73, 0x59, 0x4e, 0xa9, 0x95, 0x71, 0xec, 0x3e, 0x20, 0xc3, 0x31, 0x22, 0x91, 0x94, + 0x25, 0x68, 0xa4, 0x3d, 0x9f, 0x6b, 0xd5, 0x6f, 0x25, 0x77, 0x1e, 0xc8, 0xea, 0x37, 0xa2, 0x5c, + 0x93, 0xba, 0x10, 0x4c, 0xea, 0x82, 0xdb, 0xbf, 0x8b, 0xb9, 0x09, 0x87, 0xb1, 0xb8, 0x26, 0xf8, + 0x5f, 0xbf, 0x83, 0x4f, 0x90, 0xf9, 0x44, 0xea, 0x33, 0xa3, 0xca, 0x39, 0x4a, 0x72, 0x79, 0xbb, + 0xab, 0x2c, 0x37, 0x25, 0x61, 0x14, 0xdd, 0x94, 0x79, 0xef, 0xaf, 0xe6, 0xbf, 0xb4, 0xf9, 0x00, + 0x9e, 0xde, 0xba, 0xf6, 0xbf, 0xf4, 0xbc, 0xfd, 0x11, 0x36, 0x30, 0xf5, 0x58, 0x10, 0x50, 0x4f, + 0xe8, 0x65, 0x71, 0xf4, 0x06, 0x2c, 0x9f, 0x7c, 0x77, 0x23, 0x93, 0x76, 0xc7, 0xc4, 0xfb, 0xc2, + 0xa6, 0x53, 0xd7, 0xe7, 0xc6, 0x5e, 0xb2, 0x9e, 0x75, 0x1d, 0x26, 0xd5, 0x33, 0x6e, 0x9f, 0xc0, + 0x7a, 0x96, 0xed, 0x07, 0x53, 0x86, 0x1e, 0x43, 0x35, 0x24, 0x9c, 0xd3, 0x64, 0x98, 0x3a, 0x4e, + 0x23, 0xb4, 0x03, 0x90, 0xe3, 0x54, 0x47, 0xad, 0xe0, 0xb5, 0xb1, 0xe1, 0xd9, 0x7f, 0x0f, 0x8d, + 0x9c, 0x33, 0x50, 0x1b, 0x9a, 0x47, 0xc3, 0xb3, 0x11, 0xee, 0x39, 0x4e, 0xf7, 0xf0, 0xb4, 0xd7, + 0x7e, 0x20, 0x1d, 0xdb, 0xba, 0x18, 0xac, 0xe4, 0x0a, 0x08, 0xa0, 0x8a, 0xbb, 0x83, 0xe3, 0xe1, + 0x59, 0xbb, 0xb8, 0x7f, 0x00, 0x1b, 0xd7, 0xee, 0x81, 0xea, 0x50, 0x1e, 0x0c, 0x07, 0xaa, 0x59, + 0xbe, 0x3e, 0x7c, 0xee, 0x8f, 0x64, 0x4b, 0x03, 0x6a, 0xc7, 0xbd, 0x93, 0xd3, 0xee, 0x79, 0xaf, + 0x5d, 0x1c, 0x57, 0xf5, 0x5f, 0xcd, 0xab, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc2, 0x6a, 0xce, + 0x1e, 0x7c, 0x06, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.proto b/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.proto new file mode 100644 index 00000000..b1abc9e8 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/messages.proto @@ -0,0 +1,172 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Message definitions to be used by integration test service definitions. + +syntax = "proto3"; + +package grpc.testing; + +// The type of payload that should be returned. +enum PayloadType { + // Compressable text format. + COMPRESSABLE = 0; + + // Uncompressable binary format. + UNCOMPRESSABLE = 1; + + // Randomly chosen from all other formats defined in this enum. + RANDOM = 2; +} + +// Compression algorithms +enum CompressionType { + // No compression + NONE = 0; + GZIP = 1; + DEFLATE = 2; +} + +// A block of data, to simply increase gRPC message size. +message Payload { + // The type of data in body. + PayloadType type = 1; + // Primary contents of payload. + bytes body = 2; +} + +// A protobuf representation for grpc status. This is used by test +// clients to specify a status that the server should attempt to return. +message EchoStatus { + int32 code = 1; + string message = 2; +} + +// Unary request. +message SimpleRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + PayloadType response_type = 1; + + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + int32 response_size = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; + + // Whether SimpleResponse should include username. + bool fill_username = 4; + + // Whether SimpleResponse should include OAuth scope. + bool fill_oauth_scope = 5; + + // Compression algorithm to be used by the server for the response (stream) + CompressionType response_compression = 6; + + // Whether server should return a given status + EchoStatus response_status = 7; +} + +// Unary response, as configured by the request. +message SimpleResponse { + // Payload to increase message size. + Payload payload = 1; + // The user the request came from, for verifying authentication was + // successful when the client expected it. + string username = 2; + // OAuth scope. + string oauth_scope = 3; +} + +// Client-streaming request. +message StreamingInputCallRequest { + // Optional input payload sent along with the request. + Payload payload = 1; + + // Not expecting any payload from the response. +} + +// Client-streaming response. +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + int32 aggregated_payload_size = 1; +} + +// Configuration for a particular response. +message ResponseParameters { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + int32 interval_us = 2; +} + +// Server-streaming request. +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + PayloadType response_type = 1; + + // Configuration for each expected response message. + repeated ResponseParameters response_parameters = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; + + // Compression algorithm to be used by the server for the response (stream) + CompressionType response_compression = 6; + + // Whether server should return a given status + EchoStatus response_status = 7; +} + +// Server-streaming response, as configured by the request and parameters. +message StreamingOutputCallResponse { + // Payload to increase response size. + Payload payload = 1; +} + +// For reconnect interop test only. +// Client tells server what reconnection parameters it used. +message ReconnectParams { + int32 max_reconnect_backoff_ms = 1; +} + +// For reconnect interop test only. +// Server tells client whether its reconnects are following the spec and the +// reconnect backoffs it saw. +message ReconnectInfo { + bool passed = 1; + repeated int32 backoff_ms = 2; +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.pb.go b/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.pb.go new file mode 100644 index 00000000..ffc357d8 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.pb.go @@ -0,0 +1,223 @@ +// Code generated by protoc-gen-go. +// source: payloads.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ByteBufferParams struct { + ReqSize int32 `protobuf:"varint,1,opt,name=req_size,json=reqSize" json:"req_size,omitempty"` + RespSize int32 `protobuf:"varint,2,opt,name=resp_size,json=respSize" json:"resp_size,omitempty"` +} + +func (m *ByteBufferParams) Reset() { *m = ByteBufferParams{} } +func (m *ByteBufferParams) String() string { return proto.CompactTextString(m) } +func (*ByteBufferParams) ProtoMessage() {} +func (*ByteBufferParams) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +type SimpleProtoParams struct { + ReqSize int32 `protobuf:"varint,1,opt,name=req_size,json=reqSize" json:"req_size,omitempty"` + RespSize int32 `protobuf:"varint,2,opt,name=resp_size,json=respSize" json:"resp_size,omitempty"` +} + +func (m *SimpleProtoParams) Reset() { *m = SimpleProtoParams{} } +func (m *SimpleProtoParams) String() string { return proto.CompactTextString(m) } +func (*SimpleProtoParams) ProtoMessage() {} +func (*SimpleProtoParams) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +type ComplexProtoParams struct { +} + +func (m *ComplexProtoParams) Reset() { *m = ComplexProtoParams{} } +func (m *ComplexProtoParams) String() string { return proto.CompactTextString(m) } +func (*ComplexProtoParams) ProtoMessage() {} +func (*ComplexProtoParams) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } + +type PayloadConfig struct { + // Types that are valid to be assigned to Payload: + // *PayloadConfig_BytebufParams + // *PayloadConfig_SimpleParams + // *PayloadConfig_ComplexParams + Payload isPayloadConfig_Payload `protobuf_oneof:"payload"` +} + +func (m *PayloadConfig) Reset() { *m = PayloadConfig{} } +func (m *PayloadConfig) String() string { return proto.CompactTextString(m) } +func (*PayloadConfig) ProtoMessage() {} +func (*PayloadConfig) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } + +type isPayloadConfig_Payload interface { + isPayloadConfig_Payload() +} + +type PayloadConfig_BytebufParams struct { + BytebufParams *ByteBufferParams `protobuf:"bytes,1,opt,name=bytebuf_params,json=bytebufParams,oneof"` +} +type PayloadConfig_SimpleParams struct { + SimpleParams *SimpleProtoParams `protobuf:"bytes,2,opt,name=simple_params,json=simpleParams,oneof"` +} +type PayloadConfig_ComplexParams struct { + ComplexParams *ComplexProtoParams `protobuf:"bytes,3,opt,name=complex_params,json=complexParams,oneof"` +} + +func (*PayloadConfig_BytebufParams) isPayloadConfig_Payload() {} +func (*PayloadConfig_SimpleParams) isPayloadConfig_Payload() {} +func (*PayloadConfig_ComplexParams) isPayloadConfig_Payload() {} + +func (m *PayloadConfig) GetPayload() isPayloadConfig_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *PayloadConfig) GetBytebufParams() *ByteBufferParams { + if x, ok := m.GetPayload().(*PayloadConfig_BytebufParams); ok { + return x.BytebufParams + } + return nil +} + +func (m *PayloadConfig) GetSimpleParams() *SimpleProtoParams { + if x, ok := m.GetPayload().(*PayloadConfig_SimpleParams); ok { + return x.SimpleParams + } + return nil +} + +func (m *PayloadConfig) GetComplexParams() *ComplexProtoParams { + if x, ok := m.GetPayload().(*PayloadConfig_ComplexParams); ok { + return x.ComplexParams + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*PayloadConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _PayloadConfig_OneofMarshaler, _PayloadConfig_OneofUnmarshaler, _PayloadConfig_OneofSizer, []interface{}{ + (*PayloadConfig_BytebufParams)(nil), + (*PayloadConfig_SimpleParams)(nil), + (*PayloadConfig_ComplexParams)(nil), + } +} + +func _PayloadConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*PayloadConfig) + // payload + switch x := m.Payload.(type) { + case *PayloadConfig_BytebufParams: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BytebufParams); err != nil { + return err + } + case *PayloadConfig_SimpleParams: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.SimpleParams); err != nil { + return err + } + case *PayloadConfig_ComplexParams: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ComplexParams); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("PayloadConfig.Payload has unexpected type %T", x) + } + return nil +} + +func _PayloadConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*PayloadConfig) + switch tag { + case 1: // payload.bytebuf_params + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ByteBufferParams) + err := b.DecodeMessage(msg) + m.Payload = &PayloadConfig_BytebufParams{msg} + return true, err + case 2: // payload.simple_params + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(SimpleProtoParams) + err := b.DecodeMessage(msg) + m.Payload = &PayloadConfig_SimpleParams{msg} + return true, err + case 3: // payload.complex_params + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ComplexProtoParams) + err := b.DecodeMessage(msg) + m.Payload = &PayloadConfig_ComplexParams{msg} + return true, err + default: + return false, nil + } +} + +func _PayloadConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*PayloadConfig) + // payload + switch x := m.Payload.(type) { + case *PayloadConfig_BytebufParams: + s := proto.Size(x.BytebufParams) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PayloadConfig_SimpleParams: + s := proto.Size(x.SimpleParams) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PayloadConfig_ComplexParams: + s := proto.Size(x.ComplexParams) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +func init() { + proto.RegisterType((*ByteBufferParams)(nil), "grpc.testing.ByteBufferParams") + proto.RegisterType((*SimpleProtoParams)(nil), "grpc.testing.SimpleProtoParams") + proto.RegisterType((*ComplexProtoParams)(nil), "grpc.testing.ComplexProtoParams") + proto.RegisterType((*PayloadConfig)(nil), "grpc.testing.PayloadConfig") +} + +func init() { proto.RegisterFile("payloads.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 250 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x48, 0xac, 0xcc, + 0xc9, 0x4f, 0x4c, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x49, 0x2f, 0x2a, 0x48, + 0xd6, 0x2b, 0x49, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0x57, 0xf2, 0xe2, 0x12, 0x70, 0xaa, 0x2c, 0x49, + 0x75, 0x2a, 0x4d, 0x4b, 0x4b, 0x2d, 0x0a, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0x16, 0x92, 0xe4, 0xe2, + 0x28, 0x4a, 0x2d, 0x8c, 0x2f, 0xce, 0xac, 0x4a, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0d, 0x62, + 0x07, 0xf2, 0x83, 0x81, 0x5c, 0x21, 0x69, 0x2e, 0xce, 0xa2, 0xd4, 0xe2, 0x02, 0x88, 0x1c, 0x13, + 0x58, 0x8e, 0x03, 0x24, 0x00, 0x92, 0x54, 0xf2, 0xe6, 0x12, 0x0c, 0xce, 0xcc, 0x2d, 0xc8, 0x49, + 0x0d, 0x00, 0x59, 0x44, 0xa1, 0x61, 0x22, 0x5c, 0x42, 0xce, 0xf9, 0x20, 0xc3, 0x2a, 0x90, 0x4c, + 0x53, 0xfa, 0xc6, 0xc8, 0xc5, 0x1b, 0x00, 0xf1, 0x8f, 0x73, 0x7e, 0x5e, 0x5a, 0x66, 0xba, 0x90, + 0x3b, 0x17, 0x5f, 0x12, 0xd0, 0x03, 0x49, 0xa5, 0x69, 0xf1, 0x05, 0x60, 0x35, 0x60, 0x5b, 0xb8, + 0x8d, 0xe4, 0xf4, 0x90, 0xfd, 0xa9, 0x87, 0xee, 0x49, 0x0f, 0x86, 0x20, 0x5e, 0xa8, 0x3e, 0xa8, + 0x43, 0xdd, 0xb8, 0x78, 0x8b, 0xc1, 0xae, 0x87, 0x99, 0xc3, 0x04, 0x36, 0x47, 0x1e, 0xd5, 0x1c, + 0x0c, 0x0f, 0x02, 0x0d, 0xe2, 0x81, 0xe8, 0x83, 0x9a, 0xe3, 0xc9, 0xc5, 0x97, 0x0c, 0x71, 0x38, + 0xcc, 0x20, 0x66, 0xb0, 0x41, 0x0a, 0xa8, 0x06, 0x61, 0x7a, 0x0e, 0xe4, 0x24, 0xa8, 0x4e, 0x88, + 0x80, 0x13, 0x27, 0x17, 0x3b, 0x34, 0xf2, 0x92, 0xd8, 0xc0, 0x91, 0x67, 0x0c, 0x08, 0x00, 0x00, + 0xff, 0xff, 0xb0, 0x8c, 0x18, 0x4e, 0xce, 0x01, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.proto b/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.proto new file mode 100644 index 00000000..056fe0c7 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/payloads.proto @@ -0,0 +1,55 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.testing; + +message ByteBufferParams { + int32 req_size = 1; + int32 resp_size = 2; +} + +message SimpleProtoParams { + int32 req_size = 1; + int32 resp_size = 2; +} + +message ComplexProtoParams { + // TODO (vpai): Fill this in once the details of complex, representative + // protos are decided +} + +message PayloadConfig { + oneof payload { + ByteBufferParams bytebuf_params = 1; + SimpleProtoParams simple_params = 2; + ComplexProtoParams complex_params = 3; + } +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.pb.go b/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.pb.go new file mode 100644 index 00000000..15d08644 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.pb.go @@ -0,0 +1,443 @@ +// Code generated by protoc-gen-go. +// source: services.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for BenchmarkService service + +type BenchmarkServiceClient interface { + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) + // One request followed by one response. + // The server returns the client payload as-is. + StreamingCall(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingCallClient, error) +} + +type benchmarkServiceClient struct { + cc *grpc.ClientConn +} + +func NewBenchmarkServiceClient(cc *grpc.ClientConn) BenchmarkServiceClient { + return &benchmarkServiceClient{cc} +} + +func (c *benchmarkServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) { + out := new(SimpleResponse) + err := grpc.Invoke(ctx, "/grpc.testing.BenchmarkService/UnaryCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *benchmarkServiceClient) StreamingCall(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_BenchmarkService_serviceDesc.Streams[0], c.cc, "/grpc.testing.BenchmarkService/StreamingCall", opts...) + if err != nil { + return nil, err + } + x := &benchmarkServiceStreamingCallClient{stream} + return x, nil +} + +type BenchmarkService_StreamingCallClient interface { + Send(*SimpleRequest) error + Recv() (*SimpleResponse, error) + grpc.ClientStream +} + +type benchmarkServiceStreamingCallClient struct { + grpc.ClientStream +} + +func (x *benchmarkServiceStreamingCallClient) Send(m *SimpleRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *benchmarkServiceStreamingCallClient) Recv() (*SimpleResponse, error) { + m := new(SimpleResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for BenchmarkService service + +type BenchmarkServiceServer interface { + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) + // One request followed by one response. + // The server returns the client payload as-is. + StreamingCall(BenchmarkService_StreamingCallServer) error +} + +func RegisterBenchmarkServiceServer(s *grpc.Server, srv BenchmarkServiceServer) { + s.RegisterService(&_BenchmarkService_serviceDesc, srv) +} + +func _BenchmarkService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SimpleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BenchmarkServiceServer).UnaryCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.BenchmarkService/UnaryCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BenchmarkServiceServer).UnaryCall(ctx, req.(*SimpleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _BenchmarkService_StreamingCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(BenchmarkServiceServer).StreamingCall(&benchmarkServiceStreamingCallServer{stream}) +} + +type BenchmarkService_StreamingCallServer interface { + Send(*SimpleResponse) error + Recv() (*SimpleRequest, error) + grpc.ServerStream +} + +type benchmarkServiceStreamingCallServer struct { + grpc.ServerStream +} + +func (x *benchmarkServiceStreamingCallServer) Send(m *SimpleResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *benchmarkServiceStreamingCallServer) Recv() (*SimpleRequest, error) { + m := new(SimpleRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _BenchmarkService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.BenchmarkService", + HandlerType: (*BenchmarkServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UnaryCall", + Handler: _BenchmarkService_UnaryCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamingCall", + Handler: _BenchmarkService_StreamingCall_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor3, +} + +// Client API for WorkerService service + +type WorkerServiceClient interface { + // Start server with specified workload. + // First request sent specifies the ServerConfig followed by ServerStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test server + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + RunServer(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunServerClient, error) + // Start client with specified workload. + // First request sent specifies the ClientConfig followed by ClientStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test client + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + RunClient(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunClientClient, error) + // Just return the core count - unary call + CoreCount(ctx context.Context, in *CoreRequest, opts ...grpc.CallOption) (*CoreResponse, error) + // Quit this worker + QuitWorker(ctx context.Context, in *Void, opts ...grpc.CallOption) (*Void, error) +} + +type workerServiceClient struct { + cc *grpc.ClientConn +} + +func NewWorkerServiceClient(cc *grpc.ClientConn) WorkerServiceClient { + return &workerServiceClient{cc} +} + +func (c *workerServiceClient) RunServer(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunServerClient, error) { + stream, err := grpc.NewClientStream(ctx, &_WorkerService_serviceDesc.Streams[0], c.cc, "/grpc.testing.WorkerService/RunServer", opts...) + if err != nil { + return nil, err + } + x := &workerServiceRunServerClient{stream} + return x, nil +} + +type WorkerService_RunServerClient interface { + Send(*ServerArgs) error + Recv() (*ServerStatus, error) + grpc.ClientStream +} + +type workerServiceRunServerClient struct { + grpc.ClientStream +} + +func (x *workerServiceRunServerClient) Send(m *ServerArgs) error { + return x.ClientStream.SendMsg(m) +} + +func (x *workerServiceRunServerClient) Recv() (*ServerStatus, error) { + m := new(ServerStatus) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *workerServiceClient) RunClient(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunClientClient, error) { + stream, err := grpc.NewClientStream(ctx, &_WorkerService_serviceDesc.Streams[1], c.cc, "/grpc.testing.WorkerService/RunClient", opts...) + if err != nil { + return nil, err + } + x := &workerServiceRunClientClient{stream} + return x, nil +} + +type WorkerService_RunClientClient interface { + Send(*ClientArgs) error + Recv() (*ClientStatus, error) + grpc.ClientStream +} + +type workerServiceRunClientClient struct { + grpc.ClientStream +} + +func (x *workerServiceRunClientClient) Send(m *ClientArgs) error { + return x.ClientStream.SendMsg(m) +} + +func (x *workerServiceRunClientClient) Recv() (*ClientStatus, error) { + m := new(ClientStatus) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *workerServiceClient) CoreCount(ctx context.Context, in *CoreRequest, opts ...grpc.CallOption) (*CoreResponse, error) { + out := new(CoreResponse) + err := grpc.Invoke(ctx, "/grpc.testing.WorkerService/CoreCount", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workerServiceClient) QuitWorker(ctx context.Context, in *Void, opts ...grpc.CallOption) (*Void, error) { + out := new(Void) + err := grpc.Invoke(ctx, "/grpc.testing.WorkerService/QuitWorker", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for WorkerService service + +type WorkerServiceServer interface { + // Start server with specified workload. + // First request sent specifies the ServerConfig followed by ServerStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test server + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + RunServer(WorkerService_RunServerServer) error + // Start client with specified workload. + // First request sent specifies the ClientConfig followed by ClientStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test client + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + RunClient(WorkerService_RunClientServer) error + // Just return the core count - unary call + CoreCount(context.Context, *CoreRequest) (*CoreResponse, error) + // Quit this worker + QuitWorker(context.Context, *Void) (*Void, error) +} + +func RegisterWorkerServiceServer(s *grpc.Server, srv WorkerServiceServer) { + s.RegisterService(&_WorkerService_serviceDesc, srv) +} + +func _WorkerService_RunServer_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(WorkerServiceServer).RunServer(&workerServiceRunServerServer{stream}) +} + +type WorkerService_RunServerServer interface { + Send(*ServerStatus) error + Recv() (*ServerArgs, error) + grpc.ServerStream +} + +type workerServiceRunServerServer struct { + grpc.ServerStream +} + +func (x *workerServiceRunServerServer) Send(m *ServerStatus) error { + return x.ServerStream.SendMsg(m) +} + +func (x *workerServiceRunServerServer) Recv() (*ServerArgs, error) { + m := new(ServerArgs) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _WorkerService_RunClient_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(WorkerServiceServer).RunClient(&workerServiceRunClientServer{stream}) +} + +type WorkerService_RunClientServer interface { + Send(*ClientStatus) error + Recv() (*ClientArgs, error) + grpc.ServerStream +} + +type workerServiceRunClientServer struct { + grpc.ServerStream +} + +func (x *workerServiceRunClientServer) Send(m *ClientStatus) error { + return x.ServerStream.SendMsg(m) +} + +func (x *workerServiceRunClientServer) Recv() (*ClientArgs, error) { + m := new(ClientArgs) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _WorkerService_CoreCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CoreRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).CoreCount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.WorkerService/CoreCount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).CoreCount(ctx, req.(*CoreRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkerService_QuitWorker_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Void) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).QuitWorker(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.WorkerService/QuitWorker", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).QuitWorker(ctx, req.(*Void)) + } + return interceptor(ctx, in, info, handler) +} + +var _WorkerService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.WorkerService", + HandlerType: (*WorkerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CoreCount", + Handler: _WorkerService_CoreCount_Handler, + }, + { + MethodName: "QuitWorker", + Handler: _WorkerService_QuitWorker_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "RunServer", + Handler: _WorkerService_RunServer_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "RunClient", + Handler: _WorkerService_RunClient_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor3, +} + +func init() { proto.RegisterFile("services.proto", fileDescriptor3) } + +var fileDescriptor3 = []byte{ + // 254 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x91, 0xc1, 0x4a, 0xc4, 0x30, + 0x10, 0x86, 0xa9, 0x07, 0xa1, 0xc1, 0x2e, 0x92, 0x93, 0x46, 0x1f, 0xc0, 0x53, 0x91, 0xd5, 0x17, + 0x70, 0x8b, 0x1e, 0x05, 0xb7, 0xa8, 0xe7, 0x58, 0x87, 0x1a, 0x36, 0x4d, 0xea, 0xcc, 0x44, 0xf0, + 0x49, 0x7c, 0x07, 0x9f, 0xd2, 0xee, 0x66, 0x0b, 0xb5, 0xe4, 0xb6, 0xc7, 0xf9, 0xbf, 0xe1, 0x23, + 0x7f, 0x46, 0x2c, 0x08, 0xf0, 0xcb, 0x34, 0x40, 0x65, 0x8f, 0x9e, 0xbd, 0x3c, 0x69, 0xb1, 0x6f, + 0x4a, 0x06, 0x62, 0xe3, 0x5a, 0xb5, 0xe8, 0x80, 0x48, 0xb7, 0x23, 0x55, 0x45, 0xe3, 0x1d, 0xa3, + 0xb7, 0x71, 0x5c, 0xfe, 0x66, 0xe2, 0x74, 0x05, 0xae, 0xf9, 0xe8, 0x34, 0x6e, 0xea, 0x28, 0x92, + 0x0f, 0x22, 0x7f, 0x76, 0x1a, 0xbf, 0x2b, 0x6d, 0xad, 0xbc, 0x28, 0xa7, 0xbe, 0xb2, 0x36, 0x5d, + 0x6f, 0x61, 0x0d, 0x9f, 0x61, 0x08, 0xd4, 0x65, 0x1a, 0x52, 0xef, 0x1d, 0x81, 0x7c, 0x14, 0x45, + 0xcd, 0x08, 0xba, 0x1b, 0xd8, 0x81, 0xae, 0xab, 0xec, 0x3a, 0x5b, 0xfe, 0x1c, 0x89, 0xe2, 0xd5, + 0xe3, 0x06, 0x70, 0x7c, 0xe9, 0xbd, 0xc8, 0xd7, 0xc1, 0x6d, 0x27, 0x40, 0x79, 0x36, 0x13, 0xec, + 0xd2, 0x3b, 0x6c, 0x49, 0xa9, 0x14, 0xa9, 0x59, 0x73, 0xa0, 0xad, 0x78, 0xaf, 0xa9, 0xac, 0x01, + 0xc7, 0x73, 0x4d, 0x4c, 0x53, 0x9a, 0x48, 0x26, 0x9a, 0x95, 0xc8, 0x2b, 0x8f, 0x50, 0xf9, 0x30, + 0x68, 0xce, 0x67, 0xcb, 0x03, 0x18, 0x9b, 0xaa, 0x14, 0xda, 0xff, 0xd9, 0xad, 0x10, 0x4f, 0xc1, + 0x70, 0xac, 0x29, 0xe5, 0xff, 0xcd, 0x17, 0x6f, 0xde, 0x55, 0x22, 0x7b, 0x3b, 0xde, 0x5d, 0xf3, + 0xe6, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x3b, 0x84, 0x02, 0xe3, 0x0c, 0x02, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.proto b/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.proto new file mode 100644 index 00000000..c2acca7f --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/services.proto @@ -0,0 +1,71 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +syntax = "proto3"; + +import "messages.proto"; +import "control.proto"; + +package grpc.testing; + +service BenchmarkService { + // One request followed by one response. + // The server returns the client payload as-is. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by one response. + // The server returns the client payload as-is. + rpc StreamingCall(stream SimpleRequest) returns (stream SimpleResponse); +} + +service WorkerService { + // Start server with specified workload. + // First request sent specifies the ServerConfig followed by ServerStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test server + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + rpc RunServer(stream ServerArgs) returns (stream ServerStatus); + + // Start client with specified workload. + // First request sent specifies the ClientConfig followed by ClientStatus + // response. After that, a "Mark" can be sent anytime to request the latest + // stats. Closing the stream will initiate shutdown of the test client + // and once the shutdown has finished, the OK status is sent to terminate + // this RPC. + rpc RunClient(stream ClientArgs) returns (stream ClientStatus); + + // Just return the core count - unary call + rpc CoreCount(CoreRequest) returns (CoreResponse); + + // Quit this worker + rpc QuitWorker(Void) returns (Void); +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.pb.go b/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.pb.go new file mode 100644 index 00000000..45b9b4af --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.pb.go @@ -0,0 +1,111 @@ +// Code generated by protoc-gen-go. +// source: stats.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ServerStats struct { + // wall clock time change in seconds since last reset + TimeElapsed float64 `protobuf:"fixed64,1,opt,name=time_elapsed,json=timeElapsed" json:"time_elapsed,omitempty"` + // change in user time (in seconds) used by the server since last reset + TimeUser float64 `protobuf:"fixed64,2,opt,name=time_user,json=timeUser" json:"time_user,omitempty"` + // change in server time (in seconds) used by the server process and all + // threads since last reset + TimeSystem float64 `protobuf:"fixed64,3,opt,name=time_system,json=timeSystem" json:"time_system,omitempty"` +} + +func (m *ServerStats) Reset() { *m = ServerStats{} } +func (m *ServerStats) String() string { return proto.CompactTextString(m) } +func (*ServerStats) ProtoMessage() {} +func (*ServerStats) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } + +// Histogram params based on grpc/support/histogram.c +type HistogramParams struct { + Resolution float64 `protobuf:"fixed64,1,opt,name=resolution" json:"resolution,omitempty"` + MaxPossible float64 `protobuf:"fixed64,2,opt,name=max_possible,json=maxPossible" json:"max_possible,omitempty"` +} + +func (m *HistogramParams) Reset() { *m = HistogramParams{} } +func (m *HistogramParams) String() string { return proto.CompactTextString(m) } +func (*HistogramParams) ProtoMessage() {} +func (*HistogramParams) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{1} } + +// Histogram data based on grpc/support/histogram.c +type HistogramData struct { + Bucket []uint32 `protobuf:"varint,1,rep,name=bucket" json:"bucket,omitempty"` + MinSeen float64 `protobuf:"fixed64,2,opt,name=min_seen,json=minSeen" json:"min_seen,omitempty"` + MaxSeen float64 `protobuf:"fixed64,3,opt,name=max_seen,json=maxSeen" json:"max_seen,omitempty"` + Sum float64 `protobuf:"fixed64,4,opt,name=sum" json:"sum,omitempty"` + SumOfSquares float64 `protobuf:"fixed64,5,opt,name=sum_of_squares,json=sumOfSquares" json:"sum_of_squares,omitempty"` + Count float64 `protobuf:"fixed64,6,opt,name=count" json:"count,omitempty"` +} + +func (m *HistogramData) Reset() { *m = HistogramData{} } +func (m *HistogramData) String() string { return proto.CompactTextString(m) } +func (*HistogramData) ProtoMessage() {} +func (*HistogramData) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{2} } + +type ClientStats struct { + // Latency histogram. Data points are in nanoseconds. + Latencies *HistogramData `protobuf:"bytes,1,opt,name=latencies" json:"latencies,omitempty"` + // See ServerStats for details. + TimeElapsed float64 `protobuf:"fixed64,2,opt,name=time_elapsed,json=timeElapsed" json:"time_elapsed,omitempty"` + TimeUser float64 `protobuf:"fixed64,3,opt,name=time_user,json=timeUser" json:"time_user,omitempty"` + TimeSystem float64 `protobuf:"fixed64,4,opt,name=time_system,json=timeSystem" json:"time_system,omitempty"` +} + +func (m *ClientStats) Reset() { *m = ClientStats{} } +func (m *ClientStats) String() string { return proto.CompactTextString(m) } +func (*ClientStats) ProtoMessage() {} +func (*ClientStats) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{3} } + +func (m *ClientStats) GetLatencies() *HistogramData { + if m != nil { + return m.Latencies + } + return nil +} + +func init() { + proto.RegisterType((*ServerStats)(nil), "grpc.testing.ServerStats") + proto.RegisterType((*HistogramParams)(nil), "grpc.testing.HistogramParams") + proto.RegisterType((*HistogramData)(nil), "grpc.testing.HistogramData") + proto.RegisterType((*ClientStats)(nil), "grpc.testing.ClientStats") +} + +func init() { proto.RegisterFile("stats.proto", fileDescriptor4) } + +var fileDescriptor4 = []byte{ + // 342 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x92, 0x4f, 0x4f, 0xe3, 0x30, + 0x10, 0xc5, 0x95, 0xa6, 0xed, 0xb6, 0x93, 0x76, 0x77, 0x65, 0xad, 0x56, 0x41, 0x95, 0xf8, 0x13, + 0x71, 0xe8, 0x29, 0x07, 0x38, 0x71, 0x06, 0x24, 0x6e, 0x54, 0x0d, 0x9c, 0x23, 0x37, 0x4c, 0x2b, + 0x8b, 0xc4, 0x0e, 0x99, 0x09, 0x2a, 0x1f, 0x09, 0xf1, 0x25, 0x71, 0x9c, 0x08, 0x0a, 0x48, 0x70, + 0x49, 0xf2, 0x7e, 0x6f, 0x34, 0xe3, 0xc9, 0x33, 0x04, 0xc4, 0x92, 0x29, 0x2e, 0x2b, 0xc3, 0x46, + 0x4c, 0x36, 0x55, 0x99, 0xc5, 0x8c, 0xc4, 0x4a, 0x6f, 0x22, 0x0d, 0x41, 0x82, 0xd5, 0x23, 0x56, + 0x49, 0x53, 0x22, 0x8e, 0x60, 0xc2, 0xaa, 0xc0, 0x14, 0x73, 0x59, 0x12, 0xde, 0x85, 0xde, 0xa1, + 0x37, 0xf7, 0x96, 0x41, 0xc3, 0x2e, 0x5b, 0x24, 0x66, 0x30, 0x76, 0x25, 0x35, 0x61, 0x15, 0xf6, + 0x9c, 0x3f, 0x6a, 0xc0, 0xad, 0xd5, 0xe2, 0x00, 0x5c, 0x6d, 0x4a, 0x4f, 0xc4, 0x58, 0x84, 0xbe, + 0xb3, 0xa1, 0x41, 0x89, 0x23, 0xd1, 0x0d, 0xfc, 0xb9, 0x52, 0xc4, 0x66, 0x53, 0xc9, 0x62, 0x21, + 0xed, 0x83, 0xc4, 0x3e, 0x40, 0x85, 0x64, 0xf2, 0x9a, 0x95, 0xd1, 0xdd, 0xc4, 0x1d, 0xd2, 0x9c, + 0xa9, 0x90, 0xdb, 0xb4, 0x34, 0x44, 0x6a, 0x95, 0x63, 0x37, 0x33, 0xb0, 0x6c, 0xd1, 0xa1, 0xe8, + 0xc5, 0x83, 0xe9, 0x5b, 0xdb, 0x0b, 0xc9, 0x52, 0xfc, 0x87, 0xe1, 0xaa, 0xce, 0xee, 0x91, 0x6d, + 0x43, 0x7f, 0x3e, 0x5d, 0x76, 0x4a, 0xec, 0xc1, 0xa8, 0x50, 0x3a, 0x25, 0x44, 0xdd, 0x35, 0xfa, + 0x65, 0x75, 0x62, 0xa5, 0xb3, 0xec, 0x1c, 0x67, 0xf9, 0x9d, 0x25, 0xb7, 0xce, 0xfa, 0x0b, 0x3e, + 0xd5, 0x45, 0xd8, 0x77, 0xb4, 0xf9, 0x14, 0xc7, 0xf0, 0xdb, 0xbe, 0x52, 0xb3, 0x4e, 0xe9, 0xa1, + 0x96, 0xf6, 0xb4, 0xe1, 0xc0, 0x99, 0x13, 0x4b, 0xaf, 0xd7, 0x49, 0xcb, 0xc4, 0x3f, 0x18, 0x64, + 0xa6, 0xd6, 0x1c, 0x0e, 0x9d, 0xd9, 0x8a, 0xe8, 0xd9, 0x83, 0xe0, 0x3c, 0x57, 0xa8, 0xb9, 0xfd, + 0xe9, 0x67, 0x30, 0xce, 0x25, 0xa3, 0xce, 0x94, 0x6d, 0xd3, 0xec, 0x1f, 0x9c, 0xcc, 0xe2, 0xdd, + 0x94, 0xe2, 0x0f, 0xbb, 0x2d, 0xdf, 0xab, 0xbf, 0xe4, 0xd5, 0xfb, 0x21, 0x2f, 0xff, 0xfb, 0xbc, + 0xfa, 0x9f, 0xf3, 0x5a, 0x0d, 0xdd, 0xa5, 0x39, 0x7d, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xea, 0x75, + 0x34, 0x90, 0x43, 0x02, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.proto b/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.proto new file mode 100644 index 00000000..9bc3cb21 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/grpc_testing/stats.proto @@ -0,0 +1,70 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.testing; + +message ServerStats { + // wall clock time change in seconds since last reset + double time_elapsed = 1; + + // change in user time (in seconds) used by the server since last reset + double time_user = 2; + + // change in server time (in seconds) used by the server process and all + // threads since last reset + double time_system = 3; +} + +// Histogram params based on grpc/support/histogram.c +message HistogramParams { + double resolution = 1; // first bucket is [0, 1 + resolution) + double max_possible = 2; // use enough buckets to allow this value +} + +// Histogram data based on grpc/support/histogram.c +message HistogramData { + repeated uint32 bucket = 1; + double min_seen = 2; + double max_seen = 3; + double sum = 4; + double sum_of_squares = 5; + double count = 6; +} + +message ClientStats { + // Latency histogram. Data points are in nanoseconds. + HistogramData latencies = 1; + + // See ServerStats for details. + double time_elapsed = 2; + double time_user = 3; + double time_system = 4; +} diff --git a/vendor/google.golang.org/grpc/benchmark/server/main.go b/vendor/google.golang.org/grpc/benchmark/server/main.go new file mode 100644 index 00000000..d43aad0b --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/server/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "flag" + "math" + "net" + "net/http" + _ "net/http/pprof" + "time" + + "google.golang.org/grpc/benchmark" + "google.golang.org/grpc/grpclog" +) + +var ( + duration = flag.Int("duration", math.MaxInt32, "The duration in seconds to run the benchmark server") +) + +func main() { + flag.Parse() + go func() { + lis, err := net.Listen("tcp", ":0") + if err != nil { + grpclog.Fatalf("Failed to listen: %v", err) + } + grpclog.Println("Server profiling address: ", lis.Addr().String()) + if err := http.Serve(lis, nil); err != nil { + grpclog.Fatalf("Failed to serve: %v", err) + } + }() + addr, stopper := benchmark.StartServer(benchmark.ServerInfo{Addr: ":0", Type: "protobuf"}) // listen on all interfaces + grpclog.Println("Server Address: ", addr) + <-time.After(time.Duration(*duration) * time.Second) + stopper() +} diff --git a/vendor/google.golang.org/grpc/benchmark/server/testdata/ca.pem b/vendor/google.golang.org/grpc/benchmark/server/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/server/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.key b/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.pem b/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/server/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/benchmark/stats/histogram.go b/vendor/google.golang.org/grpc/benchmark/stats/histogram.go new file mode 100644 index 00000000..099bcd65 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/stats/histogram.go @@ -0,0 +1,198 @@ +package stats + +import ( + "bytes" + "fmt" + "io" + "log" + "math" + "strconv" + "strings" +) + +// Histogram accumulates values in the form of a histogram with +// exponentially increased bucket sizes. +type Histogram struct { + // Count is the total number of values added to the histogram. + Count int64 + // Sum is the sum of all the values added to the histogram. + Sum int64 + // SumOfSquares is the sum of squares of all values. + SumOfSquares int64 + // Min is the minimum of all the values added to the histogram. + Min int64 + // Max is the maximum of all the values added to the histogram. + Max int64 + // Buckets contains all the buckets of the histogram. + Buckets []HistogramBucket + + opts HistogramOptions + logBaseBucketSize float64 + oneOverLogOnePlusGrowthFactor float64 +} + +// HistogramOptions contains the parameters that define the histogram's buckets. +// The first bucket of the created histogram (with index 0) contains [min, min+n) +// where n = BaseBucketSize, min = MinValue. +// Bucket i (i>=1) contains [min + n * m^(i-1), min + n * m^i), where m = 1+GrowthFactor. +// The type of the values is int64. +type HistogramOptions struct { + // NumBuckets is the number of buckets. + NumBuckets int + // GrowthFactor is the growth factor of the buckets. A value of 0.1 + // indicates that bucket N+1 will be 10% larger than bucket N. + GrowthFactor float64 + // BaseBucketSize is the size of the first bucket. + BaseBucketSize float64 + // MinValue is the lower bound of the first bucket. + MinValue int64 +} + +// HistogramBucket represents one histogram bucket. +type HistogramBucket struct { + // LowBound is the lower bound of the bucket. + LowBound float64 + // Count is the number of values in the bucket. + Count int64 +} + +// NewHistogram returns a pointer to a new Histogram object that was created +// with the provided options. +func NewHistogram(opts HistogramOptions) *Histogram { + if opts.NumBuckets == 0 { + opts.NumBuckets = 32 + } + if opts.BaseBucketSize == 0.0 { + opts.BaseBucketSize = 1.0 + } + h := Histogram{ + Buckets: make([]HistogramBucket, opts.NumBuckets), + Min: math.MaxInt64, + Max: math.MinInt64, + + opts: opts, + logBaseBucketSize: math.Log(opts.BaseBucketSize), + oneOverLogOnePlusGrowthFactor: 1 / math.Log(1+opts.GrowthFactor), + } + m := 1.0 + opts.GrowthFactor + delta := opts.BaseBucketSize + h.Buckets[0].LowBound = float64(opts.MinValue) + for i := 1; i < opts.NumBuckets; i++ { + h.Buckets[i].LowBound = float64(opts.MinValue) + delta + delta = delta * m + } + return &h +} + +// Print writes textual output of the histogram values. +func (h *Histogram) Print(w io.Writer) { + avg := float64(h.Sum) / float64(h.Count) + fmt.Fprintf(w, "Count: %d Min: %d Max: %d Avg: %.2f\n", h.Count, h.Min, h.Max, avg) + fmt.Fprintf(w, "%s\n", strings.Repeat("-", 60)) + if h.Count <= 0 { + return + } + + maxBucketDigitLen := len(strconv.FormatFloat(h.Buckets[len(h.Buckets)-1].LowBound, 'f', 6, 64)) + if maxBucketDigitLen < 3 { + // For "inf". + maxBucketDigitLen = 3 + } + maxCountDigitLen := len(strconv.FormatInt(h.Count, 10)) + percentMulti := 100 / float64(h.Count) + + accCount := int64(0) + for i, b := range h.Buckets { + fmt.Fprintf(w, "[%*f, ", maxBucketDigitLen, b.LowBound) + if i+1 < len(h.Buckets) { + fmt.Fprintf(w, "%*f)", maxBucketDigitLen, h.Buckets[i+1].LowBound) + } else { + fmt.Fprintf(w, "%*s)", maxBucketDigitLen, "inf") + } + + accCount += b.Count + fmt.Fprintf(w, " %*d %5.1f%% %5.1f%%", maxCountDigitLen, b.Count, float64(b.Count)*percentMulti, float64(accCount)*percentMulti) + + const barScale = 0.1 + barLength := int(float64(b.Count)*percentMulti*barScale + 0.5) + fmt.Fprintf(w, " %s\n", strings.Repeat("#", barLength)) + } +} + +// String returns the textual output of the histogram values as string. +func (h *Histogram) String() string { + var b bytes.Buffer + h.Print(&b) + return b.String() +} + +// Clear resets all the content of histogram. +func (h *Histogram) Clear() { + h.Count = 0 + h.Sum = 0 + h.SumOfSquares = 0 + h.Min = math.MaxInt64 + h.Max = math.MinInt64 + for _, v := range h.Buckets { + v.Count = 0 + } +} + +// Opts returns a copy of the options used to create the Histogram. +func (h *Histogram) Opts() HistogramOptions { + return h.opts +} + +// Add adds a value to the histogram. +func (h *Histogram) Add(value int64) error { + bucket, err := h.findBucket(value) + if err != nil { + return err + } + h.Buckets[bucket].Count++ + h.Count++ + h.Sum += value + h.SumOfSquares += value * value + if value < h.Min { + h.Min = value + } + if value > h.Max { + h.Max = value + } + return nil +} + +func (h *Histogram) findBucket(value int64) (int, error) { + delta := float64(value - h.opts.MinValue) + var b int + if delta >= h.opts.BaseBucketSize { + // b = log_{1+growthFactor} (delta / baseBucketSize) + 1 + // = log(delta / baseBucketSize) / log(1+growthFactor) + 1 + // = (log(delta) - log(baseBucketSize)) * (1 / log(1+growthFactor)) + 1 + b = int((math.Log(delta)-h.logBaseBucketSize)*h.oneOverLogOnePlusGrowthFactor + 1) + } + if b >= len(h.Buckets) { + return 0, fmt.Errorf("no bucket for value: %d", value) + } + return b, nil +} + +// Merge takes another histogram h2, and merges its content into h. +// The two histograms must be created by equivalent HistogramOptions. +func (h *Histogram) Merge(h2 *Histogram) { + if h.opts != h2.opts { + log.Fatalf("failed to merge histograms, created by inequivalent options") + } + h.Count += h2.Count + h.Sum += h2.Sum + h.SumOfSquares += h2.SumOfSquares + if h2.Min < h.Min { + h.Min = h2.Min + } + if h2.Max > h.Max { + h.Max = h2.Max + } + for i, b := range h2.Buckets { + h.Buckets[i].Count += b.Count + } +} diff --git a/vendor/google.golang.org/grpc/benchmark/stats/stats.go b/vendor/google.golang.org/grpc/benchmark/stats/stats.go new file mode 100644 index 00000000..e0edb174 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/stats/stats.go @@ -0,0 +1,116 @@ +package stats + +import ( + "bytes" + "fmt" + "io" + "math" + "time" +) + +// Stats is a simple helper for gathering additional statistics like histogram +// during benchmarks. This is not thread safe. +type Stats struct { + numBuckets int + unit time.Duration + min, max int64 + histogram *Histogram + + durations durationSlice + dirty bool +} + +type durationSlice []time.Duration + +// NewStats creates a new Stats instance. If numBuckets is not positive, +// the default value (16) will be used. +func NewStats(numBuckets int) *Stats { + if numBuckets <= 0 { + numBuckets = 16 + } + return &Stats{ + // Use one more bucket for the last unbounded bucket. + numBuckets: numBuckets + 1, + durations: make(durationSlice, 0, 100000), + } +} + +// Add adds an elapsed time per operation to the stats. +func (stats *Stats) Add(d time.Duration) { + stats.durations = append(stats.durations, d) + stats.dirty = true +} + +// Clear resets the stats, removing all values. +func (stats *Stats) Clear() { + stats.durations = stats.durations[:0] + stats.histogram = nil + stats.dirty = false +} + +// maybeUpdate updates internal stat data if there was any newly added +// stats since this was updated. +func (stats *Stats) maybeUpdate() { + if !stats.dirty { + return + } + + stats.min = math.MaxInt64 + stats.max = 0 + for _, d := range stats.durations { + if stats.min > int64(d) { + stats.min = int64(d) + } + if stats.max < int64(d) { + stats.max = int64(d) + } + } + + // Use the largest unit that can represent the minimum time duration. + stats.unit = time.Nanosecond + for _, u := range []time.Duration{time.Microsecond, time.Millisecond, time.Second} { + if stats.min <= int64(u) { + break + } + stats.unit = u + } + + // Adjust the min/max according to the new unit. + stats.min /= int64(stats.unit) + stats.max /= int64(stats.unit) + numBuckets := stats.numBuckets + if n := int(stats.max - stats.min + 1); n < numBuckets { + numBuckets = n + } + stats.histogram = NewHistogram(HistogramOptions{ + NumBuckets: numBuckets, + // max-min(lower bound of last bucket) = (1 + growthFactor)^(numBuckets-2) * baseBucketSize. + GrowthFactor: math.Pow(float64(stats.max-stats.min), 1/float64(numBuckets-2)) - 1, + BaseBucketSize: 1.0, + MinValue: stats.min}) + + for _, d := range stats.durations { + stats.histogram.Add(int64(d / stats.unit)) + } + + stats.dirty = false +} + +// Print writes textual output of the Stats. +func (stats *Stats) Print(w io.Writer) { + stats.maybeUpdate() + + if stats.histogram == nil { + fmt.Fprint(w, "Histogram (empty)\n") + } else { + fmt.Fprintf(w, "Histogram (unit: %s)\n", fmt.Sprintf("%v", stats.unit)[1:]) + stats.histogram.Print(w) + } +} + +// String returns the textual output of the Stats as string. +func (stats *Stats) String() string { + var b bytes.Buffer + stats.Print(&b) + return b.String() +} diff --git a/vendor/google.golang.org/grpc/benchmark/stats/util.go b/vendor/google.golang.org/grpc/benchmark/stats/util.go new file mode 100644 index 00000000..a9922f98 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/stats/util.go @@ -0,0 +1,191 @@ +package stats + +import ( + "bufio" + "bytes" + "fmt" + "os" + "runtime" + "sort" + "strings" + "sync" + "testing" +) + +var ( + curB *testing.B + curBenchName string + curStats map[string]*Stats + + orgStdout *os.File + nextOutPos int + + injectCond *sync.Cond + injectDone chan struct{} +) + +// AddStats adds a new unnamed Stats instance to the current benchmark. You need +// to run benchmarks by calling RunTestMain() to inject the stats to the +// benchmark results. If numBuckets is not positive, the default value (16) will +// be used. Please note that this calls b.ResetTimer() since it may be blocked +// until the previous benchmark stats is printed out. So AddStats() should +// typically be called at the very beginning of each benchmark function. +func AddStats(b *testing.B, numBuckets int) *Stats { + return AddStatsWithName(b, "", numBuckets) +} + +// AddStatsWithName adds a new named Stats instance to the current benchmark. +// With this, you can add multiple stats in a single benchmark. You need +// to run benchmarks by calling RunTestMain() to inject the stats to the +// benchmark results. If numBuckets is not positive, the default value (16) will +// be used. Please note that this calls b.ResetTimer() since it may be blocked +// until the previous benchmark stats is printed out. So AddStatsWithName() +// should typically be called at the very beginning of each benchmark function. +func AddStatsWithName(b *testing.B, name string, numBuckets int) *Stats { + var benchName string + for i := 1; ; i++ { + pc, _, _, ok := runtime.Caller(i) + if !ok { + panic("benchmark function not found") + } + p := strings.Split(runtime.FuncForPC(pc).Name(), ".") + benchName = p[len(p)-1] + if strings.HasPrefix(benchName, "Benchmark") { + break + } + } + procs := runtime.GOMAXPROCS(-1) + if procs != 1 { + benchName = fmt.Sprintf("%s-%d", benchName, procs) + } + + stats := NewStats(numBuckets) + + if injectCond != nil { + // We need to wait until the previous benchmark stats is printed out. + injectCond.L.Lock() + for curB != nil && curBenchName != benchName { + injectCond.Wait() + } + + curB = b + curBenchName = benchName + curStats[name] = stats + + injectCond.L.Unlock() + } + + b.ResetTimer() + return stats +} + +// RunTestMain runs the tests with enabling injection of benchmark stats. It +// returns an exit code to pass to os.Exit. +func RunTestMain(m *testing.M) int { + startStatsInjector() + defer stopStatsInjector() + return m.Run() +} + +// startStatsInjector starts stats injection to benchmark results. +func startStatsInjector() { + orgStdout = os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + nextOutPos = 0 + + resetCurBenchStats() + + injectCond = sync.NewCond(&sync.Mutex{}) + injectDone = make(chan struct{}) + go func() { + defer close(injectDone) + + scanner := bufio.NewScanner(r) + scanner.Split(splitLines) + for scanner.Scan() { + injectStatsIfFinished(scanner.Text()) + } + if err := scanner.Err(); err != nil { + panic(err) + } + }() +} + +// stopStatsInjector stops stats injection and restores os.Stdout. +func stopStatsInjector() { + os.Stdout.Close() + <-injectDone + injectCond = nil + os.Stdout = orgStdout +} + +// splitLines is a split function for a bufio.Scanner that returns each line +// of text, teeing texts to the original stdout even before each line ends. +func splitLines(data []byte, eof bool) (advance int, token []byte, err error) { + if eof && len(data) == 0 { + return 0, nil, nil + } + + if i := bytes.IndexByte(data, '\n'); i >= 0 { + orgStdout.Write(data[nextOutPos : i+1]) + nextOutPos = 0 + return i + 1, data[0:i], nil + } + + orgStdout.Write(data[nextOutPos:]) + nextOutPos = len(data) + + if eof { + // This is a final, non-terminated line. Return it. + return len(data), data, nil + } + + return 0, nil, nil +} + +// injectStatsIfFinished prints out the stats if the current benchmark finishes. +func injectStatsIfFinished(line string) { + injectCond.L.Lock() + defer injectCond.L.Unlock() + + // We assume that the benchmark results start with the benchmark name. + if curB == nil || !strings.HasPrefix(line, curBenchName) { + return + } + + if !curB.Failed() { + // Output all stats in alphabetical order. + names := make([]string, 0, len(curStats)) + for name := range curStats { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + stats := curStats[name] + // The output of stats starts with a header like "Histogram (unit: ms)" + // followed by statistical properties and the buckets. Add the stats name + // if it is a named stats and indent them as Go testing outputs. + lines := strings.Split(stats.String(), "\n") + if n := len(lines); n > 0 { + if name != "" { + name = ": " + name + } + fmt.Fprintf(orgStdout, "--- %s%s\n", lines[0], name) + for _, line := range lines[1 : n-1] { + fmt.Fprintf(orgStdout, "\t%s\n", line) + } + } + } + } + + resetCurBenchStats() + injectCond.Signal() +} + +// resetCurBenchStats resets the current benchmark stats. +func resetCurBenchStats() { + curB = nil + curBenchName = "" + curStats = make(map[string]*Stats) +} diff --git a/vendor/google.golang.org/grpc/benchmark/worker/benchmark_client.go b/vendor/google.golang.org/grpc/benchmark/worker/benchmark_client.go new file mode 100644 index 00000000..77e522f2 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/worker/benchmark_client.go @@ -0,0 +1,399 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "math" + "runtime" + "sync" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/benchmark" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/benchmark/stats" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" +) + +var ( + caFile = "benchmark/server/testdata/ca.pem" +) + +type lockingHistogram struct { + mu sync.Mutex + histogram *stats.Histogram +} + +func (h *lockingHistogram) add(value int64) { + h.mu.Lock() + defer h.mu.Unlock() + h.histogram.Add(value) +} + +// swap sets h.histogram to new, and returns its old value. +func (h *lockingHistogram) swap(new *stats.Histogram) *stats.Histogram { + h.mu.Lock() + defer h.mu.Unlock() + old := h.histogram + h.histogram = new + return old +} + +func (h *lockingHistogram) mergeInto(merged *stats.Histogram) { + h.mu.Lock() + defer h.mu.Unlock() + merged.Merge(h.histogram) +} + +type benchmarkClient struct { + closeConns func() + stop chan bool + lastResetTime time.Time + histogramOptions stats.HistogramOptions + lockingHistograms []lockingHistogram +} + +func printClientConfig(config *testpb.ClientConfig) { + // Some config options are ignored: + // - client type: + // will always create sync client + // - async client threads. + // - core list + grpclog.Printf(" * client type: %v (ignored, always creates sync client)", config.ClientType) + grpclog.Printf(" * async client threads: %v (ignored)", config.AsyncClientThreads) + // TODO: use cores specified by CoreList when setting list of cores is supported in go. + grpclog.Printf(" * core list: %v (ignored)", config.CoreList) + + grpclog.Printf(" - security params: %v", config.SecurityParams) + grpclog.Printf(" - core limit: %v", config.CoreLimit) + grpclog.Printf(" - payload config: %v", config.PayloadConfig) + grpclog.Printf(" - rpcs per chann: %v", config.OutstandingRpcsPerChannel) + grpclog.Printf(" - channel number: %v", config.ClientChannels) + grpclog.Printf(" - load params: %v", config.LoadParams) + grpclog.Printf(" - rpc type: %v", config.RpcType) + grpclog.Printf(" - histogram params: %v", config.HistogramParams) + grpclog.Printf(" - server targets: %v", config.ServerTargets) +} + +func setupClientEnv(config *testpb.ClientConfig) { + // Use all cpu cores available on machine by default. + // TODO: Revisit this for the optimal default setup. + if config.CoreLimit > 0 { + runtime.GOMAXPROCS(int(config.CoreLimit)) + } else { + runtime.GOMAXPROCS(runtime.NumCPU()) + } +} + +// createConns creates connections according to given config. +// It returns the connections and corresponding function to close them. +// It returns non-nil error if there is anything wrong. +func createConns(config *testpb.ClientConfig) ([]*grpc.ClientConn, func(), error) { + var opts []grpc.DialOption + + // Sanity check for client type. + switch config.ClientType { + case testpb.ClientType_SYNC_CLIENT: + case testpb.ClientType_ASYNC_CLIENT: + default: + return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow client type: %v", config.ClientType) + } + + // Check and set security options. + if config.SecurityParams != nil { + creds, err := credentials.NewClientTLSFromFile(abs(caFile), config.SecurityParams.ServerHostOverride) + if err != nil { + return nil, nil, grpc.Errorf(codes.InvalidArgument, "failed to create TLS credentials %v", err) + } + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + + // Use byteBufCodec if it is required. + if config.PayloadConfig != nil { + switch config.PayloadConfig.Payload.(type) { + case *testpb.PayloadConfig_BytebufParams: + opts = append(opts, grpc.WithCodec(byteBufCodec{})) + case *testpb.PayloadConfig_SimpleParams: + default: + return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig) + } + } + + // Create connections. + connCount := int(config.ClientChannels) + conns := make([]*grpc.ClientConn, connCount, connCount) + for connIndex := 0; connIndex < connCount; connIndex++ { + conns[connIndex] = benchmark.NewClientConn(config.ServerTargets[connIndex%len(config.ServerTargets)], opts...) + } + + return conns, func() { + for _, conn := range conns { + conn.Close() + } + }, nil +} + +func performRPCs(config *testpb.ClientConfig, conns []*grpc.ClientConn, bc *benchmarkClient) error { + // Read payload size and type from config. + var ( + payloadReqSize, payloadRespSize int + payloadType string + ) + if config.PayloadConfig != nil { + switch c := config.PayloadConfig.Payload.(type) { + case *testpb.PayloadConfig_BytebufParams: + payloadReqSize = int(c.BytebufParams.ReqSize) + payloadRespSize = int(c.BytebufParams.RespSize) + payloadType = "bytebuf" + case *testpb.PayloadConfig_SimpleParams: + payloadReqSize = int(c.SimpleParams.ReqSize) + payloadRespSize = int(c.SimpleParams.RespSize) + payloadType = "protobuf" + default: + return grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig) + } + } + + // TODO add open loop distribution. + switch config.LoadParams.Load.(type) { + case *testpb.LoadParams_ClosedLoop: + case *testpb.LoadParams_Poisson: + return grpc.Errorf(codes.Unimplemented, "unsupported load params: %v", config.LoadParams) + default: + return grpc.Errorf(codes.InvalidArgument, "unknown load params: %v", config.LoadParams) + } + + rpcCountPerConn := int(config.OutstandingRpcsPerChannel) + + switch config.RpcType { + case testpb.RpcType_UNARY: + bc.doCloseLoopUnary(conns, rpcCountPerConn, payloadReqSize, payloadRespSize) + // TODO open loop. + case testpb.RpcType_STREAMING: + bc.doCloseLoopStreaming(conns, rpcCountPerConn, payloadReqSize, payloadRespSize, payloadType) + // TODO open loop. + default: + return grpc.Errorf(codes.InvalidArgument, "unknown rpc type: %v", config.RpcType) + } + + return nil +} + +func startBenchmarkClient(config *testpb.ClientConfig) (*benchmarkClient, error) { + printClientConfig(config) + + // Set running environment like how many cores to use. + setupClientEnv(config) + + conns, closeConns, err := createConns(config) + if err != nil { + return nil, err + } + + rpcCountPerConn := int(config.OutstandingRpcsPerChannel) + bc := &benchmarkClient{ + histogramOptions: stats.HistogramOptions{ + NumBuckets: int(math.Log(config.HistogramParams.MaxPossible)/math.Log(1+config.HistogramParams.Resolution)) + 1, + GrowthFactor: config.HistogramParams.Resolution, + BaseBucketSize: (1 + config.HistogramParams.Resolution), + MinValue: 0, + }, + lockingHistograms: make([]lockingHistogram, rpcCountPerConn*len(conns), rpcCountPerConn*len(conns)), + + stop: make(chan bool), + lastResetTime: time.Now(), + closeConns: closeConns, + } + + if err = performRPCs(config, conns, bc); err != nil { + // Close all connections if performRPCs failed. + closeConns() + return nil, err + } + + return bc, nil +} + +func (bc *benchmarkClient) doCloseLoopUnary(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int) { + for ic, conn := range conns { + client := testpb.NewBenchmarkServiceClient(conn) + // For each connection, create rpcCountPerConn goroutines to do rpc. + for j := 0; j < rpcCountPerConn; j++ { + // Create histogram for each goroutine. + idx := ic*rpcCountPerConn + j + bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions) + // Start goroutine on the created mutex and histogram. + go func(idx int) { + // TODO: do warm up if necessary. + // Now relying on worker client to reserve time to do warm up. + // The worker client needs to wait for some time after client is created, + // before starting benchmark. + done := make(chan bool) + for { + go func() { + start := time.Now() + if err := benchmark.DoUnaryCall(client, reqSize, respSize); err != nil { + select { + case <-bc.stop: + case done <- false: + } + return + } + elapse := time.Since(start) + bc.lockingHistograms[idx].add(int64(elapse)) + select { + case <-bc.stop: + case done <- true: + } + }() + select { + case <-bc.stop: + return + case <-done: + } + } + }(idx) + } + } +} + +func (bc *benchmarkClient) doCloseLoopStreaming(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int, payloadType string) { + var doRPC func(testpb.BenchmarkService_StreamingCallClient, int, int) error + if payloadType == "bytebuf" { + doRPC = benchmark.DoByteBufStreamingRoundTrip + } else { + doRPC = benchmark.DoStreamingRoundTrip + } + for ic, conn := range conns { + // For each connection, create rpcCountPerConn goroutines to do rpc. + for j := 0; j < rpcCountPerConn; j++ { + c := testpb.NewBenchmarkServiceClient(conn) + stream, err := c.StreamingCall(context.Background()) + if err != nil { + grpclog.Fatalf("%v.StreamingCall(_) = _, %v", c, err) + } + // Create histogram for each goroutine. + idx := ic*rpcCountPerConn + j + bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions) + // Start goroutine on the created mutex and histogram. + go func(idx int) { + // TODO: do warm up if necessary. + // Now relying on worker client to reserve time to do warm up. + // The worker client needs to wait for some time after client is created, + // before starting benchmark. + done := make(chan bool) + for { + go func() { + start := time.Now() + if err := doRPC(stream, reqSize, respSize); err != nil { + select { + case <-bc.stop: + case done <- false: + } + return + } + elapse := time.Since(start) + bc.lockingHistograms[idx].add(int64(elapse)) + select { + case <-bc.stop: + case done <- true: + } + }() + select { + case <-bc.stop: + return + case <-done: + } + } + }(idx) + } + } +} + +// getStats returns the stats for benchmark client. +// It resets lastResetTime and all histograms if argument reset is true. +func (bc *benchmarkClient) getStats(reset bool) *testpb.ClientStats { + var timeElapsed float64 + mergedHistogram := stats.NewHistogram(bc.histogramOptions) + + if reset { + // Merging histogram may take some time. + // Put all histograms aside and merge later. + toMerge := make([]*stats.Histogram, len(bc.lockingHistograms), len(bc.lockingHistograms)) + for i := range bc.lockingHistograms { + toMerge[i] = bc.lockingHistograms[i].swap(stats.NewHistogram(bc.histogramOptions)) + } + + for i := 0; i < len(toMerge); i++ { + mergedHistogram.Merge(toMerge[i]) + } + + timeElapsed = time.Since(bc.lastResetTime).Seconds() + bc.lastResetTime = time.Now() + } else { + // Merge only, not reset. + for i := range bc.lockingHistograms { + bc.lockingHistograms[i].mergeInto(mergedHistogram) + } + timeElapsed = time.Since(bc.lastResetTime).Seconds() + } + + b := make([]uint32, len(mergedHistogram.Buckets), len(mergedHistogram.Buckets)) + for i, v := range mergedHistogram.Buckets { + b[i] = uint32(v.Count) + } + return &testpb.ClientStats{ + Latencies: &testpb.HistogramData{ + Bucket: b, + MinSeen: float64(mergedHistogram.Min), + MaxSeen: float64(mergedHistogram.Max), + Sum: float64(mergedHistogram.Sum), + SumOfSquares: float64(mergedHistogram.SumOfSquares), + Count: float64(mergedHistogram.Count), + }, + TimeElapsed: timeElapsed, + TimeUser: 0, + TimeSystem: 0, + } +} + +func (bc *benchmarkClient) shutdown() { + close(bc.stop) + bc.closeConns() +} diff --git a/vendor/google.golang.org/grpc/benchmark/worker/benchmark_server.go b/vendor/google.golang.org/grpc/benchmark/worker/benchmark_server.go new file mode 100644 index 00000000..667ef2c1 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/worker/benchmark_server.go @@ -0,0 +1,173 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "runtime" + "strconv" + "strings" + "sync" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/benchmark" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" +) + +var ( + // File path related to google.golang.org/grpc. + certFile = "benchmark/server/testdata/server1.pem" + keyFile = "benchmark/server/testdata/server1.key" +) + +type benchmarkServer struct { + port int + cores int + closeFunc func() + mu sync.RWMutex + lastResetTime time.Time +} + +func printServerConfig(config *testpb.ServerConfig) { + // Some config options are ignored: + // - server type: + // will always start sync server + // - async server threads + // - core list + grpclog.Printf(" * server type: %v (ignored, always starts sync server)", config.ServerType) + grpclog.Printf(" * async server threads: %v (ignored)", config.AsyncServerThreads) + // TODO: use cores specified by CoreList when setting list of cores is supported in go. + grpclog.Printf(" * core list: %v (ignored)", config.CoreList) + + grpclog.Printf(" - security params: %v", config.SecurityParams) + grpclog.Printf(" - core limit: %v", config.CoreLimit) + grpclog.Printf(" - port: %v", config.Port) + grpclog.Printf(" - payload config: %v", config.PayloadConfig) +} + +func startBenchmarkServer(config *testpb.ServerConfig, serverPort int) (*benchmarkServer, error) { + printServerConfig(config) + + // Use all cpu cores available on machine by default. + // TODO: Revisit this for the optimal default setup. + numOfCores := runtime.NumCPU() + if config.CoreLimit > 0 { + numOfCores = int(config.CoreLimit) + } + runtime.GOMAXPROCS(numOfCores) + + var opts []grpc.ServerOption + + // Sanity check for server type. + switch config.ServerType { + case testpb.ServerType_SYNC_SERVER: + case testpb.ServerType_ASYNC_SERVER: + case testpb.ServerType_ASYNC_GENERIC_SERVER: + default: + return nil, grpc.Errorf(codes.InvalidArgument, "unknow server type: %v", config.ServerType) + } + + // Set security options. + if config.SecurityParams != nil { + creds, err := credentials.NewServerTLSFromFile(abs(certFile), abs(keyFile)) + if err != nil { + grpclog.Fatalf("failed to generate credentials %v", err) + } + opts = append(opts, grpc.Creds(creds)) + } + + // Priority: config.Port > serverPort > default (0). + port := int(config.Port) + if port == 0 { + port = serverPort + } + + // Create different benchmark server according to config. + var ( + addr string + closeFunc func() + err error + ) + if config.PayloadConfig != nil { + switch payload := config.PayloadConfig.Payload.(type) { + case *testpb.PayloadConfig_BytebufParams: + opts = append(opts, grpc.CustomCodec(byteBufCodec{})) + addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{ + Addr: ":" + strconv.Itoa(port), + Type: "bytebuf", + Metadata: payload.BytebufParams.RespSize, + }, opts...) + case *testpb.PayloadConfig_SimpleParams: + addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{ + Addr: ":" + strconv.Itoa(port), + Type: "protobuf", + }, opts...) + case *testpb.PayloadConfig_ComplexParams: + return nil, grpc.Errorf(codes.Unimplemented, "unsupported payload config: %v", config.PayloadConfig) + default: + return nil, grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig) + } + } else { + // Start protobuf server if payload config is nil. + addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{ + Addr: ":" + strconv.Itoa(port), + Type: "protobuf", + }, opts...) + } + + grpclog.Printf("benchmark server listening at %v", addr) + addrSplitted := strings.Split(addr, ":") + p, err := strconv.Atoi(addrSplitted[len(addrSplitted)-1]) + if err != nil { + grpclog.Fatalf("failed to get port number from server address: %v", err) + } + + return &benchmarkServer{port: p, cores: numOfCores, closeFunc: closeFunc, lastResetTime: time.Now()}, nil +} + +// getStats returns the stats for benchmark server. +// It resets lastResetTime if argument reset is true. +func (bs *benchmarkServer) getStats(reset bool) *testpb.ServerStats { + // TODO wall time, sys time, user time. + bs.mu.RLock() + defer bs.mu.RUnlock() + timeElapsed := time.Since(bs.lastResetTime).Seconds() + if reset { + bs.lastResetTime = time.Now() + } + return &testpb.ServerStats{TimeElapsed: timeElapsed, TimeUser: 0, TimeSystem: 0} +} diff --git a/vendor/google.golang.org/grpc/benchmark/worker/main.go b/vendor/google.golang.org/grpc/benchmark/worker/main.go new file mode 100644 index 00000000..17c52519 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/worker/main.go @@ -0,0 +1,231 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "flag" + "fmt" + "io" + "net" + "runtime" + "strconv" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + testpb "google.golang.org/grpc/benchmark/grpc_testing" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" +) + +var ( + driverPort = flag.Int("driver_port", 10000, "port for communication with driver") + serverPort = flag.Int("server_port", 0, "port for benchmark server if not specified by server config message") +) + +type byteBufCodec struct { +} + +func (byteBufCodec) Marshal(v interface{}) ([]byte, error) { + b, ok := v.(*[]byte) + if !ok { + return nil, fmt.Errorf("failed to marshal: %v is not type of *[]byte", v) + } + return *b, nil +} + +func (byteBufCodec) Unmarshal(data []byte, v interface{}) error { + b, ok := v.(*[]byte) + if !ok { + return fmt.Errorf("failed to marshal: %v is not type of *[]byte", v) + } + *b = data + return nil +} + +func (byteBufCodec) String() string { + return "bytebuffer" +} + +// workerServer implements WorkerService rpc handlers. +// It can create benchmarkServer or benchmarkClient on demand. +type workerServer struct { + stop chan<- bool + serverPort int +} + +func (s *workerServer) RunServer(stream testpb.WorkerService_RunServerServer) error { + var bs *benchmarkServer + defer func() { + // Close benchmark server when stream ends. + grpclog.Printf("closing benchmark server") + if bs != nil { + bs.closeFunc() + } + }() + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + var out *testpb.ServerStatus + switch argtype := in.Argtype.(type) { + case *testpb.ServerArgs_Setup: + grpclog.Printf("server setup received:") + if bs != nil { + grpclog.Printf("server setup received when server already exists, closing the existing server") + bs.closeFunc() + } + bs, err = startBenchmarkServer(argtype.Setup, s.serverPort) + if err != nil { + return err + } + out = &testpb.ServerStatus{ + Stats: bs.getStats(false), + Port: int32(bs.port), + Cores: int32(bs.cores), + } + + case *testpb.ServerArgs_Mark: + grpclog.Printf("server mark received:") + grpclog.Printf(" - %v", argtype) + if bs == nil { + return grpc.Errorf(codes.InvalidArgument, "server does not exist when mark received") + } + out = &testpb.ServerStatus{ + Stats: bs.getStats(argtype.Mark.Reset_), + Port: int32(bs.port), + Cores: int32(bs.cores), + } + } + + if err := stream.Send(out); err != nil { + return err + } + } +} + +func (s *workerServer) RunClient(stream testpb.WorkerService_RunClientServer) error { + var bc *benchmarkClient + defer func() { + // Shut down benchmark client when stream ends. + grpclog.Printf("shuting down benchmark client") + if bc != nil { + bc.shutdown() + } + }() + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + var out *testpb.ClientStatus + switch t := in.Argtype.(type) { + case *testpb.ClientArgs_Setup: + grpclog.Printf("client setup received:") + if bc != nil { + grpclog.Printf("client setup received when client already exists, shuting down the existing client") + bc.shutdown() + } + bc, err = startBenchmarkClient(t.Setup) + if err != nil { + return err + } + out = &testpb.ClientStatus{ + Stats: bc.getStats(false), + } + + case *testpb.ClientArgs_Mark: + grpclog.Printf("client mark received:") + grpclog.Printf(" - %v", t) + if bc == nil { + return grpc.Errorf(codes.InvalidArgument, "client does not exist when mark received") + } + out = &testpb.ClientStatus{ + Stats: bc.getStats(t.Mark.Reset_), + } + } + + if err := stream.Send(out); err != nil { + return err + } + } +} + +func (s *workerServer) CoreCount(ctx context.Context, in *testpb.CoreRequest) (*testpb.CoreResponse, error) { + grpclog.Printf("core count: %v", runtime.NumCPU()) + return &testpb.CoreResponse{Cores: int32(runtime.NumCPU())}, nil +} + +func (s *workerServer) QuitWorker(ctx context.Context, in *testpb.Void) (*testpb.Void, error) { + grpclog.Printf("quiting worker") + s.stop <- true + return &testpb.Void{}, nil +} + +func main() { + grpc.EnableTracing = false + + flag.Parse() + lis, err := net.Listen("tcp", ":"+strconv.Itoa(*driverPort)) + if err != nil { + grpclog.Fatalf("failed to listen: %v", err) + } + grpclog.Printf("worker listening at port %v", *driverPort) + + s := grpc.NewServer() + stop := make(chan bool) + testpb.RegisterWorkerServiceServer(s, &workerServer{ + stop: stop, + serverPort: *serverPort, + }) + + go func() { + <-stop + // Wait for 1 second before stopping the server to make sure the return value of QuitWorker is sent to client. + // TODO revise this once server graceful stop is supported in gRPC. + time.Sleep(time.Second) + s.Stop() + }() + + s.Serve(lis) +} diff --git a/vendor/google.golang.org/grpc/benchmark/worker/util.go b/vendor/google.golang.org/grpc/benchmark/worker/util.go new file mode 100644 index 00000000..f0016ce4 --- /dev/null +++ b/vendor/google.golang.org/grpc/benchmark/worker/util.go @@ -0,0 +1,75 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "log" + "os" + "path/filepath" +) + +// abs returns the absolute path the given relative file or directory path, +// relative to the google.golang.org/grpc directory in the user's GOPATH. +// If rel is already absolute, it is returned unmodified. +func abs(rel string) string { + if filepath.IsAbs(rel) { + return rel + } + v, err := goPackagePath("google.golang.org/grpc") + if err != nil { + log.Fatalf("Error finding google.golang.org/grpc/testdata directory: %v", err) + } + return filepath.Join(v, rel) +} + +func goPackagePath(pkg string) (path string, err error) { + gp := os.Getenv("GOPATH") + if gp == "" { + return path, os.ErrNotExist + } + for _, p := range filepath.SplitList(gp) { + dir := filepath.Join(p, "src", filepath.FromSlash(pkg)) + fi, err := os.Stat(dir) + if os.IsNotExist(err) { + continue + } + if err != nil { + return "", err + } + if !fi.IsDir() { + continue + } + return dir, nil + } + return path, os.ErrNotExist +} diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go new file mode 100644 index 00000000..84ac178c --- /dev/null +++ b/vendor/google.golang.org/grpc/call.go @@ -0,0 +1,213 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "io" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/transport" +) + +// recvResponse receives and parses an RPC response. +// On error, it returns the error and indicates whether the call should be retried. +// +// TODO(zhaoq): Check whether the received message sequence is valid. +func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { + // Try to acquire header metadata from the server if there is any. + var err error + c.headerMD, err = stream.Header() + if err != nil { + return err + } + p := &parser{r: stream} + for { + if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil { + if err == io.EOF { + break + } + return err + } + } + c.trailerMD = stream.Trailer() + return nil +} + +// sendRequest writes out various information of an RPC such as Context and Message. +func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) { + stream, err := t.NewStream(ctx, callHdr) + if err != nil { + return nil, err + } + defer func() { + if err != nil { + if _, ok := err.(transport.ConnectionError); !ok { + t.CloseStream(stream, err) + } + } + }() + var cbuf *bytes.Buffer + if compressor != nil { + cbuf = new(bytes.Buffer) + } + outBuf, err := encode(codec, args, compressor, cbuf) + if err != nil { + return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err) + } + err = t.Write(stream, outBuf, opts) + if err != nil { + return nil, err + } + // Sent successfully. + return stream, nil +} + +// Invoke sends the RPC request on the wire and returns after response is received. +// Invoke is called by generated code. Also users can call Invoke directly when it +// is really needed in their use cases. +func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) { + c := defaultCallInfo + for _, o := range opts { + if err := o.before(&c); err != nil { + return toRPCErr(err) + } + } + defer func() { + for _, o := range opts { + o.after(&c) + } + }() + if EnableTracing { + c.traceInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) + defer c.traceInfo.tr.Finish() + c.traceInfo.firstLine.client = true + if deadline, ok := ctx.Deadline(); ok { + c.traceInfo.firstLine.deadline = deadline.Sub(time.Now()) + } + c.traceInfo.tr.LazyLog(&c.traceInfo.firstLine, false) + // TODO(dsymonds): Arrange for c.traceInfo.firstLine.remoteAddr to be set. + defer func() { + if err != nil { + c.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + c.traceInfo.tr.SetError() + } + }() + } + topts := &transport.Options{ + Last: true, + Delay: false, + } + for { + var ( + err error + t transport.ClientTransport + stream *transport.Stream + // Record the put handler from Balancer.Get(...). It is called once the + // RPC has completed or failed. + put func() + ) + // TODO(zhaoq): Need a formal spec of fail-fast. + callHdr := &transport.CallHdr{ + Host: cc.authority, + Method: method, + } + if cc.dopts.cp != nil { + callHdr.SendCompress = cc.dopts.cp.Type() + } + gopts := BalancerGetOptions{ + BlockingWait: !c.failFast, + } + t, put, err = cc.getTransport(ctx, gopts) + if err != nil { + // TODO(zhaoq): Probably revisit the error handling. + if _, ok := err.(*rpcError); ok { + return err + } + if err == errConnClosing { + if c.failFast { + return Errorf(codes.Unavailable, "%v", errConnClosing) + } + continue + } + // All the other errors are treated as Internal errors. + return Errorf(codes.Internal, "%v", err) + } + if c.traceInfo.tr != nil { + c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true) + } + stream, err = sendRequest(ctx, cc.dopts.codec, cc.dopts.cp, callHdr, t, args, topts) + if err != nil { + if put != nil { + put() + put = nil + } + if _, ok := err.(transport.ConnectionError); ok { + if c.failFast { + return toRPCErr(err) + } + continue + } + return toRPCErr(err) + } + // Receive the response + err = recvResponse(cc.dopts, t, &c, stream, reply) + if err != nil { + if put != nil { + put() + put = nil + } + if _, ok := err.(transport.ConnectionError); ok { + if c.failFast { + return toRPCErr(err) + } + continue + } + t.CloseStream(stream, err) + return toRPCErr(err) + } + if c.traceInfo.tr != nil { + c.traceInfo.tr.LazyLog(&payload{sent: false, msg: reply}, true) + } + t.CloseStream(stream, nil) + if put != nil { + put() + put = nil + } + return Errorf(stream.StatusCode(), "%s", stream.StatusDesc()) + } +} diff --git a/vendor/google.golang.org/grpc/call_test.go b/vendor/google.golang.org/grpc/call_test.go new file mode 100644 index 00000000..49349858 --- /dev/null +++ b/vendor/google.golang.org/grpc/call_test.go @@ -0,0 +1,278 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "fmt" + "io" + "math" + "net" + "strconv" + "strings" + "sync" + "testing" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/transport" +) + +var ( + expectedRequest = "ping" + expectedResponse = "pong" + weirdError = "format verbs: %v%s" + sizeLargeErr = 1024 * 1024 + canceled = 0 +) + +type testCodec struct { +} + +func (testCodec) Marshal(v interface{}) ([]byte, error) { + return []byte(*(v.(*string))), nil +} + +func (testCodec) Unmarshal(data []byte, v interface{}) error { + *(v.(*string)) = string(data) + return nil +} + +func (testCodec) String() string { + return "test" +} + +type testStreamHandler struct { + port string + t transport.ServerTransport +} + +func (h *testStreamHandler) handleStream(t *testing.T, s *transport.Stream) { + p := &parser{r: s} + for { + pf, req, err := p.recvMsg() + if err == io.EOF { + break + } + if err != nil { + return + } + if pf != compressionNone { + t.Errorf("Received the mistaken message format %d, want %d", pf, compressionNone) + return + } + var v string + codec := testCodec{} + if err := codec.Unmarshal(req, &v); err != nil { + t.Errorf("Failed to unmarshal the received message: %v", err) + return + } + if v == "weird error" { + h.t.WriteStatus(s, codes.Internal, weirdError) + return + } + if v == "canceled" { + canceled++ + h.t.WriteStatus(s, codes.Internal, "") + return + } + if v == "port" { + h.t.WriteStatus(s, codes.Internal, h.port) + return + } + + if v != expectedRequest { + h.t.WriteStatus(s, codes.Internal, strings.Repeat("A", sizeLargeErr)) + return + } + } + // send a response back to end the stream. + reply, err := encode(testCodec{}, &expectedResponse, nil, nil) + if err != nil { + t.Errorf("Failed to encode the response: %v", err) + return + } + h.t.Write(s, reply, &transport.Options{}) + h.t.WriteStatus(s, codes.OK, "") +} + +type server struct { + lis net.Listener + port string + startedErr chan error // sent nil or an error after server starts + mu sync.Mutex + conns map[transport.ServerTransport]bool +} + +func newTestServer() *server { + return &server{startedErr: make(chan error, 1)} +} + +// start starts server. Other goroutines should block on s.startedErr for further operations. +func (s *server) start(t *testing.T, port int, maxStreams uint32) { + var err error + if port == 0 { + s.lis, err = net.Listen("tcp", "localhost:0") + } else { + s.lis, err = net.Listen("tcp", "localhost:"+strconv.Itoa(port)) + } + if err != nil { + s.startedErr <- fmt.Errorf("failed to listen: %v", err) + return + } + _, p, err := net.SplitHostPort(s.lis.Addr().String()) + if err != nil { + s.startedErr <- fmt.Errorf("failed to parse listener address: %v", err) + return + } + s.port = p + s.conns = make(map[transport.ServerTransport]bool) + s.startedErr <- nil + for { + conn, err := s.lis.Accept() + if err != nil { + return + } + st, err := transport.NewServerTransport("http2", conn, maxStreams, nil) + if err != nil { + continue + } + s.mu.Lock() + if s.conns == nil { + s.mu.Unlock() + st.Close() + return + } + s.conns[st] = true + s.mu.Unlock() + h := &testStreamHandler{ + port: s.port, + t: st, + } + go st.HandleStreams(func(s *transport.Stream) { + go h.handleStream(t, s) + }) + } +} + +func (s *server) wait(t *testing.T, timeout time.Duration) { + select { + case err := <-s.startedErr: + if err != nil { + t.Fatal(err) + } + case <-time.After(timeout): + t.Fatalf("Timed out after %v waiting for server to be ready", timeout) + } +} + +func (s *server) stop() { + s.lis.Close() + s.mu.Lock() + for c := range s.conns { + c.Close() + } + s.conns = nil + s.mu.Unlock() +} + +func setUp(t *testing.T, port int, maxStreams uint32) (*server, *ClientConn) { + server := newTestServer() + go server.start(t, port, maxStreams) + server.wait(t, 2*time.Second) + addr := "localhost:" + server.port + cc, err := Dial(addr, WithBlock(), WithInsecure(), WithCodec(testCodec{})) + if err != nil { + t.Fatalf("Failed to create ClientConn: %v", err) + } + return server, cc +} + +func TestInvoke(t *testing.T) { + server, cc := setUp(t, 0, math.MaxUint32) + var reply string + if err := Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, cc); err != nil || reply != expectedResponse { + t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want ", err) + } + cc.Close() + server.stop() +} + +func TestInvokeLargeErr(t *testing.T) { + server, cc := setUp(t, 0, math.MaxUint32) + var reply string + req := "hello" + err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc) + if _, ok := err.(*rpcError); !ok { + t.Fatalf("grpc.Invoke(_, _, _, _, _) receives non rpc error.") + } + if Code(err) != codes.Internal || len(ErrorDesc(err)) != sizeLargeErr { + t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want an error of code %d and desc size %d", err, codes.Internal, sizeLargeErr) + } + cc.Close() + server.stop() +} + +// TestInvokeErrorSpecialChars checks that error messages don't get mangled. +func TestInvokeErrorSpecialChars(t *testing.T) { + server, cc := setUp(t, 0, math.MaxUint32) + var reply string + req := "weird error" + err := Invoke(context.Background(), "/foo/bar", &req, &reply, cc) + if _, ok := err.(*rpcError); !ok { + t.Fatalf("grpc.Invoke(_, _, _, _, _) receives non rpc error.") + } + if got, want := ErrorDesc(err), weirdError; got != want { + t.Fatalf("grpc.Invoke(_, _, _, _, _) error = %q, want %q", got, want) + } + cc.Close() + server.stop() +} + +// TestInvokeCancel checks that an Invoke with a canceled context is not sent. +func TestInvokeCancel(t *testing.T) { + server, cc := setUp(t, 0, math.MaxUint32) + var reply string + req := "canceled" + for i := 0; i < 100; i++ { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + Invoke(ctx, "/foo/bar", &req, &reply, cc) + } + if canceled != 0 { + t.Fatalf("received %d of 100 canceled requests", canceled) + } + cc.Close() + server.stop() +} diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go new file mode 100644 index 00000000..c3c7691d --- /dev/null +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -0,0 +1,724 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "errors" + "fmt" + "net" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/transport" +) + +var ( + // ErrClientConnClosing indicates that the operation is illegal because + // the ClientConn is closing. + ErrClientConnClosing = errors.New("grpc: the client connection is closing") + // ErrClientConnTimeout indicates that the ClientConn cannot establish the + // underlying connections within the specified timeout. + ErrClientConnTimeout = errors.New("grpc: timed out when dialing") + + // errNoTransportSecurity indicates that there is no transport security + // being set for ClientConn. Users should either set one or explicitly + // call WithInsecure DialOption to disable security. + errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)") + // errTransportCredentialsMissing indicates that users want to transmit security + // information (e.g., oauth2 token) which requires secure connection on an insecure + // connection. + errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)") + // errCredentialsConflict indicates that grpc.WithTransportCredentials() + // and grpc.WithInsecure() are both called for a connection. + errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)") + // errNetworkIP indicates that the connection is down due to some network I/O error. + errNetworkIO = errors.New("grpc: failed with network I/O error") + // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs. + errConnDrain = errors.New("grpc: the connection is drained") + // errConnClosing indicates that the connection is closing. + errConnClosing = errors.New("grpc: the connection is closing") + errNoAddr = errors.New("grpc: there is no address available to dial") + // minimum time to give a connection to complete + minConnectTimeout = 20 * time.Second +) + +// dialOptions configure a Dial call. dialOptions are set by the DialOption +// values passed to Dial. +type dialOptions struct { + codec Codec + cp Compressor + dc Decompressor + bs backoffStrategy + balancer Balancer + block bool + insecure bool + timeout time.Duration + copts transport.ConnectOptions +} + +// DialOption configures how we set up the connection. +type DialOption func(*dialOptions) + +// WithCodec returns a DialOption which sets a codec for message marshaling and unmarshaling. +func WithCodec(c Codec) DialOption { + return func(o *dialOptions) { + o.codec = c + } +} + +// WithCompressor returns a DialOption which sets a CompressorGenerator for generating message +// compressor. +func WithCompressor(cp Compressor) DialOption { + return func(o *dialOptions) { + o.cp = cp + } +} + +// WithDecompressor returns a DialOption which sets a DecompressorGenerator for generating +// message decompressor. +func WithDecompressor(dc Decompressor) DialOption { + return func(o *dialOptions) { + o.dc = dc + } +} + +// WithBalancer returns a DialOption which sets a load balancer. +func WithBalancer(b Balancer) DialOption { + return func(o *dialOptions) { + o.balancer = b + } +} + +// WithBackoffMaxDelay configures the dialer to use the provided maximum delay +// when backing off after failed connection attempts. +func WithBackoffMaxDelay(md time.Duration) DialOption { + return WithBackoffConfig(BackoffConfig{MaxDelay: md}) +} + +// WithBackoffConfig configures the dialer to use the provided backoff +// parameters after connection failures. +// +// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up +// for use. +func WithBackoffConfig(b BackoffConfig) DialOption { + // Set defaults to ensure that provided BackoffConfig is valid and + // unexported fields get default values. + setDefaults(&b) + return withBackoff(b) +} + +// withBackoff sets the backoff strategy used for retries after a +// failed connection attempt. +// +// This can be exported if arbitrary backoff strategies are allowed by gRPC. +func withBackoff(bs backoffStrategy) DialOption { + return func(o *dialOptions) { + o.bs = bs + } +} + +// WithBlock returns a DialOption which makes caller of Dial blocks until the underlying +// connection is up. Without this, Dial returns immediately and connecting the server +// happens in background. +func WithBlock() DialOption { + return func(o *dialOptions) { + o.block = true + } +} + +// WithInsecure returns a DialOption which disables transport security for this ClientConn. +// Note that transport security is required unless WithInsecure is set. +func WithInsecure() DialOption { + return func(o *dialOptions) { + o.insecure = true + } +} + +// WithTransportCredentials returns a DialOption which configures a +// connection level security credentials (e.g., TLS/SSL). +func WithTransportCredentials(creds credentials.TransportCredentials) DialOption { + return func(o *dialOptions) { + o.copts.TransportCredentials = creds + } +} + +// WithPerRPCCredentials returns a DialOption which sets +// credentials which will place auth state on each outbound RPC. +func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption { + return func(o *dialOptions) { + o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) + } +} + +// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn +// initially. This is valid if and only if WithBlock() is present. +func WithTimeout(d time.Duration) DialOption { + return func(o *dialOptions) { + o.timeout = d + } +} + +// WithDialer returns a DialOption that specifies a function to use for dialing network addresses. +func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption { + return func(o *dialOptions) { + o.copts.Dialer = f + } +} + +// WithUserAgent returns a DialOption that specifies a user agent string for all the RPCs. +func WithUserAgent(s string) DialOption { + return func(o *dialOptions) { + o.copts.UserAgent = s + } +} + +// Dial creates a client connection the given target. +func Dial(target string, opts ...DialOption) (*ClientConn, error) { + cc := &ClientConn{ + target: target, + conns: make(map[Address]*addrConn), + } + for _, opt := range opts { + opt(&cc.dopts) + } + + // Set defaults. + if cc.dopts.codec == nil { + cc.dopts.codec = protoCodec{} + } + if cc.dopts.bs == nil { + cc.dopts.bs = DefaultBackoffConfig + } + if cc.dopts.balancer == nil { + cc.dopts.balancer = RoundRobin(nil) + } + + if err := cc.dopts.balancer.Start(target); err != nil { + return nil, err + } + var ( + ok bool + addrs []Address + ) + ch := cc.dopts.balancer.Notify() + if ch == nil { + // There is no name resolver installed. + addrs = append(addrs, Address{Addr: target}) + } else { + addrs, ok = <-ch + if !ok || len(addrs) == 0 { + return nil, errNoAddr + } + } + waitC := make(chan error, 1) + go func() { + for _, a := range addrs { + if err := cc.newAddrConn(a, false); err != nil { + waitC <- err + return + } + } + close(waitC) + }() + var timeoutCh <-chan time.Time + if cc.dopts.timeout > 0 { + timeoutCh = time.After(cc.dopts.timeout) + } + select { + case err := <-waitC: + if err != nil { + cc.Close() + return nil, err + } + case <-timeoutCh: + cc.Close() + return nil, ErrClientConnTimeout + } + if ok { + go cc.lbWatcher() + } + colonPos := strings.LastIndex(target, ":") + if colonPos == -1 { + colonPos = len(target) + } + cc.authority = target[:colonPos] + return cc, nil +} + +// ConnectivityState indicates the state of a client connection. +type ConnectivityState int + +const ( + // Idle indicates the ClientConn is idle. + Idle ConnectivityState = iota + // Connecting indicates the ClienConn is connecting. + Connecting + // Ready indicates the ClientConn is ready for work. + Ready + // TransientFailure indicates the ClientConn has seen a failure but expects to recover. + TransientFailure + // Shutdown indicates the ClientConn has started shutting down. + Shutdown +) + +func (s ConnectivityState) String() string { + switch s { + case Idle: + return "IDLE" + case Connecting: + return "CONNECTING" + case Ready: + return "READY" + case TransientFailure: + return "TRANSIENT_FAILURE" + case Shutdown: + return "SHUTDOWN" + default: + panic(fmt.Sprintf("unknown connectivity state: %d", s)) + } +} + +// ClientConn represents a client connection to an RPC server. +type ClientConn struct { + target string + authority string + dopts dialOptions + + mu sync.RWMutex + conns map[Address]*addrConn +} + +func (cc *ClientConn) lbWatcher() { + for addrs := range cc.dopts.balancer.Notify() { + var ( + add []Address // Addresses need to setup connections. + del []*addrConn // Connections need to tear down. + ) + cc.mu.Lock() + for _, a := range addrs { + if _, ok := cc.conns[a]; !ok { + add = append(add, a) + } + } + for k, c := range cc.conns { + var keep bool + for _, a := range addrs { + if k == a { + keep = true + break + } + } + if !keep { + del = append(del, c) + } + } + cc.mu.Unlock() + for _, a := range add { + cc.newAddrConn(a, true) + } + for _, c := range del { + c.tearDown(errConnDrain) + } + } +} + +func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error { + ac := &addrConn{ + cc: cc, + addr: addr, + dopts: cc.dopts, + shutdownChan: make(chan struct{}), + } + if EnableTracing { + ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr) + } + if !ac.dopts.insecure { + if ac.dopts.copts.TransportCredentials == nil { + return errNoTransportSecurity + } + } else { + if ac.dopts.copts.TransportCredentials != nil { + return errCredentialsConflict + } + for _, cd := range ac.dopts.copts.PerRPCCredentials { + if cd.RequireTransportSecurity() { + return errTransportCredentialsMissing + } + } + } + // Insert ac into ac.cc.conns. This needs to be done before any getTransport(...) is called. + ac.cc.mu.Lock() + if ac.cc.conns == nil { + ac.cc.mu.Unlock() + return ErrClientConnClosing + } + stale := ac.cc.conns[ac.addr] + ac.cc.conns[ac.addr] = ac + ac.cc.mu.Unlock() + if stale != nil { + // There is an addrConn alive on ac.addr already. This could be due to + // i) stale's Close is undergoing; + // ii) a buggy Balancer notifies duplicated Addresses. + stale.tearDown(errConnDrain) + } + ac.stateCV = sync.NewCond(&ac.mu) + // skipWait may overwrite the decision in ac.dopts.block. + if ac.dopts.block && !skipWait { + if err := ac.resetTransport(false); err != nil { + ac.tearDown(err) + return err + } + // Start to monitor the error status of transport. + go ac.transportMonitor() + } else { + // Start a goroutine connecting to the server asynchronously. + go func() { + if err := ac.resetTransport(false); err != nil { + grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err) + ac.tearDown(err) + return + } + ac.transportMonitor() + }() + } + return nil +} + +func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { + addr, put, err := cc.dopts.balancer.Get(ctx, opts) + if err != nil { + return nil, nil, toRPCErr(err) + } + cc.mu.RLock() + if cc.conns == nil { + cc.mu.RUnlock() + return nil, nil, toRPCErr(ErrClientConnClosing) + } + ac, ok := cc.conns[addr] + cc.mu.RUnlock() + if !ok { + if put != nil { + put() + } + return nil, nil, Errorf(codes.Internal, "grpc: failed to find the transport to send the rpc") + } + t, err := ac.wait(ctx, !opts.BlockingWait) + if err != nil { + if put != nil { + put() + } + return nil, nil, err + } + return t, put, nil +} + +// Close tears down the ClientConn and all underlying connections. +func (cc *ClientConn) Close() error { + cc.mu.Lock() + if cc.conns == nil { + cc.mu.Unlock() + return ErrClientConnClosing + } + conns := cc.conns + cc.conns = nil + cc.mu.Unlock() + cc.dopts.balancer.Close() + for _, ac := range conns { + ac.tearDown(ErrClientConnClosing) + } + return nil +} + +// addrConn is a network connection to a given address. +type addrConn struct { + cc *ClientConn + addr Address + dopts dialOptions + shutdownChan chan struct{} + events trace.EventLog + + mu sync.Mutex + state ConnectivityState + stateCV *sync.Cond + down func(error) // the handler called when a connection is down. + // ready is closed and becomes nil when a new transport is up or failed + // due to timeout. + ready chan struct{} + transport transport.ClientTransport +} + +// printf records an event in ac's event log, unless ac has been closed. +// REQUIRES ac.mu is held. +func (ac *addrConn) printf(format string, a ...interface{}) { + if ac.events != nil { + ac.events.Printf(format, a...) + } +} + +// errorf records an error in ac's event log, unless ac has been closed. +// REQUIRES ac.mu is held. +func (ac *addrConn) errorf(format string, a ...interface{}) { + if ac.events != nil { + ac.events.Errorf(format, a...) + } +} + +// getState returns the connectivity state of the Conn +func (ac *addrConn) getState() ConnectivityState { + ac.mu.Lock() + defer ac.mu.Unlock() + return ac.state +} + +// waitForStateChange blocks until the state changes to something other than the sourceState. +func (ac *addrConn) waitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { + ac.mu.Lock() + defer ac.mu.Unlock() + if sourceState != ac.state { + return ac.state, nil + } + done := make(chan struct{}) + var err error + go func() { + select { + case <-ctx.Done(): + ac.mu.Lock() + err = ctx.Err() + ac.stateCV.Broadcast() + ac.mu.Unlock() + case <-done: + } + }() + defer close(done) + for sourceState == ac.state { + ac.stateCV.Wait() + if err != nil { + return ac.state, err + } + } + return ac.state, nil +} + +func (ac *addrConn) resetTransport(closeTransport bool) error { + var retries int + for { + ac.mu.Lock() + ac.printf("connecting") + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + return errConnClosing + } + if ac.down != nil { + ac.down(downErrorf(false, true, "%v", errNetworkIO)) + ac.down = nil + } + ac.state = Connecting + ac.stateCV.Broadcast() + t := ac.transport + ac.mu.Unlock() + if closeTransport && t != nil { + t.Close() + } + sleepTime := ac.dopts.bs.backoff(retries) + ac.dopts.copts.Timeout = sleepTime + if sleepTime < minConnectTimeout { + ac.dopts.copts.Timeout = minConnectTimeout + } + connectTime := time.Now() + newTransport, err := transport.NewClientTransport(ac.addr.Addr, &ac.dopts.copts) + if err != nil { + ac.mu.Lock() + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + return errConnClosing + } + ac.errorf("transient failure: %v", err) + ac.state = TransientFailure + ac.stateCV.Broadcast() + if ac.ready != nil { + close(ac.ready) + ac.ready = nil + } + ac.mu.Unlock() + sleepTime -= time.Since(connectTime) + if sleepTime < 0 { + sleepTime = 0 + } + closeTransport = false + select { + case <-time.After(sleepTime): + case <-ac.shutdownChan: + } + retries++ + grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) + continue + } + ac.mu.Lock() + ac.printf("ready") + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + newTransport.Close() + return errConnClosing + } + ac.state = Ready + ac.stateCV.Broadcast() + ac.transport = newTransport + if ac.ready != nil { + close(ac.ready) + ac.ready = nil + } + ac.down = ac.cc.dopts.balancer.Up(ac.addr) + ac.mu.Unlock() + return nil + } +} + +// Run in a goroutine to track the error in transport and create the +// new transport if an error happens. It returns when the channel is closing. +func (ac *addrConn) transportMonitor() { + for { + ac.mu.Lock() + t := ac.transport + ac.mu.Unlock() + select { + // shutdownChan is needed to detect the teardown when + // the addrConn is idle (i.e., no RPC in flight). + case <-ac.shutdownChan: + return + case <-t.Error(): + ac.mu.Lock() + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + return + } + ac.state = TransientFailure + ac.stateCV.Broadcast() + ac.mu.Unlock() + if err := ac.resetTransport(true); err != nil { + ac.mu.Lock() + ac.printf("transport exiting: %v", err) + ac.mu.Unlock() + grpclog.Printf("grpc: addrConn.transportMonitor exits due to: %v", err) + return + } + } + } +} + +// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or +// iv) transport is in TransientFailure and the RPC is fail-fast. +func (ac *addrConn) wait(ctx context.Context, failFast bool) (transport.ClientTransport, error) { + for { + ac.mu.Lock() + switch { + case ac.state == Shutdown: + ac.mu.Unlock() + return nil, errConnClosing + case ac.state == Ready: + ct := ac.transport + ac.mu.Unlock() + return ct, nil + case ac.state == TransientFailure && failFast: + ac.mu.Unlock() + return nil, Errorf(codes.Unavailable, "grpc: RPC failed fast due to transport failure") + default: + ready := ac.ready + if ready == nil { + ready = make(chan struct{}) + ac.ready = ready + } + ac.mu.Unlock() + select { + case <-ctx.Done(): + return nil, toRPCErr(ctx.Err()) + // Wait until the new transport is ready or failed. + case <-ready: + } + } + } +} + +// tearDown starts to tear down the addrConn. +// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in +// some edge cases (e.g., the caller opens and closes many addrConn's in a +// tight loop. +func (ac *addrConn) tearDown(err error) { + ac.mu.Lock() + defer func() { + ac.mu.Unlock() + ac.cc.mu.Lock() + if ac.cc.conns != nil { + delete(ac.cc.conns, ac.addr) + } + ac.cc.mu.Unlock() + }() + if ac.state == Shutdown { + return + } + ac.state = Shutdown + if ac.down != nil { + ac.down(downErrorf(false, false, "%v", err)) + ac.down = nil + } + ac.stateCV.Broadcast() + if ac.events != nil { + ac.events.Finish() + ac.events = nil + } + if ac.ready != nil { + close(ac.ready) + ac.ready = nil + } + if ac.transport != nil { + if err == errConnDrain { + ac.transport.GracefulClose() + } else { + ac.transport.Close() + } + } + if ac.shutdownChan != nil { + close(ac.shutdownChan) + } + return +} diff --git a/vendor/google.golang.org/grpc/clientconn_test.go b/vendor/google.golang.org/grpc/clientconn_test.go new file mode 100644 index 00000000..29db8bfc --- /dev/null +++ b/vendor/google.golang.org/grpc/clientconn_test.go @@ -0,0 +1,126 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "testing" + "time" + + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/oauth" +) + +const tlsDir = "testdata/" + +func TestDialTimeout(t *testing.T) { + conn, err := Dial("Non-Existent.Server:80", WithTimeout(time.Millisecond), WithBlock(), WithInsecure()) + if err == nil { + conn.Close() + } + if err != ErrClientConnTimeout { + t.Fatalf("Dial(_, _) = %v, %v, want %v", conn, err, ErrClientConnTimeout) + } +} + +func TestTLSDialTimeout(t *testing.T) { + creds, err := credentials.NewClientTLSFromFile(tlsDir+"ca.pem", "x.test.youtube.com") + if err != nil { + t.Fatalf("Failed to create credentials %v", err) + } + conn, err := Dial("Non-Existent.Server:80", WithTransportCredentials(creds), WithTimeout(time.Millisecond), WithBlock()) + if err == nil { + conn.Close() + } + if err != ErrClientConnTimeout { + t.Fatalf("grpc.Dial(_, _) = %v, %v, want %v", conn, err, ErrClientConnTimeout) + } +} + +func TestCredentialsMisuse(t *testing.T) { + tlsCreds, err := credentials.NewClientTLSFromFile(tlsDir+"ca.pem", "x.test.youtube.com") + if err != nil { + t.Fatalf("Failed to create authenticator %v", err) + } + // Two conflicting credential configurations + if _, err := Dial("Non-Existent.Server:80", WithTransportCredentials(tlsCreds), WithTimeout(time.Millisecond), WithBlock(), WithInsecure()); err != errCredentialsConflict { + t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errCredentialsConflict) + } + rpcCreds, err := oauth.NewJWTAccessFromKey(nil) + if err != nil { + t.Fatalf("Failed to create credentials %v", err) + } + // security info on insecure connection + if _, err := Dial("Non-Existent.Server:80", WithPerRPCCredentials(rpcCreds), WithTimeout(time.Millisecond), WithBlock(), WithInsecure()); err != errTransportCredentialsMissing { + t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredentialsMissing) + } +} + +func TestWithBackoffConfigDefault(t *testing.T) { + testBackoffConfigSet(t, &DefaultBackoffConfig) +} + +func TestWithBackoffConfig(t *testing.T) { + b := BackoffConfig{MaxDelay: DefaultBackoffConfig.MaxDelay / 2} + expected := b + setDefaults(&expected) // defaults should be set + testBackoffConfigSet(t, &expected, WithBackoffConfig(b)) +} + +func TestWithBackoffMaxDelay(t *testing.T) { + md := DefaultBackoffConfig.MaxDelay / 2 + expected := BackoffConfig{MaxDelay: md} + setDefaults(&expected) + testBackoffConfigSet(t, &expected, WithBackoffMaxDelay(md)) +} + +func testBackoffConfigSet(t *testing.T, expected *BackoffConfig, opts ...DialOption) { + opts = append(opts, WithInsecure()) + conn, err := Dial("foo:80", opts...) + if err != nil { + t.Fatalf("unexpected error dialing connection: %v", err) + } + + if conn.dopts.bs == nil { + t.Fatalf("backoff config not set") + } + + actual, ok := conn.dopts.bs.(BackoffConfig) + if !ok { + t.Fatalf("unexpected type of backoff config: %#v", conn.dopts.bs) + } + + if actual != *expected { + t.Fatalf("unexpected backoff config on connection: %v, want %v", actual, expected) + } +} diff --git a/vendor/google.golang.org/grpc/codegen.sh b/vendor/google.golang.org/grpc/codegen.sh new file mode 100755 index 00000000..b0094888 --- /dev/null +++ b/vendor/google.golang.org/grpc/codegen.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# This script serves as an example to demonstrate how to generate the gRPC-Go +# interface and the related messages from .proto file. +# +# It assumes the installation of i) Google proto buffer compiler at +# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen +# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have +# not, please install them first. +# +# We recommend running this script at $GOPATH/src. +# +# If this is not what you need, feel free to make your own scripts. Again, this +# script is for demonstration purpose. +# +proto=$1 +protoc --go_out=plugins=grpc:. $proto diff --git a/vendor/google.golang.org/grpc/codes/code_string.go b/vendor/google.golang.org/grpc/codes/code_string.go new file mode 100644 index 00000000..e6762d08 --- /dev/null +++ b/vendor/google.golang.org/grpc/codes/code_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type=Code; DO NOT EDIT + +package codes + +import "fmt" + +const _Code_name = "OKCanceledUnknownInvalidArgumentDeadlineExceededNotFoundAlreadyExistsPermissionDeniedResourceExhaustedFailedPreconditionAbortedOutOfRangeUnimplementedInternalUnavailableDataLossUnauthenticated" + +var _Code_index = [...]uint8{0, 2, 10, 17, 32, 48, 56, 69, 85, 102, 120, 127, 137, 150, 158, 169, 177, 192} + +func (i Code) String() string { + if i+1 >= Code(len(_Code_index)) { + return fmt.Sprintf("Code(%d)", i) + } + return _Code_name[_Code_index[i]:_Code_index[i+1]] +} diff --git a/vendor/google.golang.org/grpc/codes/codes.go b/vendor/google.golang.org/grpc/codes/codes.go new file mode 100644 index 00000000..e14b464a --- /dev/null +++ b/vendor/google.golang.org/grpc/codes/codes.go @@ -0,0 +1,159 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package codes defines the canonical error codes used by gRPC. It is +// consistent across various languages. +package codes // import "google.golang.org/grpc/codes" + +// A Code is an unsigned 32-bit error code as defined in the gRPC spec. +type Code uint32 + +//go:generate stringer -type=Code + +const ( + // OK is returned on success. + OK Code = 0 + + // Canceled indicates the operation was cancelled (typically by the caller). + Canceled Code = 1 + + // Unknown error. An example of where this error may be returned is + // if a Status value received from another address space belongs to + // an error-space that is not known in this address space. Also + // errors raised by APIs that do not return enough error information + // may be converted to this error. + Unknown Code = 2 + + // InvalidArgument indicates client specified an invalid argument. + // Note that this differs from FailedPrecondition. It indicates arguments + // that are problematic regardless of the state of the system + // (e.g., a malformed file name). + InvalidArgument Code = 3 + + // DeadlineExceeded means operation expired before completion. + // For operations that change the state of the system, this error may be + // returned even if the operation has completed successfully. For + // example, a successful response from a server could have been delayed + // long enough for the deadline to expire. + DeadlineExceeded Code = 4 + + // NotFound means some requested entity (e.g., file or directory) was + // not found. + NotFound Code = 5 + + // AlreadyExists means an attempt to create an entity failed because one + // already exists. + AlreadyExists Code = 6 + + // PermissionDenied indicates the caller does not have permission to + // execute the specified operation. It must not be used for rejections + // caused by exhausting some resource (use ResourceExhausted + // instead for those errors). It must not be + // used if the caller cannot be identified (use Unauthenticated + // instead for those errors). + PermissionDenied Code = 7 + + // Unauthenticated indicates the request does not have valid + // authentication credentials for the operation. + Unauthenticated Code = 16 + + // ResourceExhausted indicates some resource has been exhausted, perhaps + // a per-user quota, or perhaps the entire file system is out of space. + ResourceExhausted Code = 8 + + // FailedPrecondition indicates operation was rejected because the + // system is not in a state required for the operation's execution. + // For example, directory to be deleted may be non-empty, an rmdir + // operation is applied to a non-directory, etc. + // + // A litmus test that may help a service implementor in deciding + // between FailedPrecondition, Aborted, and Unavailable: + // (a) Use Unavailable if the client can retry just the failing call. + // (b) Use Aborted if the client should retry at a higher-level + // (e.g., restarting a read-modify-write sequence). + // (c) Use FailedPrecondition if the client should not retry until + // the system state has been explicitly fixed. E.g., if an "rmdir" + // fails because the directory is non-empty, FailedPrecondition + // should be returned since the client should not retry unless + // they have first fixed up the directory by deleting files from it. + // (d) Use FailedPrecondition if the client performs conditional + // REST Get/Update/Delete on a resource and the resource on the + // server does not match the condition. E.g., conflicting + // read-modify-write on the same resource. + FailedPrecondition Code = 9 + + // Aborted indicates the operation was aborted, typically due to a + // concurrency issue like sequencer check failures, transaction aborts, + // etc. + // + // See litmus test above for deciding between FailedPrecondition, + // Aborted, and Unavailable. + Aborted Code = 10 + + // OutOfRange means operation was attempted past the valid range. + // E.g., seeking or reading past end of file. + // + // Unlike InvalidArgument, this error indicates a problem that may + // be fixed if the system state changes. For example, a 32-bit file + // system will generate InvalidArgument if asked to read at an + // offset that is not in the range [0,2^32-1], but it will generate + // OutOfRange if asked to read from an offset past the current + // file size. + // + // There is a fair bit of overlap between FailedPrecondition and + // OutOfRange. We recommend using OutOfRange (the more specific + // error) when it applies so that callers who are iterating through + // a space can easily look for an OutOfRange error to detect when + // they are done. + OutOfRange Code = 11 + + // Unimplemented indicates operation is not implemented or not + // supported/enabled in this service. + Unimplemented Code = 12 + + // Internal errors. Means some invariants expected by underlying + // system has been broken. If you see one of these errors, + // something is very broken. + Internal Code = 13 + + // Unavailable indicates the service is currently unavailable. + // This is a most likely a transient condition and may be corrected + // by retrying with a backoff. + // + // See litmus test above for deciding between FailedPrecondition, + // Aborted, and Unavailable. + Unavailable Code = 14 + + // DataLoss indicates unrecoverable data loss or corruption. + DataLoss Code = 15 +) diff --git a/vendor/google.golang.org/grpc/coverage.sh b/vendor/google.golang.org/grpc/coverage.sh new file mode 100755 index 00000000..12023537 --- /dev/null +++ b/vendor/google.golang.org/grpc/coverage.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -e + +workdir=.cover +profile="$workdir/cover.out" +mode=set +end2endtest="google.golang.org/grpc/test" + +generate_cover_data() { + rm -rf "$workdir" + mkdir "$workdir" + + for pkg in "$@"; do + if [ $pkg == "google.golang.org/grpc" -o $pkg == "google.golang.org/grpc/transport" -o $pkg == "google.golang.org/grpc/metadata" -o $pkg == "google.golang.org/grpc/credentials" ] + then + f="$workdir/$(echo $pkg | tr / -)" + go test -covermode="$mode" -coverprofile="$f.cover" "$pkg" + go test -covermode="$mode" -coverpkg "$pkg" -coverprofile="$f.e2e.cover" "$end2endtest" + fi + done + + echo "mode: $mode" >"$profile" + grep -h -v "^mode:" "$workdir"/*.cover >>"$profile" +} + +show_cover_report() { + go tool cover -${1}="$profile" +} + +push_to_coveralls() { + goveralls -coverprofile="$profile" +} + +generate_cover_data $(go list ./...) +show_cover_report func +case "$1" in +"") + ;; +--html) + show_cover_report html ;; +--coveralls) + push_to_coveralls ;; +*) + echo >&2 "error: invalid option: $1" ;; +esac +rm -rf "$workdir" diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go new file mode 100644 index 00000000..53707902 --- /dev/null +++ b/vendor/google.golang.org/grpc/credentials/credentials.go @@ -0,0 +1,226 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package credentials implements various credentials supported by gRPC library, +// which encapsulate all the state needed by a client to authenticate with a +// server and make various assertions, e.g., about the client's identity, role, +// or whether it is authorized to make a particular call. +package credentials // import "google.golang.org/grpc/credentials" + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "net" + "strings" + "time" + + "golang.org/x/net/context" +) + +var ( + // alpnProtoStr are the specified application level protocols for gRPC. + alpnProtoStr = []string{"h2"} +) + +// PerRPCCredentials defines the common interface for the credentials which need to +// attach security information to every RPC (e.g., oauth2). +type PerRPCCredentials interface { + // GetRequestMetadata gets the current request metadata, refreshing + // tokens if required. This should be called by the transport layer on + // each request, and the data should be populated in headers or other + // context. uri is the URI of the entry point for the request. When + // supported by the underlying implementation, ctx can be used for + // timeout and cancellation. + // TODO(zhaoq): Define the set of the qualified keys instead of leaving + // it as an arbitrary string. + GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) + // RequireTransportSecurity indicates whether the credentials requires + // transport security. + RequireTransportSecurity() bool +} + +// ProtocolInfo provides information regarding the gRPC wire protocol version, +// security protocol, security protocol version in use, etc. +type ProtocolInfo struct { + // ProtocolVersion is the gRPC wire protocol version. + ProtocolVersion string + // SecurityProtocol is the security protocol in use. + SecurityProtocol string + // SecurityVersion is the security protocol version. + SecurityVersion string +} + +// AuthInfo defines the common interface for the auth information the users are interested in. +type AuthInfo interface { + AuthType() string +} + +// TransportCredentials defines the common interface for all the live gRPC wire +// protocols and supported transport security protocols (e.g., TLS, SSL). +type TransportCredentials interface { + // ClientHandshake does the authentication handshake specified by the corresponding + // authentication protocol on rawConn for clients. It returns the authenticated + // connection and the corresponding auth information about the connection. + ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error) + // ServerHandshake does the authentication handshake for servers. It returns + // the authenticated connection and the corresponding auth information about + // the connection. + ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) + // Info provides the ProtocolInfo of this TransportCredentials. + Info() ProtocolInfo +} + +// TLSInfo contains the auth information for a TLS authenticated connection. +// It implements the AuthInfo interface. +type TLSInfo struct { + State tls.ConnectionState +} + +// AuthType returns the type of TLSInfo as a string. +func (t TLSInfo) AuthType() string { + return "tls" +} + +// tlsCreds is the credentials required for authenticating a connection using TLS. +type tlsCreds struct { + // TLS configuration + config *tls.Config +} + +func (c tlsCreds) Info() ProtocolInfo { + return ProtocolInfo{ + SecurityProtocol: "tls", + SecurityVersion: "1.2", + } +} + +// GetRequestMetadata returns nil, nil since TLS credentials does not have +// metadata. +func (c *tlsCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + return nil, nil +} + +func (c *tlsCreds) RequireTransportSecurity() bool { + return true +} + +type timeoutError struct{} + +func (timeoutError) Error() string { return "credentials: Dial timed out" } +func (timeoutError) Timeout() bool { return true } +func (timeoutError) Temporary() bool { return true } + +func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) { + // borrow some code from tls.DialWithDialer + var errChannel chan error + if timeout != 0 { + errChannel = make(chan error, 2) + time.AfterFunc(timeout, func() { + errChannel <- timeoutError{} + }) + } + if c.config.ServerName == "" { + colonPos := strings.LastIndex(addr, ":") + if colonPos == -1 { + colonPos = len(addr) + } + c.config.ServerName = addr[:colonPos] + } + conn := tls.Client(rawConn, c.config) + if timeout == 0 { + err = conn.Handshake() + } else { + go func() { + errChannel <- conn.Handshake() + }() + err = <-errChannel + } + if err != nil { + rawConn.Close() + return nil, nil, err + } + // TODO(zhaoq): Omit the auth info for client now. It is more for + // information than anything else. + return conn, nil, nil +} + +func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { + conn := tls.Server(rawConn, c.config) + if err := conn.Handshake(); err != nil { + rawConn.Close() + return nil, nil, err + } + return conn, TLSInfo{conn.ConnectionState()}, nil +} + +// NewTLS uses c to construct a TransportCredentials based on TLS. +func NewTLS(c *tls.Config) TransportCredentials { + tc := &tlsCreds{c} + tc.config.NextProtos = alpnProtoStr + return tc +} + +// NewClientTLSFromCert constructs a TLS from the input certificate for client. +func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportCredentials { + return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}) +} + +// NewClientTLSFromFile constructs a TLS from the input certificate file for client. +func NewClientTLSFromFile(certFile, serverName string) (TransportCredentials, error) { + b, err := ioutil.ReadFile(certFile) + if err != nil { + return nil, err + } + cp := x509.NewCertPool() + if !cp.AppendCertsFromPEM(b) { + return nil, fmt.Errorf("credentials: failed to append certificates") + } + return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}), nil +} + +// NewServerTLSFromCert constructs a TLS from the input certificate for server. +func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials { + return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}}) +} + +// NewServerTLSFromFile constructs a TLS from the input certificate file and key +// file for server. +func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) { + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return nil, err + } + return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil +} diff --git a/vendor/google.golang.org/grpc/credentials/oauth/oauth.go b/vendor/google.golang.org/grpc/credentials/oauth/oauth.go new file mode 100644 index 00000000..8e68c4d7 --- /dev/null +++ b/vendor/google.golang.org/grpc/credentials/oauth/oauth.go @@ -0,0 +1,180 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package oauth implements gRPC credentials using OAuth. +package oauth + +import ( + "fmt" + "io/ioutil" + + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "golang.org/x/oauth2/jwt" + "google.golang.org/grpc/credentials" +) + +// TokenSource supplies PerRPCCredentials from an oauth2.TokenSource. +type TokenSource struct { + oauth2.TokenSource +} + +// GetRequestMetadata gets the request metadata as a map from a TokenSource. +func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + token, err := ts.Token() + if err != nil { + return nil, err + } + return map[string]string{ + "authorization": token.Type() + " " + token.AccessToken, + }, nil +} + +// RequireTransportSecurity indicates whether the credentails requires transport security. +func (ts TokenSource) RequireTransportSecurity() bool { + return true +} + +type jwtAccess struct { + jsonKey []byte +} + +// NewJWTAccessFromFile creates PerRPCCredentials from the given keyFile. +func NewJWTAccessFromFile(keyFile string) (credentials.PerRPCCredentials, error) { + jsonKey, err := ioutil.ReadFile(keyFile) + if err != nil { + return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) + } + return NewJWTAccessFromKey(jsonKey) +} + +// NewJWTAccessFromKey creates PerRPCCredentials from the given jsonKey. +func NewJWTAccessFromKey(jsonKey []byte) (credentials.PerRPCCredentials, error) { + return jwtAccess{jsonKey}, nil +} + +func (j jwtAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + ts, err := google.JWTAccessTokenSourceFromJSON(j.jsonKey, uri[0]) + if err != nil { + return nil, err + } + token, err := ts.Token() + if err != nil { + return nil, err + } + return map[string]string{ + "authorization": token.TokenType + " " + token.AccessToken, + }, nil +} + +func (j jwtAccess) RequireTransportSecurity() bool { + return true +} + +// oauthAccess supplies PerRPCCredentials from a given token. +type oauthAccess struct { + token oauth2.Token +} + +// NewOauthAccess constructs the PerRPCCredentials using a given token. +func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials { + return oauthAccess{token: *token} +} + +func (oa oauthAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + return map[string]string{ + "authorization": oa.token.TokenType + " " + oa.token.AccessToken, + }, nil +} + +func (oa oauthAccess) RequireTransportSecurity() bool { + return true +} + +// NewComputeEngine constructs the PerRPCCredentials that fetches access tokens from +// Google Compute Engine (GCE)'s metadata server. It is only valid to use this +// if your program is running on a GCE instance. +// TODO(dsymonds): Deprecate and remove this. +func NewComputeEngine() credentials.PerRPCCredentials { + return TokenSource{google.ComputeTokenSource("")} +} + +// serviceAccount represents PerRPCCredentials via JWT signing key. +type serviceAccount struct { + config *jwt.Config +} + +func (s serviceAccount) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + token, err := s.config.TokenSource(ctx).Token() + if err != nil { + return nil, err + } + return map[string]string{ + "authorization": token.TokenType + " " + token.AccessToken, + }, nil +} + +func (s serviceAccount) RequireTransportSecurity() bool { + return true +} + +// NewServiceAccountFromKey constructs the PerRPCCredentials using the JSON key slice +// from a Google Developers service account. +func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) { + config, err := google.JWTConfigFromJSON(jsonKey, scope...) + if err != nil { + return nil, err + } + return serviceAccount{config: config}, nil +} + +// NewServiceAccountFromFile constructs the PerRPCCredentials using the JSON key file +// of a Google Developers service account. +func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) { + jsonKey, err := ioutil.ReadFile(keyFile) + if err != nil { + return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) + } + return NewServiceAccountFromKey(jsonKey, scope...) +} + +// NewApplicationDefault returns "Application Default Credentials". For more +// detail, see https://developers.google.com/accounts/docs/application-default-credentials. +func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.PerRPCCredentials, error) { + t, err := google.DefaultTokenSource(ctx, scope...) + if err != nil { + return nil, err + } + return TokenSource{t}, nil +} diff --git a/vendor/google.golang.org/grpc/doc.go b/vendor/google.golang.org/grpc/doc.go new file mode 100644 index 00000000..a35f2188 --- /dev/null +++ b/vendor/google.golang.org/grpc/doc.go @@ -0,0 +1,6 @@ +/* +Package grpc implements an RPC system called gRPC. + +See www.grpc.io for more information about gRPC. +*/ +package grpc // import "google.golang.org/grpc" diff --git a/vendor/google.golang.org/grpc/examples/README.md b/vendor/google.golang.org/grpc/examples/README.md new file mode 100644 index 00000000..b65f8c5e --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/README.md @@ -0,0 +1,57 @@ +gRPC in 3 minutes (Go) +====================== + +BACKGROUND +------------- +For this sample, we've already generated the server and client stubs from [helloworld.proto](helloworld/helloworld/helloworld.proto). + +PREREQUISITES +------------- + +- This requires Go 1.4 +- Requires that [GOPATH is set](https://golang.org/doc/code.html#GOPATH) + +``` +$ go help gopath +$ # ensure the PATH contains $GOPATH/bin +$ export PATH=$PATH:$GOPATH/bin +``` + +INSTALL +------- + +``` +$ go get -u google.golang.org/grpc/examples/helloworld/greeter_client +$ go get -u google.golang.org/grpc/examples/helloworld/greeter_server +``` + +TRY IT! +------- + +- Run the server + +``` +$ greeter_server & +``` + +- Run the client + +``` +$ greeter_client +``` + +OPTIONAL - Rebuilding the generated code +---------------------------------------- + +1 First [install protoc](https://github.com/google/protobuf/blob/master/README.md) + - For now, this needs to be installed from source + - This is will change once proto3 is officially released + +2 Install the protoc Go plugin. + +``` +$ go get -a github.com/golang/protobuf/protoc-gen-go +$ +$ # from this dir; invoke protoc +$ protoc -I ./helloworld/helloworld/ ./helloworld/helloworld/helloworld.proto --go_out=plugins=grpc:helloworld +``` diff --git a/vendor/google.golang.org/grpc/examples/gotutorial.md b/vendor/google.golang.org/grpc/examples/gotutorial.md new file mode 100644 index 00000000..39833fdf --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/gotutorial.md @@ -0,0 +1,431 @@ +#gRPC Basics: Go + +This tutorial provides a basic Go programmer's introduction to working with gRPC. By walking through this example you'll learn how to: + +- Define a service in a .proto file. +- Generate server and client code using the protocol buffer compiler. +- Use the Go gRPC API to write a simple client and server for your service. + +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. + +This isn't a comprehensive guide to using gRPC in Go: more reference documentation is coming soon. + +## Why use gRPC? + +Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients. + +With gRPC we can define our service once in a .proto file and implement clients and servers in any of gRPC's supported languages, which in turn can be run in environments ranging from servers inside Google to your own tablet - all the complexity of communication between different languages and environments is handled for you by gRPC. We also get all the advantages of working with protocol buffers, including efficient serialization, a simple IDL, and easy interface updating. + +## Example code and setup + +The example code for our tutorial is in [grpc/grpc-go/examples/route_guide](https://github.com/grpc/grpc-go/tree/master/examples/route_guide). To download the example, clone the `grpc-go` repository by running the following command: +```shell +$ go get google.golang.org/grpc +``` + +Then change your current directory to `grpc-go/examples/route_guide`: +```shell +$ cd $GOPATH/src/google.golang.org/grpc/examples/route_guide +``` + +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Go quick start guide](examples/). + + +## Defining the service + +Our first step (as you'll know from the [quick start](http://www.grpc.io/docs/#quick-start)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/route_guide/proto/route_guide.proto`](examples/route_guide/proto/route_guide.proto). + +To define a service, you specify a named `service` in your .proto file: + +```proto +service RouteGuide { + ... +} +``` + +Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service: + +- A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call. +```proto + // Obtains the feature at a given position. + rpc GetFeature(Point) returns (Feature) {} +``` + +- A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type. +```proto + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} +``` + +- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a client-side streaming method by placing the `stream` keyword before the *request* type. +```proto + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} +``` + +- A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response. +```proto + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +``` + +Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type: +```proto +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} +``` + + +## Generating client and server code + +Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC Go plugin. + +For simplicity, we've provided a [bash script](https://github.com/grpc/grpc-go/blob/master/codegen.sh) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this by yourself, make sure you've installed protoc and followed the gRPC-Go [installation instructions](https://github.com/grpc/grpc-go/blob/master/README.md) first): + +```shell +$ codegen.sh route_guide.proto +``` + +which actually runs: + +```shell +$ protoc --go_out=plugins=grpc:. route_guide.proto +``` + +Running this command generates the following file in your current directory: +- `route_guide.pb.go` + +This contains: +- All the protocol buffer code to populate, serialize, and retrieve our request and response message types +- An interface type (or *stub*) for clients to call with the methods defined in the `RouteGuide` service. +- An interface type for servers to implement, also with the methods defined in the `RouteGuide` service. + + + +## Creating the server + +First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC clients, you can skip this section and go straight to [Creating the client](#client) (though you might find it interesting anyway!). + +There are two parts to making our `RouteGuide` service do its job: +- Implementing the service interface generated from our service definition: doing the actual "work" of our service. +- Running a gRPC server to listen for requests from clients and dispatch them to the right service implementation. + +You can find our example `RouteGuide` server in [grpc-go/examples/route_guide/server/server.go](https://github.com/grpc/grpc-go/tree/master/examples/route_guide/server/server.go). Let's take a closer look at how it works. + +### Implementing RouteGuide + +As you can see, our server has a `routeGuideServer` struct type that implements the generated `RouteGuideServer` interface: + +```go +type routeGuideServer struct { + ... +} +... + +func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) { + ... +} +... + +func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error { + ... +} +... + +func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error { + ... +} +... + +func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error { + ... +} +... +``` + +#### Simple RPC +`routeGuideServer` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`. + +```go +func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) { + for _, feature := range s.savedFeatures { + if proto.Equal(feature.Location, point) { + return feature, nil + } + } + // No feature was found, return an unnamed feature + return &pb.Feature{"", point}, nil +} +``` + +The method is passed a context object for the RPC and the client's `Point` protocol buffer request. It returns a `Feature` protocol buffer object with the response information and an `error`. In the method we populate the `Feature` with the appropriate information, and then `return` it along with an `nil` error to tell gRPC that we've finished dealing with the RPC and that the `Feature` can be returned to the client. + +#### Server-side streaming RPC +Now let's look at one of our streaming RPCs. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature`s to our client. + +```go +func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error { + for _, feature := range s.savedFeatures { + if inRange(feature.Location, rect) { + if err := stream.Send(feature); err != nil { + return err + } + } + } + return nil +} +``` + +As you can see, instead of getting simple request and response objects in our method parameters, this time we get a request object (the `Rectangle` in which our client wants to find `Feature`s) and a special `RouteGuide_ListFeaturesServer` object to write our responses. + +In the method, we populate as many `Feature` objects as we need to return, writing them to the `RouteGuide_ListFeaturesServer` using its `Send()` method. Finally, as in our simple RPC, we return a `nil` error to tell gRPC that we've finished writing responses. Should any error happen in this call, we return a non-`nil` error; the gRPC layer will translate it into an appropriate RPC status to be sent on the wire. + +#### Client-side streaming RPC +Now let's look at something a little more complicated: the client-side streaming method `RecordRoute`, where we get a stream of `Point`s from the client and return a single `RouteSummary` with information about their trip. As you can see, this time the method doesn't have a request parameter at all. Instead, it gets a `RouteGuide_RecordRouteServer` stream, which the server can use to both read *and* write messages - it can receive client messages using its `Recv()` method and return its single response using its `SendAndClose()` method. + +```go +func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error { + var pointCount, featureCount, distance int32 + var lastPoint *pb.Point + startTime := time.Now() + for { + point, err := stream.Recv() + if err == io.EOF { + endTime := time.Now() + return stream.SendAndClose(&pb.RouteSummary{ + PointCount: pointCount, + FeatureCount: featureCount, + Distance: distance, + ElapsedTime: int32(endTime.Sub(startTime).Seconds()), + }) + } + if err != nil { + return err + } + pointCount++ + for _, feature := range s.savedFeatures { + if proto.Equal(feature.Location, point) { + featureCount++ + } + } + if lastPoint != nil { + distance += calcDistance(lastPoint, point) + } + lastPoint = point + } +} +``` + +In the method body we use the `RouteGuide_RecordRouteServer`s `Recv()` method to repeatedly read in our client's requests to a request object (in this case a `Point`) until there are no more messages: the server needs to check the the error returned from `Recv()` after each call. If this is `nil`, the stream is still good and it can continue reading; if it's `io.EOF` the message stream has ended and the server can return its `RouteSummary`. If it has any other value, we return the error "as is" so that it'll be translated to an RPC status by the gRPC layer. + +#### Bidirectional streaming RPC +Finally, let's look at our bidirectional streaming RPC `RouteChat()`. + +```go +func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + key := serialize(in.Location) + ... // look for notes to be sent to client + for _, note := range s.routeNotes[key] { + if err := stream.Send(note); err != nil { + return err + } + } + } +} +``` + +This time we get a `RouteGuide_RouteChatServer` stream that, as in our client-side streaming example, can be used to read and write messages. However, this time we return values via our method's stream while the client is still writing messages to *their* message stream. + +The syntax for reading and writing here is very similar to our client-streaming method, except the server uses the stream's `Send()` method rather than `SendAndClose()` because it's writing multiple responses. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. + +### Starting the server + +Once we've implemented all our methods, we also need to start up a gRPC server so that clients can actually use our service. The following snippet shows how we do this for our `RouteGuide` service: + +```go +flag.Parse() +lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) +if err != nil { + log.Fatalf("failed to listen: %v", err) +} +grpcServer := grpc.NewServer() +pb.RegisterRouteGuideServer(grpcServer, &routeGuideServer{}) +... // determine whether to use TLS +grpcServer.Serve(lis) +``` +To build and start a server, we: + +1. Specify the port we want to use to listen for client requests using `lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))`. +2. Create an instance of the gRPC server using `grpc.NewServer()`. +3. Register our service implementation with the gRPC server. +4. Call `Serve()` on the server with our port details to do a blocking wait until the process is killed or `Stop()` is called. + + +## Creating the client + +In this section, we'll look at creating a Go client for our `RouteGuide` service. You can see our complete example client code in [grpc-go/examples/route_guide/client/client.go](https://github.com/grpc/grpc-go/tree/master/examples/route_guide/client/client.go). + +### Creating a stub + +To call service methods, we first need to create a gRPC *channel* to communicate with the server. We create this by passing the server address and port number to `grpc.Dial()` as follows: + +```go +conn, err := grpc.Dial(*serverAddr) +if err != nil { + ... +} +defer conn.Close() +``` + +You can use `DialOptions` to set the auth credentials (e.g., TLS, GCE credentials, JWT credentials) in `grpc.Dial` if the service you request requires that - however, we don't need to do this for our `RouteGuide` service. + +Once the gRPC *channel* is setup, we need a client *stub* to perform RPCs. We get this using the `NewRouteGuideClient` method provided in the `pb` package we generated from our .proto. + +```go +client := pb.NewRouteGuideClient(conn) +``` + +### Calling service methods + +Now let's look at how we call our service methods. Note that in gRPC-Go, RPCs operate in a blocking/synchronous mode, which means that the RPC call waits for the server to respond, and will either return a response or an error. + +#### Simple RPC + +Calling the simple RPC `GetFeature` is nearly as straightforward as calling a local method. + +```go +feature, err := client.GetFeature(context.Background(), &pb.Point{409146138, -746188906}) +if err != nil { + ... +} +``` + +As you can see, we call the method on the stub we got earlier. In our method parameters we create and populate a request protocol buffer object (in our case `Point`). We also pass a `context.Context` object which lets us change our RPC's behaviour if necessary, such as time-out/cancel an RPC in flight. If the call doesn't return an error, then we can read the response information from the server from the first return value. + +```go +log.Println(feature) +``` + +#### Server-side streaming RPC + +Here's where we call the server-side streaming method `ListFeatures`, which returns a stream of geographical `Feature`s. If you've already read [Creating the server](#server) some of this may look very familiar - streaming RPCs are implemented in a similar way on both sides. + +```go +rect := &pb.Rectangle{ ... } // initialize a pb.Rectangle +stream, err := client.ListFeatures(context.Background(), rect) +if err != nil { + ... +} +for { + feature, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + log.Fatalf("%v.ListFeatures(_) = _, %v", client, err) + } + log.Println(feature) +} +``` + +As in the simple RPC, we pass the method a context and a request. However, instead of getting a response object back, we get back an instance of `RouteGuide_ListFeaturesClient`. The client can use the `RouteGuide_ListFeaturesClient` stream to read the server's responses. + +We use the `RouteGuide_ListFeaturesClient`'s `Recv()` method to repeatedly read in the server's responses to a response protocol buffer object (in this case a `Feature`) until there are no more messages: the client needs to check the error `err` returned from `Recv()` after each call. If `nil`, the stream is still good and it can continue reading; if it's `io.EOF` then the message stream has ended; otherwise there must be an RPC error, which is passed over through `err`. + +#### Client-side streaming RPC + +The client-side streaming method `RecordRoute` is similar to the server-side method, except that we only pass the method a context and get a `RouteGuide_RecordRouteClient` stream back, which we can use to both write *and* read messages. + +```go +// Create a random number of random points +r := rand.New(rand.NewSource(time.Now().UnixNano())) +pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points +var points []*pb.Point +for i := 0; i < pointCount; i++ { + points = append(points, randomPoint(r)) +} +log.Printf("Traversing %d points.", len(points)) +stream, err := client.RecordRoute(context.Background()) +if err != nil { + log.Fatalf("%v.RecordRoute(_) = _, %v", client, err) +} +for _, point := range points { + if err := stream.Send(point); err != nil { + log.Fatalf("%v.Send(%v) = %v", stream, point, err) + } +} +reply, err := stream.CloseAndRecv() +if err != nil { + log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) +} +log.Printf("Route summary: %v", reply) +``` + +The `RouteGuide_RecordRouteClient` has a `Send()` method that we can use to send requests to the server. Once we've finished writing our client's requests to the stream using `Send()`, we need to call `CloseAndRecv()` on the stream to let gRPC know that we've finished writing and are expecting to receive a response. We get our RPC status from the `err` returned from `CloseAndRecv()`. If the status is `nil`, then the first return value from `CloseAndRecv()` will be a valid server response. + +#### Bidirectional streaming RPC + +Finally, let's look at our bidirectional streaming RPC `RouteChat()`. As in the case of `RecordRoute`, we only pass the method a context object and get back a stream that we can use to both write and read messages. However, this time we return values via our method's stream while the server is still writing messages to *their* message stream. + +```go +stream, err := client.RouteChat(context.Background()) +waitc := make(chan struct{}) +go func() { + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + close(waitc) + return + } + if err != nil { + log.Fatalf("Failed to receive a note : %v", err) + } + log.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude) + } +}() +for _, note := range notes { + if err := stream.Send(note); err != nil { + log.Fatalf("Failed to send a note: %v", err) + } +} +stream.CloseSend() +<-waitc +``` + +The syntax for reading and writing here is very similar to our client-side streaming method, except we use the stream's `CloseSend()` method once we've finished our call. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. + +## Try it out! + +To compile and run the server, assuming you are in the folder +`$GOPATH/src/google.golang.org/grpc/examples/route_guide`, simply: + +```sh +$ go run server/server.go +``` + +Likewise, to run the client: + +```sh +$ go run client/client.go +``` + diff --git a/vendor/google.golang.org/grpc/examples/helloworld/greeter_client/main.go b/vendor/google.golang.org/grpc/examples/helloworld/greeter_client/main.go new file mode 100644 index 00000000..a451c99d --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/helloworld/greeter_client/main.go @@ -0,0 +1,69 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "log" + "os" + + "golang.org/x/net/context" + "google.golang.org/grpc" + pb "google.golang.org/grpc/examples/helloworld/helloworld" +) + +const ( + address = "localhost:50051" + defaultName = "world" +) + +func main() { + // Set up a connection to the server. + conn, err := grpc.Dial(address, grpc.WithInsecure()) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + c := pb.NewGreeterClient(conn) + + // Contact the server and print out its response. + name := defaultName + if len(os.Args) > 1 { + name = os.Args[1] + } + r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name}) + if err != nil { + log.Fatalf("could not greet: %v", err) + } + log.Printf("Greeting: %s", r.Message) +} diff --git a/vendor/google.golang.org/grpc/examples/helloworld/greeter_server/main.go b/vendor/google.golang.org/grpc/examples/helloworld/greeter_server/main.go new file mode 100644 index 00000000..4dce9e07 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/helloworld/greeter_server/main.go @@ -0,0 +1,65 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "log" + "net" + + "golang.org/x/net/context" + "google.golang.org/grpc" + pb "google.golang.org/grpc/examples/helloworld/helloworld" +) + +const ( + port = ":50051" +) + +// server is used to implement helloworld.GreeterServer. +type server struct{} + +// SayHello implements helloworld.GreeterServer +func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { + return &pb.HelloReply{Message: "Hello " + in.Name}, nil +} + +func main() { + lis, err := net.Listen("tcp", port) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + s := grpc.NewServer() + pb.RegisterGreeterServer(s, &server{}) + s.Serve(lis) +} diff --git a/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.pb.go b/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.pb.go new file mode 100644 index 00000000..0419f6af --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.pb.go @@ -0,0 +1,151 @@ +// Code generated by protoc-gen-go. +// source: helloworld.proto +// DO NOT EDIT! + +/* +Package helloworld is a generated protocol buffer package. + +It is generated from these files: + helloworld.proto + +It has these top-level messages: + HelloRequest + HelloReply +*/ +package helloworld + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The request message containing the user's name. +type HelloRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *HelloRequest) Reset() { *m = HelloRequest{} } +func (m *HelloRequest) String() string { return proto.CompactTextString(m) } +func (*HelloRequest) ProtoMessage() {} +func (*HelloRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// The response message containing the greetings +type HelloReply struct { + Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` +} + +func (m *HelloReply) Reset() { *m = HelloReply{} } +func (m *HelloReply) String() string { return proto.CompactTextString(m) } +func (*HelloReply) ProtoMessage() {} +func (*HelloReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func init() { + proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest") + proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for Greeter service + +type GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc *grpc.ClientConn +} + +func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := grpc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Greeter service + +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) +} + +func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { + s.RegisterService(&_Greeter_serviceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/helloworld.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Greeter_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("helloworld.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 174 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, + 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88, + 0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42, + 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92, + 0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71, + 0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a, + 0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64, + 0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x00, 0xad, 0x50, 0x62, 0x70, 0x32, 0xe0, 0x92, 0xce, 0xcc, 0xd7, + 0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x4b, 0xad, 0x48, 0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0x46, 0x52, 0xeb, + 0xc4, 0x0f, 0x56, 0x1c, 0x0e, 0x62, 0x07, 0x80, 0xbc, 0x14, 0xc0, 0x98, 0xc4, 0x06, 0xf6, 0x9b, + 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x0f, 0xb7, 0xcd, 0xf2, 0xef, 0x00, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.proto b/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.proto new file mode 100644 index 00000000..c3ddd4ae --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.proto @@ -0,0 +1,52 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/vendor/google.golang.org/grpc/examples/route_guide/README.md b/vendor/google.golang.org/grpc/examples/route_guide/README.md new file mode 100644 index 00000000..a7c0c2b0 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/README.md @@ -0,0 +1,35 @@ +# Description +The route guide server and client demonstrate how to use grpc go libraries to +perform unary, client streaming, server streaming and full duplex RPCs. + +Please refer to [gRPC Basics: Go] (http://www.grpc.io/docs/tutorials/basic/go.html) for more information. + +See the definition of the route guide service in proto/route_guide.proto. + +# Run the sample code +To compile and run the server, assuming you are in the root of the route_guide +folder, i.e., .../examples/route_guide/, simply: + +```sh +$ go run server/server.go +``` + +Likewise, to run the client: + +```sh +$ go run client/client.go +``` + +# Optional command line flags +The server and client both take optional command line flags. For example, the +client and server run without TLS by default. To enable TLS: + +```sh +$ go run server/server.go -tls=true +``` + +and + +```sh +$ go run client/client.go -tls=true +``` diff --git a/vendor/google.golang.org/grpc/examples/route_guide/client/client.go b/vendor/google.golang.org/grpc/examples/route_guide/client/client.go new file mode 100644 index 00000000..02c04909 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/client/client.go @@ -0,0 +1,202 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package main implements a simple gRPC client that demonstrates how to use gRPC-Go libraries +// to perform unary, client streaming, server streaming and full duplex RPCs. +// +// It interacts with the route guide service whose definition can be found in proto/route_guide.proto. +package main + +import ( + "flag" + "io" + "math/rand" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + pb "google.golang.org/grpc/examples/route_guide/routeguide" + "google.golang.org/grpc/grpclog" +) + +var ( + tls = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP") + caFile = flag.String("ca_file", "testdata/ca.pem", "The file containning the CA root cert file") + serverAddr = flag.String("server_addr", "127.0.0.1:10000", "The server address in the format of host:port") + serverHostOverride = flag.String("server_host_override", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake") +) + +// printFeature gets the feature for the given point. +func printFeature(client pb.RouteGuideClient, point *pb.Point) { + grpclog.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude) + feature, err := client.GetFeature(context.Background(), point) + if err != nil { + grpclog.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err) + } + grpclog.Println(feature) +} + +// printFeatures lists all the features within the given bounding Rectangle. +func printFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) { + grpclog.Printf("Looking for features within %v", rect) + stream, err := client.ListFeatures(context.Background(), rect) + if err != nil { + grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err) + } + for { + feature, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err) + } + grpclog.Println(feature) + } +} + +// runRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server. +func runRecordRoute(client pb.RouteGuideClient) { + // Create a random number of random points + r := rand.New(rand.NewSource(time.Now().UnixNano())) + pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points + var points []*pb.Point + for i := 0; i < pointCount; i++ { + points = append(points, randomPoint(r)) + } + grpclog.Printf("Traversing %d points.", len(points)) + stream, err := client.RecordRoute(context.Background()) + if err != nil { + grpclog.Fatalf("%v.RecordRoute(_) = _, %v", client, err) + } + for _, point := range points { + if err := stream.Send(point); err != nil { + grpclog.Fatalf("%v.Send(%v) = %v", stream, point, err) + } + } + reply, err := stream.CloseAndRecv() + if err != nil { + grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) + } + grpclog.Printf("Route summary: %v", reply) +} + +// runRouteChat receives a sequence of route notes, while sending notes for various locations. +func runRouteChat(client pb.RouteGuideClient) { + notes := []*pb.RouteNote{ + {&pb.Point{Latitude: 0, Longitude: 1}, "First message"}, + {&pb.Point{Latitude: 0, Longitude: 2}, "Second message"}, + {&pb.Point{Latitude: 0, Longitude: 3}, "Third message"}, + {&pb.Point{Latitude: 0, Longitude: 1}, "Fourth message"}, + {&pb.Point{Latitude: 0, Longitude: 2}, "Fifth message"}, + {&pb.Point{Latitude: 0, Longitude: 3}, "Sixth message"}, + } + stream, err := client.RouteChat(context.Background()) + if err != nil { + grpclog.Fatalf("%v.RouteChat(_) = _, %v", client, err) + } + waitc := make(chan struct{}) + go func() { + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + close(waitc) + return + } + if err != nil { + grpclog.Fatalf("Failed to receive a note : %v", err) + } + grpclog.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude) + } + }() + for _, note := range notes { + if err := stream.Send(note); err != nil { + grpclog.Fatalf("Failed to send a note: %v", err) + } + } + stream.CloseSend() + <-waitc +} + +func randomPoint(r *rand.Rand) *pb.Point { + lat := (r.Int31n(180) - 90) * 1e7 + long := (r.Int31n(360) - 180) * 1e7 + return &pb.Point{lat, long} +} + +func main() { + flag.Parse() + var opts []grpc.DialOption + if *tls { + var sn string + if *serverHostOverride != "" { + sn = *serverHostOverride + } + var creds credentials.TransportCredentials + if *caFile != "" { + var err error + creds, err = credentials.NewClientTLSFromFile(*caFile, sn) + if err != nil { + grpclog.Fatalf("Failed to create TLS credentials %v", err) + } + } else { + creds = credentials.NewClientTLSFromCert(nil, sn) + } + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + conn, err := grpc.Dial(*serverAddr, opts...) + if err != nil { + grpclog.Fatalf("fail to dial: %v", err) + } + defer conn.Close() + client := pb.NewRouteGuideClient(conn) + + // Looking for a valid feature + printFeature(client, &pb.Point{409146138, -746188906}) + + // Feature missing. + printFeature(client, &pb.Point{0, 0}) + + // Looking for features between 40, -75 and 42, -73. + printFeatures(client, &pb.Rectangle{&pb.Point{Latitude: 400000000, Longitude: -750000000}, &pb.Point{Latitude: 420000000, Longitude: -730000000}}) + + // RecordRoute + runRecordRoute(client) + + // RouteChat + runRouteChat(client) +} diff --git a/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.pb.go b/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.pb.go new file mode 100644 index 00000000..9bb1d605 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.pb.go @@ -0,0 +1,488 @@ +// Code generated by protoc-gen-go. +// source: route_guide.proto +// DO NOT EDIT! + +/* +Package routeguide is a generated protocol buffer package. + +It is generated from these files: + route_guide.proto + +It has these top-level messages: + Point + Rectangle + Feature + RouteNote + RouteSummary +*/ +package routeguide + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +type Point struct { + Latitude int32 `protobuf:"varint,1,opt,name=latitude" json:"latitude,omitempty"` + Longitude int32 `protobuf:"varint,2,opt,name=longitude" json:"longitude,omitempty"` +} + +func (m *Point) Reset() { *m = Point{} } +func (m *Point) String() string { return proto.CompactTextString(m) } +func (*Point) ProtoMessage() {} +func (*Point) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +type Rectangle struct { + // One corner of the rectangle. + Lo *Point `protobuf:"bytes,1,opt,name=lo" json:"lo,omitempty"` + // The other corner of the rectangle. + Hi *Point `protobuf:"bytes,2,opt,name=hi" json:"hi,omitempty"` +} + +func (m *Rectangle) Reset() { *m = Rectangle{} } +func (m *Rectangle) String() string { return proto.CompactTextString(m) } +func (*Rectangle) ProtoMessage() {} +func (*Rectangle) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Rectangle) GetLo() *Point { + if m != nil { + return m.Lo + } + return nil +} + +func (m *Rectangle) GetHi() *Point { + if m != nil { + return m.Hi + } + return nil +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +type Feature struct { + // The name of the feature. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The point where the feature is detected. + Location *Point `protobuf:"bytes,2,opt,name=location" json:"location,omitempty"` +} + +func (m *Feature) Reset() { *m = Feature{} } +func (m *Feature) String() string { return proto.CompactTextString(m) } +func (*Feature) ProtoMessage() {} +func (*Feature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Feature) GetLocation() *Point { + if m != nil { + return m.Location + } + return nil +} + +// A RouteNote is a message sent while at a given point. +type RouteNote struct { + // The location from which the message is sent. + Location *Point `protobuf:"bytes,1,opt,name=location" json:"location,omitempty"` + // The message to be sent. + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` +} + +func (m *RouteNote) Reset() { *m = RouteNote{} } +func (m *RouteNote) String() string { return proto.CompactTextString(m) } +func (*RouteNote) ProtoMessage() {} +func (*RouteNote) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *RouteNote) GetLocation() *Point { + if m != nil { + return m.Location + } + return nil +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +type RouteSummary struct { + // The number of points received. + PointCount int32 `protobuf:"varint,1,opt,name=point_count,json=pointCount" json:"point_count,omitempty"` + // The number of known features passed while traversing the route. + FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count,json=featureCount" json:"feature_count,omitempty"` + // The distance covered in metres. + Distance int32 `protobuf:"varint,3,opt,name=distance" json:"distance,omitempty"` + // The duration of the traversal in seconds. + ElapsedTime int32 `protobuf:"varint,4,opt,name=elapsed_time,json=elapsedTime" json:"elapsed_time,omitempty"` +} + +func (m *RouteSummary) Reset() { *m = RouteSummary{} } +func (m *RouteSummary) String() string { return proto.CompactTextString(m) } +func (*RouteSummary) ProtoMessage() {} +func (*RouteSummary) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func init() { + proto.RegisterType((*Point)(nil), "routeguide.Point") + proto.RegisterType((*Rectangle)(nil), "routeguide.Rectangle") + proto.RegisterType((*Feature)(nil), "routeguide.Feature") + proto.RegisterType((*RouteNote)(nil), "routeguide.RouteNote") + proto.RegisterType((*RouteSummary)(nil), "routeguide.RouteSummary") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for RouteGuide service + +type RouteGuideClient interface { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) +} + +type routeGuideClient struct { + cc *grpc.ClientConn +} + +func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient { + return &routeGuideClient{cc} +} + +func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) { + out := new(Feature) + err := grpc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) { + stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[0], c.cc, "/routeguide.RouteGuide/ListFeatures", opts...) + if err != nil { + return nil, err + } + x := &routeGuideListFeaturesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type RouteGuide_ListFeaturesClient interface { + Recv() (*Feature, error) + grpc.ClientStream +} + +type routeGuideListFeaturesClient struct { + grpc.ClientStream +} + +func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) { + m := new(Feature) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) { + stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/routeguide.RouteGuide/RecordRoute", opts...) + if err != nil { + return nil, err + } + x := &routeGuideRecordRouteClient{stream} + return x, nil +} + +type RouteGuide_RecordRouteClient interface { + Send(*Point) error + CloseAndRecv() (*RouteSummary, error) + grpc.ClientStream +} + +type routeGuideRecordRouteClient struct { + grpc.ClientStream +} + +func (x *routeGuideRecordRouteClient) Send(m *Point) error { + return x.ClientStream.SendMsg(m) +} + +func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(RouteSummary) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) { + stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/routeguide.RouteGuide/RouteChat", opts...) + if err != nil { + return nil, err + } + x := &routeGuideRouteChatClient{stream} + return x, nil +} + +type RouteGuide_RouteChatClient interface { + Send(*RouteNote) error + Recv() (*RouteNote, error) + grpc.ClientStream +} + +type routeGuideRouteChatClient struct { + grpc.ClientStream +} + +func (x *routeGuideRouteChatClient) Send(m *RouteNote) error { + return x.ClientStream.SendMsg(m) +} + +func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) { + m := new(RouteNote) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for RouteGuide service + +type RouteGuideServer interface { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + GetFeature(context.Context, *Point) (*Feature, error) + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + RecordRoute(RouteGuide_RecordRouteServer) error + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + RouteChat(RouteGuide_RouteChatServer) error +} + +func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) { + s.RegisterService(&_RouteGuide_serviceDesc, srv) +} + +func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Point) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RouteGuideServer).GetFeature(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/routeguide.RouteGuide/GetFeature", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RouteGuideServer).GetFeature(ctx, req.(*Point)) + } + return interceptor(ctx, in, info, handler) +} + +func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Rectangle) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RouteGuideServer).ListFeatures(m, &routeGuideListFeaturesServer{stream}) +} + +type RouteGuide_ListFeaturesServer interface { + Send(*Feature) error + grpc.ServerStream +} + +type routeGuideListFeaturesServer struct { + grpc.ServerStream +} + +func (x *routeGuideListFeaturesServer) Send(m *Feature) error { + return x.ServerStream.SendMsg(m) +} + +func _RouteGuide_RecordRoute_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(RouteGuideServer).RecordRoute(&routeGuideRecordRouteServer{stream}) +} + +type RouteGuide_RecordRouteServer interface { + SendAndClose(*RouteSummary) error + Recv() (*Point, error) + grpc.ServerStream +} + +type routeGuideRecordRouteServer struct { + grpc.ServerStream +} + +func (x *routeGuideRecordRouteServer) SendAndClose(m *RouteSummary) error { + return x.ServerStream.SendMsg(m) +} + +func (x *routeGuideRecordRouteServer) Recv() (*Point, error) { + m := new(Point) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _RouteGuide_RouteChat_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(RouteGuideServer).RouteChat(&routeGuideRouteChatServer{stream}) +} + +type RouteGuide_RouteChatServer interface { + Send(*RouteNote) error + Recv() (*RouteNote, error) + grpc.ServerStream +} + +type routeGuideRouteChatServer struct { + grpc.ServerStream +} + +func (x *routeGuideRouteChatServer) Send(m *RouteNote) error { + return x.ServerStream.SendMsg(m) +} + +func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) { + m := new(RouteNote) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _RouteGuide_serviceDesc = grpc.ServiceDesc{ + ServiceName: "routeguide.RouteGuide", + HandlerType: (*RouteGuideServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFeature", + Handler: _RouteGuide_GetFeature_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListFeatures", + Handler: _RouteGuide_ListFeatures_Handler, + ServerStreams: true, + }, + { + StreamName: "RecordRoute", + Handler: _RouteGuide_RecordRoute_Handler, + ClientStreams: true, + }, + { + StreamName: "RouteChat", + Handler: _RouteGuide_RouteChat_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("route_guide.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0xc1, 0x4a, 0xeb, 0x40, + 0x14, 0xed, 0xf4, 0xb5, 0xaf, 0x2f, 0x37, 0x79, 0x3c, 0x3a, 0x0f, 0x21, 0x54, 0x41, 0x8d, 0x9b, + 0x6e, 0x0c, 0xa5, 0x82, 0x4b, 0xc5, 0x16, 0xec, 0xa6, 0x48, 0x8d, 0xdd, 0x97, 0x31, 0x19, 0xd3, + 0x81, 0x24, 0x13, 0x92, 0x09, 0xe8, 0x07, 0xf8, 0x05, 0xfe, 0xb0, 0x93, 0xc9, 0xa4, 0x4d, 0xb5, + 0xc5, 0x5d, 0xe6, 0xdc, 0x73, 0xee, 0x3d, 0xf7, 0x5c, 0x02, 0xfd, 0x8c, 0x17, 0x82, 0xae, 0xc2, + 0x82, 0x05, 0xd4, 0x4d, 0x33, 0x2e, 0x38, 0x06, 0x05, 0x29, 0xc4, 0xb9, 0x83, 0xee, 0x82, 0xb3, + 0x44, 0xe0, 0x01, 0xfc, 0x89, 0x88, 0x60, 0xa2, 0x08, 0xa8, 0x8d, 0xce, 0xd0, 0xb0, 0xeb, 0x6d, + 0xde, 0xf8, 0x04, 0x8c, 0x88, 0x27, 0x61, 0x55, 0x6c, 0xab, 0xe2, 0x16, 0x70, 0x1e, 0xc1, 0xf0, + 0xa8, 0x2f, 0x48, 0x12, 0x46, 0x14, 0x9f, 0x43, 0x3b, 0xe2, 0xaa, 0x81, 0x39, 0xee, 0xbb, 0xdb, + 0x41, 0xae, 0x9a, 0xe2, 0xc9, 0x62, 0x49, 0x59, 0x33, 0xd5, 0x66, 0x3f, 0x65, 0xcd, 0x9c, 0x39, + 0xf4, 0xee, 0x29, 0x11, 0x45, 0x46, 0x31, 0x86, 0x4e, 0x42, 0xe2, 0xca, 0x93, 0xe1, 0xa9, 0x6f, + 0x7c, 0x29, 0xbd, 0x72, 0x5f, 0xba, 0xe3, 0xc9, 0xe1, 0x3e, 0x1b, 0x8a, 0xb3, 0x94, 0x06, 0xcb, + 0xea, 0x03, 0x17, 0xbb, 0x5a, 0xf4, 0xa3, 0x16, 0xdb, 0xd0, 0x8b, 0x69, 0x9e, 0x93, 0xb0, 0x5a, + 0xdc, 0xf0, 0xea, 0xa7, 0xf3, 0x81, 0xc0, 0x52, 0x6d, 0x9f, 0x8a, 0x38, 0x26, 0xd9, 0x1b, 0x3e, + 0x05, 0x33, 0x2d, 0xd5, 0x2b, 0x9f, 0x17, 0x89, 0xd0, 0x21, 0x82, 0x82, 0xa6, 0x25, 0x82, 0x2f, + 0xe0, 0xef, 0x4b, 0xb5, 0x95, 0xa6, 0x54, 0x51, 0x5a, 0x1a, 0xac, 0x48, 0xf2, 0x0e, 0x01, 0xcb, + 0x65, 0x9a, 0x3e, 0xb5, 0x7f, 0x55, 0x77, 0xa8, 0xdf, 0x32, 0x39, 0x8b, 0x46, 0x24, 0xcd, 0x69, + 0xb0, 0x12, 0x4c, 0x66, 0xd2, 0x51, 0x75, 0x53, 0x63, 0x4b, 0x09, 0x8d, 0xdf, 0xdb, 0x00, 0xca, + 0xd5, 0xac, 0x5c, 0x07, 0x5f, 0x03, 0xcc, 0xa8, 0xa8, 0xb3, 0xfc, 0xbe, 0xe9, 0xe0, 0x7f, 0x13, + 0xd2, 0x3c, 0xa7, 0x85, 0x6f, 0xc0, 0x9a, 0xcb, 0xa9, 0x1a, 0xc8, 0xf1, 0x51, 0x93, 0xb6, 0xb9, + 0xf6, 0x01, 0xf5, 0x08, 0x49, 0xbd, 0x29, 0x59, 0x3c, 0x0b, 0x94, 0x97, 0x7d, 0x83, 0xed, 0x9d, + 0x8e, 0x8d, 0x1c, 0x9d, 0xd6, 0x10, 0xe1, 0x5b, 0x7d, 0xb2, 0xe9, 0x9a, 0x88, 0x2f, 0xc3, 0xeb, + 0x4b, 0x0e, 0xf6, 0xc3, 0xa5, 0x7c, 0x84, 0x26, 0x23, 0x38, 0x66, 0xdc, 0x0d, 0xb3, 0xd4, 0x77, + 0xe9, 0x2b, 0x89, 0xd3, 0x88, 0xe6, 0x0d, 0xfa, 0xe4, 0xdf, 0x36, 0xa3, 0x45, 0xf9, 0x4f, 0x2c, + 0xd0, 0xf3, 0x6f, 0xf5, 0x73, 0x5c, 0x7d, 0x06, 0x00, 0x00, 0xff, 0xff, 0xc8, 0xe4, 0xef, 0xe6, + 0x31, 0x03, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.proto b/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.proto new file mode 100644 index 00000000..5a782aa2 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/routeguide/route_guide.proto @@ -0,0 +1,125 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.routeguide"; +option java_outer_classname = "RouteGuideProto"; + +package routeguide; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + rpc GetFeature(Point) returns (Feature) {} + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + Point lo = 1; + + // The other corner of the rectangle. + Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + string name = 1; + + // The point where the feature is detected. + Point location = 2; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + Point location = 1; + + // The message to be sent. + string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + int32 point_count = 1; + + // The number of known features passed while traversing the route. + int32 feature_count = 2; + + // The distance covered in metres. + int32 distance = 3; + + // The duration of the traversal in seconds. + int32 elapsed_time = 4; +} diff --git a/vendor/google.golang.org/grpc/examples/route_guide/server/server.go b/vendor/google.golang.org/grpc/examples/route_guide/server/server.go new file mode 100644 index 00000000..c8be4970 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/server/server.go @@ -0,0 +1,239 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries +// to perform unary, client streaming, server streaming and full duplex RPCs. +// +// It implements the route guide service whose definition can be found in proto/route_guide.proto. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io" + "io/ioutil" + "math" + "net" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + + "github.com/golang/protobuf/proto" + + pb "google.golang.org/grpc/examples/route_guide/routeguide" +) + +var ( + tls = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP") + certFile = flag.String("cert_file", "testdata/server1.pem", "The TLS cert file") + keyFile = flag.String("key_file", "testdata/server1.key", "The TLS key file") + jsonDBFile = flag.String("json_db_file", "testdata/route_guide_db.json", "A json file containing a list of features") + port = flag.Int("port", 10000, "The server port") +) + +type routeGuideServer struct { + savedFeatures []*pb.Feature + routeNotes map[string][]*pb.RouteNote +} + +// GetFeature returns the feature at the given point. +func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) { + for _, feature := range s.savedFeatures { + if proto.Equal(feature.Location, point) { + return feature, nil + } + } + // No feature was found, return an unnamed feature + return &pb.Feature{"", point}, nil +} + +// ListFeatures lists all features contained within the given bounding Rectangle. +func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error { + for _, feature := range s.savedFeatures { + if inRange(feature.Location, rect) { + if err := stream.Send(feature); err != nil { + return err + } + } + } + return nil +} + +// RecordRoute records a route composited of a sequence of points. +// +// It gets a stream of points, and responds with statistics about the "trip": +// number of points, number of known features visited, total distance traveled, and +// total time spent. +func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error { + var pointCount, featureCount, distance int32 + var lastPoint *pb.Point + startTime := time.Now() + for { + point, err := stream.Recv() + if err == io.EOF { + endTime := time.Now() + return stream.SendAndClose(&pb.RouteSummary{ + PointCount: pointCount, + FeatureCount: featureCount, + Distance: distance, + ElapsedTime: int32(endTime.Sub(startTime).Seconds()), + }) + } + if err != nil { + return err + } + pointCount++ + for _, feature := range s.savedFeatures { + if proto.Equal(feature.Location, point) { + featureCount++ + } + } + if lastPoint != nil { + distance += calcDistance(lastPoint, point) + } + lastPoint = point + } +} + +// RouteChat receives a stream of message/location pairs, and responds with a stream of all +// previous messages at each of those locations. +func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + key := serialize(in.Location) + if _, present := s.routeNotes[key]; !present { + s.routeNotes[key] = []*pb.RouteNote{in} + } else { + s.routeNotes[key] = append(s.routeNotes[key], in) + } + for _, note := range s.routeNotes[key] { + if err := stream.Send(note); err != nil { + return err + } + } + } +} + +// loadFeatures loads features from a JSON file. +func (s *routeGuideServer) loadFeatures(filePath string) { + file, err := ioutil.ReadFile(filePath) + if err != nil { + grpclog.Fatalf("Failed to load default features: %v", err) + } + if err := json.Unmarshal(file, &s.savedFeatures); err != nil { + grpclog.Fatalf("Failed to load default features: %v", err) + } +} + +func toRadians(num float64) float64 { + return num * math.Pi / float64(180) +} + +// calcDistance calculates the distance between two points using the "haversine" formula. +// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. +func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 { + const CordFactor float64 = 1e7 + const R float64 = float64(6371000) // metres + lat1 := float64(p1.Latitude) / CordFactor + lat2 := float64(p2.Latitude) / CordFactor + lng1 := float64(p1.Longitude) / CordFactor + lng2 := float64(p2.Longitude) / CordFactor + φ1 := toRadians(lat1) + φ2 := toRadians(lat2) + Δφ := toRadians(lat2 - lat1) + Δλ := toRadians(lng2 - lng1) + + a := math.Sin(Δφ/2)*math.Sin(Δφ/2) + + math.Cos(φ1)*math.Cos(φ2)* + math.Sin(Δλ/2)*math.Sin(Δλ/2) + c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) + + distance := R * c + return int32(distance) +} + +func inRange(point *pb.Point, rect *pb.Rectangle) bool { + left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) + right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) + top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) + bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) + + if float64(point.Longitude) >= left && + float64(point.Longitude) <= right && + float64(point.Latitude) >= bottom && + float64(point.Latitude) <= top { + return true + } + return false +} + +func serialize(point *pb.Point) string { + return fmt.Sprintf("%d %d", point.Latitude, point.Longitude) +} + +func newServer() *routeGuideServer { + s := new(routeGuideServer) + s.loadFeatures(*jsonDBFile) + s.routeNotes = make(map[string][]*pb.RouteNote) + return s +} + +func main() { + flag.Parse() + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) + if err != nil { + grpclog.Fatalf("failed to listen: %v", err) + } + var opts []grpc.ServerOption + if *tls { + creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + if err != nil { + grpclog.Fatalf("Failed to generate credentials %v", err) + } + opts = []grpc.ServerOption{grpc.Creds(creds)} + } + grpcServer := grpc.NewServer(opts...) + pb.RegisterRouteGuideServer(grpcServer, newServer()) + grpcServer.Serve(lis) +} diff --git a/vendor/google.golang.org/grpc/examples/route_guide/testdata/ca.pem b/vendor/google.golang.org/grpc/examples/route_guide/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/examples/route_guide/testdata/route_guide_db.json b/vendor/google.golang.org/grpc/examples/route_guide/testdata/route_guide_db.json new file mode 100644 index 00000000..9d6a980a --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/testdata/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] diff --git a/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.key b/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.pem b/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/examples/route_guide/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/grpclog/glogger/glogger.go b/vendor/google.golang.org/grpc/grpclog/glogger/glogger.go new file mode 100644 index 00000000..53e3c539 --- /dev/null +++ b/vendor/google.golang.org/grpc/grpclog/glogger/glogger.go @@ -0,0 +1,72 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* +Package glogger defines glog-based logging for grpc. +*/ +package glogger + +import ( + "github.com/golang/glog" + "google.golang.org/grpc/grpclog" +) + +func init() { + grpclog.SetLogger(&glogger{}) +} + +type glogger struct{} + +func (g *glogger) Fatal(args ...interface{}) { + glog.Fatal(args...) +} + +func (g *glogger) Fatalf(format string, args ...interface{}) { + glog.Fatalf(format, args...) +} + +func (g *glogger) Fatalln(args ...interface{}) { + glog.Fatalln(args...) +} + +func (g *glogger) Print(args ...interface{}) { + glog.Info(args...) +} + +func (g *glogger) Printf(format string, args ...interface{}) { + glog.Infof(format, args...) +} + +func (g *glogger) Println(args ...interface{}) { + glog.Infoln(args...) +} diff --git a/vendor/google.golang.org/grpc/grpclog/logger.go b/vendor/google.golang.org/grpc/grpclog/logger.go new file mode 100644 index 00000000..3b293307 --- /dev/null +++ b/vendor/google.golang.org/grpc/grpclog/logger.go @@ -0,0 +1,93 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* +Package grpclog defines logging for grpc. +*/ +package grpclog // import "google.golang.org/grpc/grpclog" + +import ( + "log" + "os" +) + +// Use golang's standard logger by default. +// Access is not mutex-protected: do not modify except in init() +// functions. +var logger Logger = log.New(os.Stderr, "", log.LstdFlags) + +// Logger mimics golang's standard Logger as an interface. +type Logger interface { + Fatal(args ...interface{}) + Fatalf(format string, args ...interface{}) + Fatalln(args ...interface{}) + Print(args ...interface{}) + Printf(format string, args ...interface{}) + Println(args ...interface{}) +} + +// SetLogger sets the logger that is used in grpc. Call only from +// init() functions. +func SetLogger(l Logger) { + logger = l +} + +// Fatal is equivalent to Print() followed by a call to os.Exit() with a non-zero exit code. +func Fatal(args ...interface{}) { + logger.Fatal(args...) +} + +// Fatalf is equivalent to Printf() followed by a call to os.Exit() with a non-zero exit code. +func Fatalf(format string, args ...interface{}) { + logger.Fatalf(format, args...) +} + +// Fatalln is equivalent to Println() followed by a call to os.Exit()) with a non-zero exit code. +func Fatalln(args ...interface{}) { + logger.Fatalln(args...) +} + +// Print prints to the logger. Arguments are handled in the manner of fmt.Print. +func Print(args ...interface{}) { + logger.Print(args...) +} + +// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf. +func Printf(format string, args ...interface{}) { + logger.Printf(format, args...) +} + +// Println prints to the logger. Arguments are handled in the manner of fmt.Println. +func Println(args ...interface{}) { + logger.Println(args...) +} diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go new file mode 100644 index 00000000..0e6a9100 --- /dev/null +++ b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go @@ -0,0 +1,176 @@ +// Code generated by protoc-gen-go. +// source: health.proto +// DO NOT EDIT! + +/* +Package grpc_health_v1 is a generated protocol buffer package. + +It is generated from these files: + health.proto + +It has these top-level messages: + HealthCheckRequest + HealthCheckResponse +*/ +package grpc_health_v1 + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type HealthCheckResponse_ServingStatus int32 + +const ( + HealthCheckResponse_UNKNOWN HealthCheckResponse_ServingStatus = 0 + HealthCheckResponse_SERVING HealthCheckResponse_ServingStatus = 1 + HealthCheckResponse_NOT_SERVING HealthCheckResponse_ServingStatus = 2 +) + +var HealthCheckResponse_ServingStatus_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SERVING", + 2: "NOT_SERVING", +} +var HealthCheckResponse_ServingStatus_value = map[string]int32{ + "UNKNOWN": 0, + "SERVING": 1, + "NOT_SERVING": 2, +} + +func (x HealthCheckResponse_ServingStatus) String() string { + return proto.EnumName(HealthCheckResponse_ServingStatus_name, int32(x)) +} +func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{1, 0} +} + +type HealthCheckRequest struct { + Service string `protobuf:"bytes,1,opt,name=service" json:"service,omitempty"` +} + +func (m *HealthCheckRequest) Reset() { *m = HealthCheckRequest{} } +func (m *HealthCheckRequest) String() string { return proto.CompactTextString(m) } +func (*HealthCheckRequest) ProtoMessage() {} +func (*HealthCheckRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type HealthCheckResponse struct { + Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,enum=grpc.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"` +} + +func (m *HealthCheckResponse) Reset() { *m = HealthCheckResponse{} } +func (m *HealthCheckResponse) String() string { return proto.CompactTextString(m) } +func (*HealthCheckResponse) ProtoMessage() {} +func (*HealthCheckResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func init() { + proto.RegisterType((*HealthCheckRequest)(nil), "grpc.health.v1.HealthCheckRequest") + proto.RegisterType((*HealthCheckResponse)(nil), "grpc.health.v1.HealthCheckResponse") + proto.RegisterEnum("grpc.health.v1.HealthCheckResponse_ServingStatus", HealthCheckResponse_ServingStatus_name, HealthCheckResponse_ServingStatus_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for Health service + +type HealthClient interface { + Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) +} + +type healthClient struct { + cc *grpc.ClientConn +} + +func NewHealthClient(cc *grpc.ClientConn) HealthClient { + return &healthClient{cc} +} + +func (c *healthClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { + out := new(HealthCheckResponse) + err := grpc.Invoke(ctx, "/grpc.health.v1.Health/Check", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Health service + +type HealthServer interface { + Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) +} + +func RegisterHealthServer(s *grpc.Server, srv HealthServer) { + s.RegisterService(&_Health_serviceDesc, srv) +} + +func _Health_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HealthCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HealthServer).Check(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.health.v1.Health/Check", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HealthServer).Check(ctx, req.(*HealthCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Health_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.health.v1.Health", + HandlerType: (*HealthServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Check", + Handler: _Health_Check_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("health.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 204 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x48, 0x4d, 0xcc, + 0x29, 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x83, + 0x0a, 0x95, 0x19, 0x2a, 0xe9, 0x71, 0x09, 0x79, 0x80, 0x39, 0xce, 0x19, 0xa9, 0xc9, 0xd9, 0x41, + 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0x45, 0x65, 0x99, 0xc9, + 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0xd2, 0x1c, 0x46, 0x2e, 0x61, 0x14, + 0x0d, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x9e, 0x5c, 0x6c, 0xc5, 0x25, 0x89, 0x25, 0xa5, + 0xc5, 0x60, 0x0d, 0x7c, 0x46, 0x86, 0x7a, 0xa8, 0x16, 0xe9, 0x61, 0xd1, 0xa4, 0x17, 0x0c, 0x32, + 0x34, 0x2f, 0x3d, 0x18, 0xac, 0x31, 0x08, 0x6a, 0x80, 0x92, 0x15, 0x17, 0x2f, 0x8a, 0x84, 0x10, + 0x37, 0x17, 0x7b, 0xa8, 0x9f, 0xb7, 0x9f, 0x7f, 0xb8, 0x9f, 0x00, 0x03, 0x88, 0x13, 0xec, 0x1a, + 0x14, 0xe6, 0xe9, 0xe7, 0x2e, 0xc0, 0x28, 0xc4, 0xcf, 0xc5, 0xed, 0xe7, 0x1f, 0x12, 0x0f, 0x13, + 0x60, 0x32, 0x8a, 0xe2, 0x62, 0x83, 0x58, 0x24, 0x14, 0xc0, 0xc5, 0x0a, 0xb6, 0x4c, 0x48, 0x09, + 0xaf, 0x4b, 0xc0, 0xfe, 0x95, 0x52, 0x26, 0xc2, 0xb5, 0x49, 0x6c, 0xe0, 0x10, 0x34, 0x06, 0x04, + 0x00, 0x00, 0xff, 0xff, 0xac, 0x56, 0x2a, 0xcb, 0x51, 0x01, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto new file mode 100644 index 00000000..e2dc0889 --- /dev/null +++ b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package grpc.health.v1; + +message HealthCheckRequest { + string service = 1; +} + +message HealthCheckResponse { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + } + ServingStatus status = 1; +} + +service Health{ + rpc Check(HealthCheckRequest) returns (HealthCheckResponse); +} diff --git a/vendor/google.golang.org/grpc/health/health.go b/vendor/google.golang.org/grpc/health/health.go new file mode 100644 index 00000000..f74fd69b --- /dev/null +++ b/vendor/google.golang.org/grpc/health/health.go @@ -0,0 +1,49 @@ +// Package health provides some utility functions to health-check a server. The implementation +// is based on protobuf. Users need to write their own implementations if other IDLs are used. +package health + +import ( + "sync" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + healthpb "google.golang.org/grpc/health/grpc_health_v1" +) + +type HealthServer struct { + mu sync.Mutex + // statusMap stores the serving status of the services this HealthServer monitors. + statusMap map[string]healthpb.HealthCheckResponse_ServingStatus +} + +func NewHealthServer() *HealthServer { + return &HealthServer{ + statusMap: make(map[string]healthpb.HealthCheckResponse_ServingStatus), + } +} + +func (s *HealthServer) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { + s.mu.Lock() + defer s.mu.Unlock() + if in.Service == "" { + // check the server overall health status. + return &healthpb.HealthCheckResponse{ + Status: healthpb.HealthCheckResponse_SERVING, + }, nil + } + if status, ok := s.statusMap[in.Service]; ok { + return &healthpb.HealthCheckResponse{ + Status: status, + }, nil + } + return nil, grpc.Errorf(codes.NotFound, "unknown service") +} + +// SetServingStatus is called when need to reset the serving status of a service +// or insert a new service entry into the statusMap. +func (s *HealthServer) SetServingStatus(service string, status healthpb.HealthCheckResponse_ServingStatus) { + s.mu.Lock() + s.statusMap[service] = status + s.mu.Unlock() +} diff --git a/vendor/google.golang.org/grpc/interceptor.go b/vendor/google.golang.org/grpc/interceptor.go new file mode 100644 index 00000000..588f59e5 --- /dev/null +++ b/vendor/google.golang.org/grpc/interceptor.go @@ -0,0 +1,74 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "golang.org/x/net/context" +) + +// UnaryServerInfo consists of various information about a unary RPC on +// server side. All per-rpc information may be mutated by the interceptor. +type UnaryServerInfo struct { + // Server is the service implementation the user provides. This is read-only. + Server interface{} + // FullMethod is the full RPC method string, i.e., /package.service/method. + FullMethod string +} + +// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal +// execution of a unary RPC. +type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error) + +// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info +// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper +// of the service method implementation. It is the responsibility of the interceptor to invoke handler +// to complete the RPC. +type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error) + +// StreamServerInfo consists of various information about a streaming RPC on +// server side. All per-rpc information may be mutated by the interceptor. +type StreamServerInfo struct { + // FullMethod is the full RPC method string, i.e., /package.service/method. + FullMethod string + // IsClientStream indicates whether the RPC is a client streaming RPC. + IsClientStream bool + // IsServerStream indicates whether the RPC is a server streaming RPC. + IsServerStream bool +} + +// StreamServerInterceptor provides a hook to intercept the execution of a streaming RPC on the server. +// info contains all the information of this RPC the interceptor can operate on. And handler is the +// service method implementation. It is the responsibility of the interceptor to invoke handler to +// complete the RPC. +type StreamServerInterceptor func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go new file mode 100644 index 00000000..5489143a --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/internal.go @@ -0,0 +1,49 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package internal contains gRPC-internal code for testing, to avoid polluting +// the godoc of the top-level grpc package. +package internal + +// TestingCloseConns closes all existing transports but keeps +// grpcServer.lis accepting new connections. +// +// The provided grpcServer must be of type *grpc.Server. It is untyped +// for circular dependency reasons. +var TestingCloseConns func(grpcServer interface{}) + +// TestingUseHandlerImpl enables the http.Handler-based server implementation. +// It must be called before Serve and requires TLS credentials. +// +// The provided grpcServer must be of type *grpc.Server. It is untyped +// for circular dependency reasons. +var TestingUseHandlerImpl func(grpcServer interface{}) diff --git a/vendor/google.golang.org/grpc/interop/client/client.go b/vendor/google.golang.org/grpc/interop/client/client.go new file mode 100644 index 00000000..98f6cfec --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/client/client.go @@ -0,0 +1,186 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "flag" + "net" + "strconv" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/oauth" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/interop" + testpb "google.golang.org/grpc/interop/grpc_testing" +) + +var ( + useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP") + testCA = flag.Bool("use_test_ca", false, "Whether to replace platform root CAs with test CA as the CA root") + serviceAccountKeyFile = flag.String("service_account_key_file", "", "Path to service account json key file") + oauthScope = flag.String("oauth_scope", "", "The scope for OAuth2 tokens") + defaultServiceAccount = flag.String("default_service_account", "", "Email of GCE default service account") + serverHost = flag.String("server_host", "127.0.0.1", "The server host name") + serverPort = flag.Int("server_port", 10000, "The server port number") + tlsServerName = flag.String("server_host_override", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake if it is not empty. Otherwise, --server_host is used.") + testCase = flag.String("test_case", "large_unary", + `Configure different test cases. Valid options are: + empty_unary : empty (zero bytes) request and response; + large_unary : single request and (large) response; + client_streaming : request streaming with single response; + server_streaming : single request with response streaming; + ping_pong : full-duplex streaming; + empty_stream : full-duplex streaming with zero message; + timeout_on_sleeping_server: fullduplex streaming on a sleeping server; + compute_engine_creds: large_unary with compute engine auth; + service_account_creds: large_unary with service account auth; + jwt_token_creds: large_unary with jwt token auth; + per_rpc_creds: large_unary with per rpc token; + oauth2_auth_token: large_unary with oauth2 token auth; + cancel_after_begin: cancellation after metadata has been sent but before payloads are sent; + cancel_after_first_response: cancellation after receiving 1st message from the server.`) + + // The test CA root cert file + testCAFile = "testdata/ca.pem" +) + +func main() { + flag.Parse() + serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort)) + var opts []grpc.DialOption + if *useTLS { + var sn string + if *tlsServerName != "" { + sn = *tlsServerName + } + var creds credentials.TransportCredentials + if *testCA { + var err error + creds, err = credentials.NewClientTLSFromFile(testCAFile, sn) + if err != nil { + grpclog.Fatalf("Failed to create TLS credentials %v", err) + } + } else { + creds = credentials.NewClientTLSFromCert(nil, sn) + } + opts = append(opts, grpc.WithTransportCredentials(creds)) + if *testCase == "compute_engine_creds" { + opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewComputeEngine())) + } else if *testCase == "service_account_creds" { + jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope) + if err != nil { + grpclog.Fatalf("Failed to create JWT credentials: %v", err) + } + opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds)) + } else if *testCase == "jwt_token_creds" { + jwtCreds, err := oauth.NewJWTAccessFromFile(*serviceAccountKeyFile) + if err != nil { + grpclog.Fatalf("Failed to create JWT credentials: %v", err) + } + opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds)) + } else if *testCase == "oauth2_auth_token" { + opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope)))) + } + } else { + opts = append(opts, grpc.WithInsecure()) + } + conn, err := grpc.Dial(serverAddr, opts...) + if err != nil { + grpclog.Fatalf("Fail to dial: %v", err) + } + defer conn.Close() + tc := testpb.NewTestServiceClient(conn) + switch *testCase { + case "empty_unary": + interop.DoEmptyUnaryCall(tc) + grpclog.Println("EmptyUnaryCall done") + case "large_unary": + interop.DoLargeUnaryCall(tc) + grpclog.Println("LargeUnaryCall done") + case "client_streaming": + interop.DoClientStreaming(tc) + grpclog.Println("ClientStreaming done") + case "server_streaming": + interop.DoServerStreaming(tc) + grpclog.Println("ServerStreaming done") + case "ping_pong": + interop.DoPingPong(tc) + grpclog.Println("Pingpong done") + case "empty_stream": + interop.DoEmptyStream(tc) + grpclog.Println("Emptystream done") + case "timeout_on_sleeping_server": + interop.DoTimeoutOnSleepingServer(tc) + grpclog.Println("TimeoutOnSleepingServer done") + case "compute_engine_creds": + if !*useTLS { + grpclog.Fatalf("TLS is not enabled. TLS is required to execute compute_engine_creds test case.") + } + interop.DoComputeEngineCreds(tc, *defaultServiceAccount, *oauthScope) + grpclog.Println("ComputeEngineCreds done") + case "service_account_creds": + if !*useTLS { + grpclog.Fatalf("TLS is not enabled. TLS is required to execute service_account_creds test case.") + } + interop.DoServiceAccountCreds(tc, *serviceAccountKeyFile, *oauthScope) + grpclog.Println("ServiceAccountCreds done") + case "jwt_token_creds": + if !*useTLS { + grpclog.Fatalf("TLS is not enabled. TLS is required to execute jwt_token_creds test case.") + } + interop.DoJWTTokenCreds(tc, *serviceAccountKeyFile) + grpclog.Println("JWTtokenCreds done") + case "per_rpc_creds": + if !*useTLS { + grpclog.Fatalf("TLS is not enabled. TLS is required to execute per_rpc_creds test case.") + } + interop.DoPerRPCCreds(tc, *serviceAccountKeyFile, *oauthScope) + grpclog.Println("PerRPCCreds done") + case "oauth2_auth_token": + if !*useTLS { + grpclog.Fatalf("TLS is not enabled. TLS is required to execute oauth2_auth_token test case.") + } + interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope) + grpclog.Println("Oauth2TokenCreds done") + case "cancel_after_begin": + interop.DoCancelAfterBegin(tc) + grpclog.Println("CancelAfterBegin done") + case "cancel_after_first_response": + interop.DoCancelAfterFirstResponse(tc) + grpclog.Println("CancelAfterFirstResponse done") + default: + grpclog.Fatal("Unsupported test case: ", *testCase) + } +} diff --git a/vendor/google.golang.org/grpc/interop/client/testdata/ca.pem b/vendor/google.golang.org/grpc/interop/client/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/client/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/interop/client/testdata/server1.key b/vendor/google.golang.org/grpc/interop/client/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/client/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/interop/client/testdata/server1.pem b/vendor/google.golang.org/grpc/interop/client/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/client/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go new file mode 100755 index 00000000..0ceb12df --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go @@ -0,0 +1,788 @@ +// Code generated by protoc-gen-go. +// source: test.proto +// DO NOT EDIT! + +/* +Package grpc_testing is a generated protocol buffer package. + +It is generated from these files: + test.proto + +It has these top-level messages: + Empty + Payload + SimpleRequest + SimpleResponse + StreamingInputCallRequest + StreamingInputCallResponse + ResponseParameters + StreamingOutputCallRequest + StreamingOutputCallResponse +*/ +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The type of payload that should be returned. +type PayloadType int32 + +const ( + // Compressable text format. + PayloadType_COMPRESSABLE PayloadType = 0 + // Uncompressable binary format. + PayloadType_UNCOMPRESSABLE PayloadType = 1 + // Randomly chosen from all other formats defined in this enum. + PayloadType_RANDOM PayloadType = 2 +) + +var PayloadType_name = map[int32]string{ + 0: "COMPRESSABLE", + 1: "UNCOMPRESSABLE", + 2: "RANDOM", +} +var PayloadType_value = map[string]int32{ + "COMPRESSABLE": 0, + "UNCOMPRESSABLE": 1, + "RANDOM": 2, +} + +func (x PayloadType) Enum() *PayloadType { + p := new(PayloadType) + *p = x + return p +} +func (x PayloadType) String() string { + return proto.EnumName(PayloadType_name, int32(x)) +} +func (x *PayloadType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PayloadType_value, data, "PayloadType") + if err != nil { + return err + } + *x = PayloadType(value) + return nil +} +func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type Empty struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// A block of data, to simply increase gRPC message size. +type Payload struct { + // The type of data in body. + Type *PayloadType `protobuf:"varint,1,opt,name=type,enum=grpc.testing.PayloadType" json:"type,omitempty"` + // Primary contents of payload. + Body []byte `protobuf:"bytes,2,opt,name=body" json:"body,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Payload) Reset() { *m = Payload{} } +func (m *Payload) String() string { return proto.CompactTextString(m) } +func (*Payload) ProtoMessage() {} +func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Payload) GetType() PayloadType { + if m != nil && m.Type != nil { + return *m.Type + } + return PayloadType_COMPRESSABLE +} + +func (m *Payload) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +// Unary request. +type SimpleRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + ResponseType *PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + ResponseSize *int32 `protobuf:"varint,2,opt,name=response_size,json=responseSize" json:"response_size,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + // Whether SimpleResponse should include username. + FillUsername *bool `protobuf:"varint,4,opt,name=fill_username,json=fillUsername" json:"fill_username,omitempty"` + // Whether SimpleResponse should include OAuth scope. + FillOauthScope *bool `protobuf:"varint,5,opt,name=fill_oauth_scope,json=fillOauthScope" json:"fill_oauth_scope,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SimpleRequest) Reset() { *m = SimpleRequest{} } +func (m *SimpleRequest) String() string { return proto.CompactTextString(m) } +func (*SimpleRequest) ProtoMessage() {} +func (*SimpleRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *SimpleRequest) GetResponseType() PayloadType { + if m != nil && m.ResponseType != nil { + return *m.ResponseType + } + return PayloadType_COMPRESSABLE +} + +func (m *SimpleRequest) GetResponseSize() int32 { + if m != nil && m.ResponseSize != nil { + return *m.ResponseSize + } + return 0 +} + +func (m *SimpleRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *SimpleRequest) GetFillUsername() bool { + if m != nil && m.FillUsername != nil { + return *m.FillUsername + } + return false +} + +func (m *SimpleRequest) GetFillOauthScope() bool { + if m != nil && m.FillOauthScope != nil { + return *m.FillOauthScope + } + return false +} + +// Unary response, as configured by the request. +type SimpleResponse struct { + // Payload to increase message size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + // The user the request came from, for verifying authentication was + // successful when the client expected it. + Username *string `protobuf:"bytes,2,opt,name=username" json:"username,omitempty"` + // OAuth scope. + OauthScope *string `protobuf:"bytes,3,opt,name=oauth_scope,json=oauthScope" json:"oauth_scope,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SimpleResponse) Reset() { *m = SimpleResponse{} } +func (m *SimpleResponse) String() string { return proto.CompactTextString(m) } +func (*SimpleResponse) ProtoMessage() {} +func (*SimpleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *SimpleResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *SimpleResponse) GetUsername() string { + if m != nil && m.Username != nil { + return *m.Username + } + return "" +} + +func (m *SimpleResponse) GetOauthScope() string { + if m != nil && m.OauthScope != nil { + return *m.OauthScope + } + return "" +} + +// Client-streaming request. +type StreamingInputCallRequest struct { + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingInputCallRequest) Reset() { *m = StreamingInputCallRequest{} } +func (m *StreamingInputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallRequest) ProtoMessage() {} +func (*StreamingInputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *StreamingInputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Client-streaming response. +type StreamingInputCallResponse struct { + // Aggregated size of payloads received from the client. + AggregatedPayloadSize *int32 `protobuf:"varint,1,opt,name=aggregated_payload_size,json=aggregatedPayloadSize" json:"aggregated_payload_size,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingInputCallResponse) Reset() { *m = StreamingInputCallResponse{} } +func (m *StreamingInputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallResponse) ProtoMessage() {} +func (*StreamingInputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *StreamingInputCallResponse) GetAggregatedPayloadSize() int32 { + if m != nil && m.AggregatedPayloadSize != nil { + return *m.AggregatedPayloadSize + } + return 0 +} + +// Configuration for a particular response. +type ResponseParameters struct { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + Size *int32 `protobuf:"varint,1,opt,name=size" json:"size,omitempty"` + // Desired interval between consecutive responses in the response stream in + // microseconds. + IntervalUs *int32 `protobuf:"varint,2,opt,name=interval_us,json=intervalUs" json:"interval_us,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ResponseParameters) Reset() { *m = ResponseParameters{} } +func (m *ResponseParameters) String() string { return proto.CompactTextString(m) } +func (*ResponseParameters) ProtoMessage() {} +func (*ResponseParameters) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *ResponseParameters) GetSize() int32 { + if m != nil && m.Size != nil { + return *m.Size + } + return 0 +} + +func (m *ResponseParameters) GetIntervalUs() int32 { + if m != nil && m.IntervalUs != nil { + return *m.IntervalUs + } + return 0 +} + +// Server-streaming request. +type StreamingOutputCallRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + ResponseType *PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Configuration for each expected response message. + ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters,json=responseParameters" json:"response_parameters,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingOutputCallRequest) Reset() { *m = StreamingOutputCallRequest{} } +func (m *StreamingOutputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallRequest) ProtoMessage() {} +func (*StreamingOutputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *StreamingOutputCallRequest) GetResponseType() PayloadType { + if m != nil && m.ResponseType != nil { + return *m.ResponseType + } + return PayloadType_COMPRESSABLE +} + +func (m *StreamingOutputCallRequest) GetResponseParameters() []*ResponseParameters { + if m != nil { + return m.ResponseParameters + } + return nil +} + +func (m *StreamingOutputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Server-streaming response, as configured by the request and parameters. +type StreamingOutputCallResponse struct { + // Payload to increase response size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingOutputCallResponse) Reset() { *m = StreamingOutputCallResponse{} } +func (m *StreamingOutputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallResponse) ProtoMessage() {} +func (*StreamingOutputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *StreamingOutputCallResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func init() { + proto.RegisterType((*Empty)(nil), "grpc.testing.Empty") + proto.RegisterType((*Payload)(nil), "grpc.testing.Payload") + proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest") + proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse") + proto.RegisterType((*StreamingInputCallRequest)(nil), "grpc.testing.StreamingInputCallRequest") + proto.RegisterType((*StreamingInputCallResponse)(nil), "grpc.testing.StreamingInputCallResponse") + proto.RegisterType((*ResponseParameters)(nil), "grpc.testing.ResponseParameters") + proto.RegisterType((*StreamingOutputCallRequest)(nil), "grpc.testing.StreamingOutputCallRequest") + proto.RegisterType((*StreamingOutputCallResponse)(nil), "grpc.testing.StreamingOutputCallResponse") + proto.RegisterEnum("grpc.testing.PayloadType", PayloadType_name, PayloadType_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for TestService service + +type TestServiceClient interface { + // One empty request followed by one empty response. + EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) +} + +type testServiceClient struct { + cc *grpc.ClientConn +} + +func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) { + out := new(SimpleResponse) + err := grpc.Invoke(ctx, "/grpc.testing.TestService/UnaryCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[0], c.cc, "/grpc.testing.TestService/StreamingOutputCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceStreamingOutputCallClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TestService_StreamingOutputCallClient interface { + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceStreamingOutputCallClient struct { + grpc.ClientStream +} + +func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[1], c.cc, "/grpc.testing.TestService/StreamingInputCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceStreamingInputCallClient{stream} + return x, nil +} + +type TestService_StreamingInputCallClient interface { + Send(*StreamingInputCallRequest) error + CloseAndRecv() (*StreamingInputCallResponse, error) + grpc.ClientStream +} + +type testServiceStreamingInputCallClient struct { + grpc.ClientStream +} + +func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(StreamingInputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[2], c.cc, "/grpc.testing.TestService/FullDuplexCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceFullDuplexCallClient{stream} + return x, nil +} + +type TestService_FullDuplexCallClient interface { + Send(*StreamingOutputCallRequest) error + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceFullDuplexCallClient struct { + grpc.ClientStream +} + +func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[3], c.cc, "/grpc.testing.TestService/HalfDuplexCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceHalfDuplexCallClient{stream} + return x, nil +} + +type TestService_HalfDuplexCallClient interface { + Send(*StreamingOutputCallRequest) error + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceHalfDuplexCallClient struct { + grpc.ClientStream +} + +func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for TestService service + +type TestServiceServer interface { + // One empty request followed by one empty response. + EmptyCall(context.Context, *Empty) (*Empty, error) + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + StreamingInputCall(TestService_StreamingInputCallServer) error + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + FullDuplexCall(TestService_FullDuplexCallServer) error + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + HalfDuplexCall(TestService_HalfDuplexCallServer) error +} + +func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { + s.RegisterService(&_TestService_serviceDesc, srv) +} + +func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).EmptyCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.TestService/EmptyCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SimpleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).UnaryCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.TestService/UnaryCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StreamingOutputCallRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream}) +} + +type TestService_StreamingOutputCallServer interface { + Send(*StreamingOutputCallResponse) error + grpc.ServerStream +} + +type testServiceStreamingOutputCallServer struct { + grpc.ServerStream +} + +func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream}) +} + +type TestService_StreamingInputCallServer interface { + SendAndClose(*StreamingInputCallResponse) error + Recv() (*StreamingInputCallRequest, error) + grpc.ServerStream +} + +type testServiceStreamingInputCallServer struct { + grpc.ServerStream +} + +func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) { + m := new(StreamingInputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream}) +} + +type TestService_FullDuplexCallServer interface { + Send(*StreamingOutputCallResponse) error + Recv() (*StreamingOutputCallRequest, error) + grpc.ServerStream +} + +type testServiceFullDuplexCallServer struct { + grpc.ServerStream +} + +func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) { + m := new(StreamingOutputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream}) +} + +type TestService_HalfDuplexCallServer interface { + Send(*StreamingOutputCallResponse) error + Recv() (*StreamingOutputCallRequest, error) + grpc.ServerStream +} + +type testServiceHalfDuplexCallServer struct { + grpc.ServerStream +} + +func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) { + m := new(StreamingOutputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _TestService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EmptyCall", + Handler: _TestService_EmptyCall_Handler, + }, + { + MethodName: "UnaryCall", + Handler: _TestService_UnaryCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamingOutputCall", + Handler: _TestService_StreamingOutputCall_Handler, + ServerStreams: true, + }, + { + StreamName: "StreamingInputCall", + Handler: _TestService_StreamingInputCall_Handler, + ClientStreams: true, + }, + { + StreamName: "FullDuplexCall", + Handler: _TestService_FullDuplexCall_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "HalfDuplexCall", + Handler: _TestService_HalfDuplexCall_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("test.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 567 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x54, 0x51, 0x6f, 0xd2, 0x50, + 0x14, 0xb6, 0x03, 0x64, 0x1c, 0x58, 0x43, 0x0e, 0x59, 0x64, 0x9d, 0x89, 0x4b, 0x7d, 0xb0, 0x9a, + 0x88, 0x86, 0x44, 0x1f, 0x35, 0x73, 0x63, 0x71, 0x09, 0x03, 0x6c, 0xe1, 0x99, 0x5c, 0xe1, 0x0e, + 0x9b, 0x94, 0xb6, 0xb6, 0xb7, 0x46, 0x7c, 0xf0, 0x8f, 0xf9, 0x67, 0xfc, 0x11, 0xfe, 0x00, 0xef, + 0xbd, 0x6d, 0xa1, 0x40, 0x17, 0x99, 0xc6, 0xbd, 0xb5, 0xdf, 0xf9, 0xce, 0x77, 0xbe, 0xef, 0x9e, + 0xdb, 0x02, 0x30, 0x1a, 0xb2, 0x96, 0x1f, 0x78, 0xcc, 0xc3, 0xda, 0x2c, 0xf0, 0x27, 0x2d, 0x01, + 0xd8, 0xee, 0x4c, 0x2f, 0x43, 0xa9, 0x33, 0xf7, 0xd9, 0x42, 0xef, 0x42, 0x79, 0x40, 0x16, 0x8e, + 0x47, 0xa6, 0xf8, 0x1c, 0x8a, 0x6c, 0xe1, 0xd3, 0xa6, 0x72, 0xa2, 0x18, 0x6a, 0xfb, 0xa8, 0x95, + 0x6d, 0x68, 0x25, 0xa4, 0x21, 0x27, 0x98, 0x92, 0x86, 0x08, 0xc5, 0x8f, 0xde, 0x74, 0xd1, 0xdc, + 0xe3, 0xf4, 0x9a, 0x29, 0x9f, 0xf5, 0x5f, 0x0a, 0x1c, 0x58, 0xf6, 0xdc, 0x77, 0xa8, 0x49, 0x3f, + 0x47, 0xbc, 0x15, 0xdf, 0xc0, 0x41, 0x40, 0x43, 0xdf, 0x73, 0x43, 0x3a, 0xde, 0x4d, 0xbd, 0x96, + 0xf2, 0xc5, 0x1b, 0x3e, 0xce, 0xf4, 0x87, 0xf6, 0x37, 0x2a, 0xc7, 0x95, 0x56, 0x24, 0x8b, 0x63, + 0xf8, 0x02, 0xca, 0x7e, 0xac, 0xd0, 0x2c, 0xf0, 0x72, 0xb5, 0x7d, 0x98, 0x2b, 0x6f, 0xa6, 0x2c, + 0xa1, 0x7a, 0x6d, 0x3b, 0xce, 0x38, 0x0a, 0x69, 0xe0, 0x92, 0x39, 0x6d, 0x16, 0x79, 0xdb, 0xbe, + 0x59, 0x13, 0xe0, 0x28, 0xc1, 0xd0, 0x80, 0xba, 0x24, 0x79, 0x24, 0x62, 0x9f, 0xc6, 0xe1, 0xc4, + 0xe3, 0xee, 0x4b, 0x92, 0xa7, 0x0a, 0xbc, 0x2f, 0x60, 0x4b, 0xa0, 0xfa, 0x77, 0x50, 0xd3, 0xd4, + 0xb1, 0xab, 0xac, 0x23, 0x65, 0x27, 0x47, 0x1a, 0xec, 0x2f, 0xcd, 0x88, 0x88, 0x15, 0x73, 0xf9, + 0x8e, 0x8f, 0xa0, 0x9a, 0xf5, 0x50, 0x90, 0x65, 0xf0, 0x56, 0xf3, 0xbb, 0x70, 0x64, 0xb1, 0x80, + 0x92, 0x39, 0x97, 0xbe, 0x74, 0xfd, 0x88, 0x9d, 0x11, 0xc7, 0x49, 0x37, 0x70, 0x5b, 0x2b, 0xfa, + 0x10, 0xb4, 0x3c, 0xb5, 0x24, 0xd9, 0x6b, 0x78, 0x40, 0x66, 0xb3, 0x80, 0xce, 0x08, 0xa3, 0xd3, + 0x71, 0xd2, 0x13, 0xaf, 0x46, 0x91, 0xab, 0x39, 0x5c, 0x95, 0x13, 0x69, 0xb1, 0x23, 0xfd, 0x12, + 0x30, 0xd5, 0x18, 0x90, 0x80, 0xc7, 0x62, 0x34, 0x08, 0xc5, 0x25, 0xca, 0xb4, 0xca, 0x67, 0x11, + 0xd7, 0x76, 0x79, 0xf5, 0x0b, 0x11, 0x0b, 0x4a, 0x16, 0x0e, 0x29, 0x34, 0x0a, 0xf5, 0x9f, 0x4a, + 0xc6, 0x61, 0x3f, 0x62, 0x1b, 0x81, 0xff, 0xf5, 0xca, 0x7d, 0x80, 0xc6, 0xb2, 0xdf, 0x5f, 0x5a, + 0xe5, 0x3e, 0x0a, 0xfc, 0xf0, 0x4e, 0xd6, 0x55, 0xb6, 0x23, 0x99, 0x18, 0x6c, 0xc7, 0xbc, 0xed, + 0x05, 0xd5, 0x7b, 0x70, 0x9c, 0x9b, 0xf0, 0x2f, 0xaf, 0xd7, 0xb3, 0xb7, 0x50, 0xcd, 0x04, 0xc6, + 0x3a, 0xd4, 0xce, 0xfa, 0x57, 0x03, 0xb3, 0x63, 0x59, 0xa7, 0xef, 0xba, 0x9d, 0xfa, 0x3d, 0xbe, + 0x08, 0x75, 0xd4, 0x5b, 0xc3, 0x14, 0x04, 0xb8, 0x6f, 0x9e, 0xf6, 0xce, 0xfb, 0x57, 0xf5, 0xbd, + 0xf6, 0x8f, 0x22, 0x54, 0x87, 0x5c, 0xdd, 0xe2, 0x4b, 0xb0, 0x27, 0x14, 0x5f, 0x41, 0x45, 0xfe, + 0x40, 0x84, 0x2d, 0x6c, 0xac, 0x4f, 0x97, 0x05, 0x2d, 0x0f, 0xc4, 0x0b, 0xa8, 0x8c, 0x5c, 0x12, + 0xc4, 0x6d, 0xc7, 0xeb, 0x8c, 0xb5, 0x1f, 0x87, 0xf6, 0x30, 0xbf, 0x98, 0x1c, 0x80, 0x03, 0x8d, + 0x9c, 0xf3, 0x41, 0x63, 0xa3, 0xe9, 0xc6, 0x4b, 0xa2, 0x3d, 0xdd, 0x81, 0x19, 0xcf, 0x7a, 0xa9, + 0xa0, 0x0d, 0xb8, 0xfd, 0x45, 0xe0, 0x93, 0x1b, 0x24, 0x36, 0xbf, 0x40, 0xcd, 0xf8, 0x33, 0x31, + 0x1e, 0x65, 0x88, 0x51, 0xea, 0x45, 0xe4, 0x38, 0xe7, 0x11, 0x4f, 0xfb, 0xf5, 0xbf, 0x65, 0x32, + 0x14, 0x99, 0x4a, 0x7d, 0x4f, 0x9c, 0xeb, 0x3b, 0x18, 0xf5, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x4c, + 0x41, 0xfe, 0xb6, 0x89, 0x06, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/test.proto b/vendor/google.golang.org/grpc/interop/grpc_testing/test.proto new file mode 100644 index 00000000..b5bfe053 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/grpc_testing/test.proto @@ -0,0 +1,140 @@ +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +syntax = "proto2"; + +package grpc.testing; + +message Empty {} + +// The type of payload that should be returned. +enum PayloadType { + // Compressable text format. + COMPRESSABLE = 0; + + // Uncompressable binary format. + UNCOMPRESSABLE = 1; + + // Randomly chosen from all other formats defined in this enum. + RANDOM = 2; +} + +// A block of data, to simply increase gRPC message size. +message Payload { + // The type of data in body. + optional PayloadType type = 1; + // Primary contents of payload. + optional bytes body = 2; +} + +// Unary request. +message SimpleRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + optional PayloadType response_type = 1; + + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + optional int32 response_size = 2; + + // Optional input payload sent along with the request. + optional Payload payload = 3; + + // Whether SimpleResponse should include username. + optional bool fill_username = 4; + + // Whether SimpleResponse should include OAuth scope. + optional bool fill_oauth_scope = 5; +} + +// Unary response, as configured by the request. +message SimpleResponse { + // Payload to increase message size. + optional Payload payload = 1; + + // The user the request came from, for verifying authentication was + // successful when the client expected it. + optional string username = 2; + + // OAuth scope. + optional string oauth_scope = 3; +} + +// Client-streaming request. +message StreamingInputCallRequest { + // Optional input payload sent along with the request. + optional Payload payload = 1; + + // Not expecting any payload from the response. +} + +// Client-streaming response. +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + optional int32 aggregated_payload_size = 1; +} + +// Configuration for a particular response. +message ResponseParameters { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + optional int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + optional int32 interval_us = 2; +} + +// Server-streaming request. +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + optional PayloadType response_type = 1; + + // Configuration for each expected response message. + repeated ResponseParameters response_parameters = 2; + + // Optional input payload sent along with the request. + optional Payload payload = 3; +} + +// Server-streaming response, as configured by the request and parameters. +message StreamingOutputCallResponse { + // Payload to increase response size. + optional Payload payload = 1; +} + +// A simple service to test the various types of RPCs and experiment with +// performance with various types of payload. +service TestService { + // One empty request followed by one empty response. + rpc EmptyCall(Empty) returns (Empty); + + // One request followed by one response. + // The server returns the client payload as-is. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + rpc StreamingOutputCall(StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + rpc StreamingInputCall(stream StreamingInputCallRequest) + returns (StreamingInputCallResponse); + + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + rpc FullDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + rpc HalfDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); +} diff --git a/vendor/google.golang.org/grpc/interop/server/server.go b/vendor/google.golang.org/grpc/interop/server/server.go new file mode 100644 index 00000000..36ebcb64 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/server/server.go @@ -0,0 +1,73 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "flag" + "net" + "strconv" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/interop" + testpb "google.golang.org/grpc/interop/grpc_testing" +) + +var ( + useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP") + certFile = flag.String("tls_cert_file", "testdata/server1.pem", "The TLS cert file") + keyFile = flag.String("tls_key_file", "testdata/server1.key", "The TLS key file") + port = flag.Int("port", 10000, "The server port") +) + +func main() { + flag.Parse() + p := strconv.Itoa(*port) + lis, err := net.Listen("tcp", ":"+p) + if err != nil { + grpclog.Fatalf("failed to listen: %v", err) + } + var opts []grpc.ServerOption + if *useTLS { + creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + if err != nil { + grpclog.Fatalf("Failed to generate credentials %v", err) + } + opts = []grpc.ServerOption{grpc.Creds(creds)} + } + server := grpc.NewServer(opts...) + testpb.RegisterTestServiceServer(server, interop.NewTestServer()) + server.Serve(lis) +} diff --git a/vendor/google.golang.org/grpc/interop/server/testdata/ca.pem b/vendor/google.golang.org/grpc/interop/server/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/server/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/interop/server/testdata/server1.key b/vendor/google.golang.org/grpc/interop/server/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/server/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/interop/server/testdata/server1.pem b/vendor/google.golang.org/grpc/interop/server/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/server/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/interop/test_utils.go b/vendor/google.golang.org/grpc/interop/test_utils.go new file mode 100644 index 00000000..23340ab8 --- /dev/null +++ b/vendor/google.golang.org/grpc/interop/test_utils.go @@ -0,0 +1,592 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package interop + +import ( + "fmt" + "io" + "io/ioutil" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + testpb "google.golang.org/grpc/interop/grpc_testing" + "google.golang.org/grpc/metadata" +) + +var ( + reqSizes = []int{27182, 8, 1828, 45904} + respSizes = []int{31415, 9, 2653, 58979} + largeReqSize = 271828 + largeRespSize = 314159 +) + +func clientNewPayload(t testpb.PayloadType, size int) *testpb.Payload { + if size < 0 { + grpclog.Fatalf("Requested a response with invalid length %d", size) + } + body := make([]byte, size) + switch t { + case testpb.PayloadType_COMPRESSABLE: + case testpb.PayloadType_UNCOMPRESSABLE: + grpclog.Fatalf("PayloadType UNCOMPRESSABLE is not supported") + default: + grpclog.Fatalf("Unsupported payload type: %d", t) + } + return &testpb.Payload{ + Type: t.Enum(), + Body: body, + } +} + +// DoEmptyUnaryCall performs a unary RPC with empty request and response messages. +func DoEmptyUnaryCall(tc testpb.TestServiceClient) { + reply, err := tc.EmptyCall(context.Background(), &testpb.Empty{}) + if err != nil { + grpclog.Fatal("/TestService/EmptyCall RPC failed: ", err) + } + if !proto.Equal(&testpb.Empty{}, reply) { + grpclog.Fatalf("/TestService/EmptyCall receives %v, want %v", reply, testpb.Empty{}) + } +} + +// DoLargeUnaryCall performs a unary RPC with large payload in the request and response. +func DoLargeUnaryCall(tc testpb.TestServiceClient) { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + t := reply.GetPayload().GetType() + s := len(reply.GetPayload().GetBody()) + if t != testpb.PayloadType_COMPRESSABLE || s != largeRespSize { + grpclog.Fatalf("Got the reply with type %d len %d; want %d, %d", t, s, testpb.PayloadType_COMPRESSABLE, largeRespSize) + } +} + +// DoClientStreaming performs a client streaming RPC. +func DoClientStreaming(tc testpb.TestServiceClient) { + stream, err := tc.StreamingInputCall(context.Background()) + if err != nil { + grpclog.Fatalf("%v.StreamingInputCall(_) = _, %v", tc, err) + } + var sum int + for _, s := range reqSizes { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, s) + req := &testpb.StreamingInputCallRequest{ + Payload: pl, + } + if err := stream.Send(req); err != nil { + grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) + } + sum += s + grpclog.Printf("Sent a request of size %d, aggregated size %d", s, sum) + + } + reply, err := stream.CloseAndRecv() + if err != nil { + grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) + } + if reply.GetAggregatedPayloadSize() != int32(sum) { + grpclog.Fatalf("%v.CloseAndRecv().GetAggregatePayloadSize() = %v; want %v", stream, reply.GetAggregatedPayloadSize(), sum) + } +} + +// DoServerStreaming performs a server streaming RPC. +func DoServerStreaming(tc testpb.TestServiceClient) { + respParam := make([]*testpb.ResponseParameters, len(respSizes)) + for i, s := range respSizes { + respParam[i] = &testpb.ResponseParameters{ + Size: proto.Int32(int32(s)), + } + } + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + } + stream, err := tc.StreamingOutputCall(context.Background(), req) + if err != nil { + grpclog.Fatalf("%v.StreamingOutputCall(_) = _, %v", tc, err) + } + var rpcStatus error + var respCnt int + var index int + for { + reply, err := stream.Recv() + if err != nil { + rpcStatus = err + break + } + t := reply.GetPayload().GetType() + if t != testpb.PayloadType_COMPRESSABLE { + grpclog.Fatalf("Got the reply of type %d, want %d", t, testpb.PayloadType_COMPRESSABLE) + } + size := len(reply.GetPayload().GetBody()) + if size != int(respSizes[index]) { + grpclog.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) + } + index++ + respCnt++ + } + if rpcStatus != io.EOF { + grpclog.Fatalf("Failed to finish the server streaming rpc: %v", err) + } + if respCnt != len(respSizes) { + grpclog.Fatalf("Got %d reply, want %d", len(respSizes), respCnt) + } +} + +// DoPingPong performs ping-pong style bi-directional streaming RPC. +func DoPingPong(tc testpb.TestServiceClient) { + stream, err := tc.FullDuplexCall(context.Background()) + if err != nil { + grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) + } + var index int + for index < len(reqSizes) { + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(int32(respSizes[index])), + }, + } + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, reqSizes[index]) + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: pl, + } + if err := stream.Send(req); err != nil { + grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) + } + reply, err := stream.Recv() + if err != nil { + grpclog.Fatalf("%v.Recv() = %v", stream, err) + } + t := reply.GetPayload().GetType() + if t != testpb.PayloadType_COMPRESSABLE { + grpclog.Fatalf("Got the reply of type %d, want %d", t, testpb.PayloadType_COMPRESSABLE) + } + size := len(reply.GetPayload().GetBody()) + if size != int(respSizes[index]) { + grpclog.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) + } + index++ + } + if err := stream.CloseSend(); err != nil { + grpclog.Fatalf("%v.CloseSend() got %v, want %v", stream, err, nil) + } + if _, err := stream.Recv(); err != io.EOF { + grpclog.Fatalf("%v failed to complele the ping pong test: %v", stream, err) + } +} + +// DoEmptyStream sets up a bi-directional streaming with zero message. +func DoEmptyStream(tc testpb.TestServiceClient) { + stream, err := tc.FullDuplexCall(context.Background()) + if err != nil { + grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) + } + if err := stream.CloseSend(); err != nil { + grpclog.Fatalf("%v.CloseSend() got %v, want %v", stream, err, nil) + } + if _, err := stream.Recv(); err != io.EOF { + grpclog.Fatalf("%v failed to complete the empty stream test: %v", stream, err) + } +} + +// DoTimeoutOnSleepingServer performs an RPC on a sleep server which causes RPC timeout. +func DoTimeoutOnSleepingServer(tc testpb.TestServiceClient) { + ctx, _ := context.WithTimeout(context.Background(), 1*time.Millisecond) + stream, err := tc.FullDuplexCall(ctx) + if err != nil { + if grpc.Code(err) == codes.DeadlineExceeded { + return + } + grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) + } + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, 27182) + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + Payload: pl, + } + if err := stream.Send(req); err != nil { + grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) + } + if _, err := stream.Recv(); grpc.Code(err) != codes.DeadlineExceeded { + grpclog.Fatalf("%v.Recv() = _, %v, want error code %d", stream, err, codes.DeadlineExceeded) + } +} + +// DoComputeEngineCreds performs a unary RPC with compute engine auth. +func DoComputeEngineCreds(tc testpb.TestServiceClient, serviceAccount, oauthScope string) { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + FillUsername: proto.Bool(true), + FillOauthScope: proto.Bool(true), + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + user := reply.GetUsername() + scope := reply.GetOauthScope() + if user != serviceAccount { + grpclog.Fatalf("Got user name %q, want %q.", user, serviceAccount) + } + if !strings.Contains(oauthScope, scope) { + grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) + } +} + +func getServiceAccountJSONKey(keyFile string) []byte { + jsonKey, err := ioutil.ReadFile(keyFile) + if err != nil { + grpclog.Fatalf("Failed to read the service account key file: %v", err) + } + return jsonKey +} + +// DoServiceAccountCreds performs a unary RPC with service account auth. +func DoServiceAccountCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + FillUsername: proto.Bool(true), + FillOauthScope: proto.Bool(true), + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) + user := reply.GetUsername() + scope := reply.GetOauthScope() + if !strings.Contains(string(jsonKey), user) { + grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) + } + if !strings.Contains(oauthScope, scope) { + grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) + } +} + +// DoJWTTokenCreds performs a unary RPC with JWT token auth. +func DoJWTTokenCreds(tc testpb.TestServiceClient, serviceAccountKeyFile string) { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + FillUsername: proto.Bool(true), + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) + user := reply.GetUsername() + if !strings.Contains(string(jsonKey), user) { + grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) + } +} + +// GetToken obtains an OAUTH token from the input. +func GetToken(serviceAccountKeyFile string, oauthScope string) *oauth2.Token { + jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) + config, err := google.JWTConfigFromJSON(jsonKey, oauthScope) + if err != nil { + grpclog.Fatalf("Failed to get the config: %v", err) + } + token, err := config.TokenSource(context.Background()).Token() + if err != nil { + grpclog.Fatalf("Failed to get the token: %v", err) + } + return token +} + +// DoOauth2TokenCreds performs a unary RPC with OAUTH2 token auth. +func DoOauth2TokenCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + FillUsername: proto.Bool(true), + FillOauthScope: proto.Bool(true), + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) + user := reply.GetUsername() + scope := reply.GetOauthScope() + if !strings.Contains(string(jsonKey), user) { + grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) + } + if !strings.Contains(oauthScope, scope) { + grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) + } +} + +// DoPerRPCCreds performs a unary RPC with per RPC OAUTH2 token. +func DoPerRPCCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { + jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(int32(largeRespSize)), + Payload: pl, + FillUsername: proto.Bool(true), + FillOauthScope: proto.Bool(true), + } + token := GetToken(serviceAccountKeyFile, oauthScope) + kv := map[string]string{"authorization": token.TokenType + " " + token.AccessToken} + ctx := metadata.NewContext(context.Background(), metadata.MD{"authorization": []string{kv["authorization"]}}) + reply, err := tc.UnaryCall(ctx, req) + if err != nil { + grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) + } + user := reply.GetUsername() + scope := reply.GetOauthScope() + if !strings.Contains(string(jsonKey), user) { + grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) + } + if !strings.Contains(oauthScope, scope) { + grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) + } +} + +var ( + testMetadata = metadata.MD{ + "key1": []string{"value1"}, + "key2": []string{"value2"}, + } +) + +// DoCancelAfterBegin cancels the RPC after metadata has been sent but before payloads are sent. +func DoCancelAfterBegin(tc testpb.TestServiceClient) { + ctx, cancel := context.WithCancel(metadata.NewContext(context.Background(), testMetadata)) + stream, err := tc.StreamingInputCall(ctx) + if err != nil { + grpclog.Fatalf("%v.StreamingInputCall(_) = _, %v", tc, err) + } + cancel() + _, err = stream.CloseAndRecv() + if grpc.Code(err) != codes.Canceled { + grpclog.Fatalf("%v.CloseAndRecv() got error code %d, want %d", stream, grpc.Code(err), codes.Canceled) + } +} + +// DoCancelAfterFirstResponse cancels the RPC after receiving the first message from the server. +func DoCancelAfterFirstResponse(tc testpb.TestServiceClient) { + ctx, cancel := context.WithCancel(context.Background()) + stream, err := tc.FullDuplexCall(ctx) + if err != nil { + grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) + } + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(31415), + }, + } + pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, 27182) + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: pl, + } + if err := stream.Send(req); err != nil { + grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) + } + if _, err := stream.Recv(); err != nil { + grpclog.Fatalf("%v.Recv() = %v", stream, err) + } + cancel() + if _, err := stream.Recv(); grpc.Code(err) != codes.Canceled { + grpclog.Fatalf("%v compleled with error code %d, want %d", stream, grpc.Code(err), codes.Canceled) + } +} + +type testServer struct { +} + +// NewTestServer creates a test server for test service. +func NewTestServer() testpb.TestServiceServer { + return &testServer{} +} + +func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { + return new(testpb.Empty), nil +} + +func serverNewPayload(t testpb.PayloadType, size int32) (*testpb.Payload, error) { + if size < 0 { + return nil, fmt.Errorf("requested a response with invalid length %d", size) + } + body := make([]byte, size) + switch t { + case testpb.PayloadType_COMPRESSABLE: + case testpb.PayloadType_UNCOMPRESSABLE: + return nil, fmt.Errorf("payloadType UNCOMPRESSABLE is not supported") + default: + return nil, fmt.Errorf("unsupported payload type: %d", t) + } + return &testpb.Payload{ + Type: t.Enum(), + Body: body, + }, nil +} + +func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + pl, err := serverNewPayload(in.GetResponseType(), in.GetResponseSize()) + if err != nil { + return nil, err + } + return &testpb.SimpleResponse{ + Payload: pl, + }, nil +} + +func (s *testServer) StreamingOutputCall(args *testpb.StreamingOutputCallRequest, stream testpb.TestService_StreamingOutputCallServer) error { + cs := args.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + pl, err := serverNewPayload(args.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: pl, + }); err != nil { + return err + } + } + return nil +} + +func (s *testServer) StreamingInputCall(stream testpb.TestService_StreamingInputCallServer) error { + var sum int + for { + in, err := stream.Recv() + if err == io.EOF { + return stream.SendAndClose(&testpb.StreamingInputCallResponse{ + AggregatedPayloadSize: proto.Int32(int32(sum)), + }) + } + if err != nil { + return err + } + p := in.GetPayload().GetBody() + sum += len(p) + } +} + +func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + return nil + } + if err != nil { + return err + } + cs := in.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + pl, err := serverNewPayload(in.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: pl, + }); err != nil { + return err + } + } + } +} + +func (s *testServer) HalfDuplexCall(stream testpb.TestService_HalfDuplexCallServer) error { + var msgBuf []*testpb.StreamingOutputCallRequest + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + break + } + if err != nil { + return err + } + msgBuf = append(msgBuf, in) + } + for _, m := range msgBuf { + cs := m.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + pl, err := serverNewPayload(m.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: pl, + }); err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/google.golang.org/grpc/metadata/metadata.go b/vendor/google.golang.org/grpc/metadata/metadata.go new file mode 100644 index 00000000..52070dbe --- /dev/null +++ b/vendor/google.golang.org/grpc/metadata/metadata.go @@ -0,0 +1,134 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package metadata define the structure of the metadata supported by gRPC library. +package metadata // import "google.golang.org/grpc/metadata" + +import ( + "encoding/base64" + "fmt" + "strings" + + "golang.org/x/net/context" +) + +const ( + binHdrSuffix = "-bin" +) + +// encodeKeyValue encodes key and value qualified for transmission via gRPC. +// Transmitting binary headers violates HTTP/2 spec. +// TODO(zhaoq): Maybe check if k is ASCII also. +func encodeKeyValue(k, v string) (string, string) { + k = strings.ToLower(k) + if strings.HasSuffix(k, binHdrSuffix) { + val := base64.StdEncoding.EncodeToString([]byte(v)) + v = string(val) + } + return k, v +} + +// DecodeKeyValue returns the original key and value corresponding to the +// encoded data in k, v. +func DecodeKeyValue(k, v string) (string, string, error) { + if !strings.HasSuffix(k, binHdrSuffix) { + return k, v, nil + } + val, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return "", "", err + } + return k, string(val), nil +} + +// MD is a mapping from metadata keys to values. Users should use the following +// two convenience functions New and Pairs to generate MD. +type MD map[string][]string + +// New creates a MD from given key-value map. +func New(m map[string]string) MD { + md := MD{} + for k, v := range m { + key, val := encodeKeyValue(k, v) + md[key] = append(md[key], val) + } + return md +} + +// Pairs returns an MD formed by the mapping of key, value ... +// Pairs panics if len(kv) is odd. +func Pairs(kv ...string) MD { + if len(kv)%2 == 1 { + panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv))) + } + md := MD{} + var k string + for i, s := range kv { + if i%2 == 0 { + k = s + continue + } + key, val := encodeKeyValue(k, s) + md[key] = append(md[key], val) + } + return md +} + +// Len returns the number of items in md. +func (md MD) Len() int { + return len(md) +} + +// Copy returns a copy of md. +func (md MD) Copy() MD { + out := MD{} + for k, v := range md { + for _, i := range v { + out[k] = append(out[k], i) + } + } + return out +} + +type mdKey struct{} + +// NewContext creates a new context with md attached. +func NewContext(ctx context.Context, md MD) context.Context { + return context.WithValue(ctx, mdKey{}, md) +} + +// FromContext returns the MD in ctx if it exists. +func FromContext(ctx context.Context) (md MD, ok bool) { + md, ok = ctx.Value(mdKey{}).(MD) + return +} diff --git a/vendor/google.golang.org/grpc/metadata/metadata_test.go b/vendor/google.golang.org/grpc/metadata/metadata_test.go new file mode 100644 index 00000000..02e6ba51 --- /dev/null +++ b/vendor/google.golang.org/grpc/metadata/metadata_test.go @@ -0,0 +1,107 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package metadata + +import ( + "reflect" + "testing" +) + +const binaryValue = string(128) + +func TestEncodeKeyValue(t *testing.T) { + for _, test := range []struct { + // input + kin string + vin string + // output + kout string + vout string + }{ + {"key", "abc", "key", "abc"}, + {"KEY", "abc", "key", "abc"}, + {"key-bin", "abc", "key-bin", "YWJj"}, + {"key-bin", binaryValue, "key-bin", "woA="}, + } { + k, v := encodeKeyValue(test.kin, test.vin) + if k != test.kout || !reflect.DeepEqual(v, test.vout) { + t.Fatalf("encodeKeyValue(%q, %q) = %q, %q, want %q, %q", test.kin, test.vin, k, v, test.kout, test.vout) + } + } +} + +func TestDecodeKeyValue(t *testing.T) { + for _, test := range []struct { + // input + kin string + vin string + // output + kout string + vout string + err error + }{ + {"a", "abc", "a", "abc", nil}, + {"key-bin", "Zm9vAGJhcg==", "key-bin", "foo\x00bar", nil}, + {"key-bin", "woA=", "key-bin", binaryValue, nil}, + } { + k, v, err := DecodeKeyValue(test.kin, test.vin) + if k != test.kout || !reflect.DeepEqual(v, test.vout) || !reflect.DeepEqual(err, test.err) { + t.Fatalf("DecodeKeyValue(%q, %q) = %q, %q, %v, want %q, %q, %v", test.kin, test.vin, k, v, err, test.kout, test.vout, test.err) + } + } +} + +func TestPairsMD(t *testing.T) { + for _, test := range []struct { + // input + kv []string + // output + md MD + size int + }{ + {[]string{}, MD{}, 0}, + {[]string{"k1", "v1", "k2-bin", binaryValue}, New(map[string]string{ + "k1": "v1", + "k2-bin": binaryValue, + }), 2}, + } { + md := Pairs(test.kv...) + if !reflect.DeepEqual(md, test.md) { + t.Fatalf("Pairs(%v) = %v, want %v", test.kv, md, test.md) + } + if md.Len() != test.size { + t.Fatalf("Pairs(%v) generates md of size %d, want %d", test.kv, md.Len(), test.size) + } + } +} diff --git a/vendor/google.golang.org/grpc/naming/naming.go b/vendor/google.golang.org/grpc/naming/naming.go new file mode 100644 index 00000000..c2e0871e --- /dev/null +++ b/vendor/google.golang.org/grpc/naming/naming.go @@ -0,0 +1,74 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package naming defines the naming API and related data structures for gRPC. +// The interface is EXPERIMENTAL and may be suject to change. +package naming + +// Operation defines the corresponding operations for a name resolution change. +type Operation uint8 + +const ( + // Add indicates a new address is added. + Add Operation = iota + // Delete indicates an exisiting address is deleted. + Delete +) + +// Update defines a name resolution update. Notice that it is not valid having both +// empty string Addr and nil Metadata in an Update. +type Update struct { + // Op indicates the operation of the update. + Op Operation + // Addr is the updated address. It is empty string if there is no address update. + Addr string + // Metadata is the updated metadata. It is nil if there is no metadata update. + // Metadata is not required for a custom naming implementation. + Metadata interface{} +} + +// Resolver creates a Watcher for a target to track its resolution changes. +type Resolver interface { + // Resolve creates a Watcher for target. + Resolve(target string) (Watcher, error) +} + +// Watcher watches for the updates on the specified target. +type Watcher interface { + // Next blocks until an update or error happens. It may return one or more + // updates. The first call should get the full set of the results. It should + // return an error if and only if Watcher cannot recover. + Next() ([]*Update, error) + // Close closes the Watcher. + Close() +} diff --git a/vendor/google.golang.org/grpc/peer/peer.go b/vendor/google.golang.org/grpc/peer/peer.go new file mode 100644 index 00000000..bfa6205b --- /dev/null +++ b/vendor/google.golang.org/grpc/peer/peer.go @@ -0,0 +1,65 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Package peer defines various peer information associated with RPCs and +// corresponding utils. +package peer + +import ( + "net" + + "golang.org/x/net/context" + "google.golang.org/grpc/credentials" +) + +// Peer contains the information of the peer for an RPC. +type Peer struct { + // Addr is the peer address. + Addr net.Addr + // AuthInfo is the authentication information of the transport. + // It is nil if there is no transport security being used. + AuthInfo credentials.AuthInfo +} + +type peerKey struct{} + +// NewContext creates a new context with peer information attached. +func NewContext(ctx context.Context, p *Peer) context.Context { + return context.WithValue(ctx, peerKey{}, p) +} + +// FromContext returns the peer information in ctx if it exists. +func FromContext(ctx context.Context) (p *Peer, ok bool) { + p, ok = ctx.Value(peerKey{}).(*Peer) + return +} diff --git a/vendor/google.golang.org/grpc/reflection/README.md b/vendor/google.golang.org/grpc/reflection/README.md new file mode 100644 index 00000000..04b6371a --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/README.md @@ -0,0 +1,18 @@ +# Reflection + +Package reflection implements server reflection service. + +The service implemented is defined in: https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto. + +To register server reflection on a gRPC server: +```go +import "google.golang.org/grpc/reflection" + +s := grpc.NewServer() +pb.RegisterYourOwnServer(s, &server{}) + +// Register reflection service on gRPC server. +reflection.Register(s) + +s.Serve(lis) +``` diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go new file mode 100644 index 00000000..da90479e --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go @@ -0,0 +1,694 @@ +// Code generated by protoc-gen-go. +// source: reflection.proto +// DO NOT EDIT! + +/* +Package grpc_reflection_v1alpha is a generated protocol buffer package. + +It is generated from these files: + reflection.proto + +It has these top-level messages: + ServerReflectionRequest + ExtensionRequest + ServerReflectionResponse + FileDescriptorResponse + ExtensionNumberResponse + ListServiceResponse + ServiceResponse + ErrorResponse +*/ +package grpc_reflection_v1alpha + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The message sent by the client when calling ServerReflectionInfo method. +type ServerReflectionRequest struct { + Host string `protobuf:"bytes,1,opt,name=host" json:"host,omitempty"` + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + // + // Types that are valid to be assigned to MessageRequest: + // *ServerReflectionRequest_FileByFilename + // *ServerReflectionRequest_FileContainingSymbol + // *ServerReflectionRequest_FileContainingExtension + // *ServerReflectionRequest_AllExtensionNumbersOfType + // *ServerReflectionRequest_ListServices + MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` +} + +func (m *ServerReflectionRequest) Reset() { *m = ServerReflectionRequest{} } +func (m *ServerReflectionRequest) String() string { return proto.CompactTextString(m) } +func (*ServerReflectionRequest) ProtoMessage() {} +func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type isServerReflectionRequest_MessageRequest interface { + isServerReflectionRequest_MessageRequest() +} + +type ServerReflectionRequest_FileByFilename struct { + FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,oneof"` +} +type ServerReflectionRequest_FileContainingSymbol struct { + FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,oneof"` +} +type ServerReflectionRequest_FileContainingExtension struct { + FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,oneof"` +} +type ServerReflectionRequest_AllExtensionNumbersOfType struct { + AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,oneof"` +} +type ServerReflectionRequest_ListServices struct { + ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,oneof"` +} + +func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} +func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} +func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} +func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() {} +func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} + +func (m *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { + if m != nil { + return m.MessageRequest + } + return nil +} + +func (m *ServerReflectionRequest) GetFileByFilename() string { + if x, ok := m.GetMessageRequest().(*ServerReflectionRequest_FileByFilename); ok { + return x.FileByFilename + } + return "" +} + +func (m *ServerReflectionRequest) GetFileContainingSymbol() string { + if x, ok := m.GetMessageRequest().(*ServerReflectionRequest_FileContainingSymbol); ok { + return x.FileContainingSymbol + } + return "" +} + +func (m *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { + if x, ok := m.GetMessageRequest().(*ServerReflectionRequest_FileContainingExtension); ok { + return x.FileContainingExtension + } + return nil +} + +func (m *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { + if x, ok := m.GetMessageRequest().(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { + return x.AllExtensionNumbersOfType + } + return "" +} + +func (m *ServerReflectionRequest) GetListServices() string { + if x, ok := m.GetMessageRequest().(*ServerReflectionRequest_ListServices); ok { + return x.ListServices + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ServerReflectionRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ServerReflectionRequest_OneofMarshaler, _ServerReflectionRequest_OneofUnmarshaler, _ServerReflectionRequest_OneofSizer, []interface{}{ + (*ServerReflectionRequest_FileByFilename)(nil), + (*ServerReflectionRequest_FileContainingSymbol)(nil), + (*ServerReflectionRequest_FileContainingExtension)(nil), + (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), + (*ServerReflectionRequest_ListServices)(nil), + } +} + +func _ServerReflectionRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ServerReflectionRequest) + // message_request + switch x := m.MessageRequest.(type) { + case *ServerReflectionRequest_FileByFilename: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.FileByFilename) + case *ServerReflectionRequest_FileContainingSymbol: + b.EncodeVarint(4<<3 | proto.WireBytes) + b.EncodeStringBytes(x.FileContainingSymbol) + case *ServerReflectionRequest_FileContainingExtension: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.FileContainingExtension); err != nil { + return err + } + case *ServerReflectionRequest_AllExtensionNumbersOfType: + b.EncodeVarint(6<<3 | proto.WireBytes) + b.EncodeStringBytes(x.AllExtensionNumbersOfType) + case *ServerReflectionRequest_ListServices: + b.EncodeVarint(7<<3 | proto.WireBytes) + b.EncodeStringBytes(x.ListServices) + case nil: + default: + return fmt.Errorf("ServerReflectionRequest.MessageRequest has unexpected type %T", x) + } + return nil +} + +func _ServerReflectionRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ServerReflectionRequest) + switch tag { + case 3: // message_request.file_by_filename + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.MessageRequest = &ServerReflectionRequest_FileByFilename{x} + return true, err + case 4: // message_request.file_containing_symbol + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.MessageRequest = &ServerReflectionRequest_FileContainingSymbol{x} + return true, err + case 5: // message_request.file_containing_extension + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ExtensionRequest) + err := b.DecodeMessage(msg) + m.MessageRequest = &ServerReflectionRequest_FileContainingExtension{msg} + return true, err + case 6: // message_request.all_extension_numbers_of_type + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.MessageRequest = &ServerReflectionRequest_AllExtensionNumbersOfType{x} + return true, err + case 7: // message_request.list_services + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.MessageRequest = &ServerReflectionRequest_ListServices{x} + return true, err + default: + return false, nil + } +} + +func _ServerReflectionRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ServerReflectionRequest) + // message_request + switch x := m.MessageRequest.(type) { + case *ServerReflectionRequest_FileByFilename: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.FileByFilename))) + n += len(x.FileByFilename) + case *ServerReflectionRequest_FileContainingSymbol: + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.FileContainingSymbol))) + n += len(x.FileContainingSymbol) + case *ServerReflectionRequest_FileContainingExtension: + s := proto.Size(x.FileContainingExtension) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ServerReflectionRequest_AllExtensionNumbersOfType: + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AllExtensionNumbersOfType))) + n += len(x.AllExtensionNumbersOfType) + case *ServerReflectionRequest_ListServices: + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.ListServices))) + n += len(x.ListServices) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +type ExtensionRequest struct { + // Fully-qualified type name. The format should be . + ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType" json:"containing_type,omitempty"` + ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber" json:"extension_number,omitempty"` +} + +func (m *ExtensionRequest) Reset() { *m = ExtensionRequest{} } +func (m *ExtensionRequest) String() string { return proto.CompactTextString(m) } +func (*ExtensionRequest) ProtoMessage() {} +func (*ExtensionRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +// The message sent by the server to answer ServerReflectionInfo method. +type ServerReflectionResponse struct { + ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost" json:"valid_host,omitempty"` + OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest" json:"original_request,omitempty"` + // The server set one of the following fields accroding to the message_request + // in the request. + // + // Types that are valid to be assigned to MessageResponse: + // *ServerReflectionResponse_FileDescriptorResponse + // *ServerReflectionResponse_AllExtensionNumbersResponse + // *ServerReflectionResponse_ListServicesResponse + // *ServerReflectionResponse_ErrorResponse + MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` +} + +func (m *ServerReflectionResponse) Reset() { *m = ServerReflectionResponse{} } +func (m *ServerReflectionResponse) String() string { return proto.CompactTextString(m) } +func (*ServerReflectionResponse) ProtoMessage() {} +func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type isServerReflectionResponse_MessageResponse interface { + isServerReflectionResponse_MessageResponse() +} + +type ServerReflectionResponse_FileDescriptorResponse struct { + FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,oneof"` +} +type ServerReflectionResponse_AllExtensionNumbersResponse struct { + AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,oneof"` +} +type ServerReflectionResponse_ListServicesResponse struct { + ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,oneof"` +} +type ServerReflectionResponse_ErrorResponse struct { + ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,oneof"` +} + +func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() {} +func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { +} +func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} +func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} + +func (m *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { + if m != nil { + return m.MessageResponse + } + return nil +} + +func (m *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { + if m != nil { + return m.OriginalRequest + } + return nil +} + +func (m *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { + if x, ok := m.GetMessageResponse().(*ServerReflectionResponse_FileDescriptorResponse); ok { + return x.FileDescriptorResponse + } + return nil +} + +func (m *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { + if x, ok := m.GetMessageResponse().(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { + return x.AllExtensionNumbersResponse + } + return nil +} + +func (m *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { + if x, ok := m.GetMessageResponse().(*ServerReflectionResponse_ListServicesResponse); ok { + return x.ListServicesResponse + } + return nil +} + +func (m *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { + if x, ok := m.GetMessageResponse().(*ServerReflectionResponse_ErrorResponse); ok { + return x.ErrorResponse + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ServerReflectionResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ServerReflectionResponse_OneofMarshaler, _ServerReflectionResponse_OneofUnmarshaler, _ServerReflectionResponse_OneofSizer, []interface{}{ + (*ServerReflectionResponse_FileDescriptorResponse)(nil), + (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), + (*ServerReflectionResponse_ListServicesResponse)(nil), + (*ServerReflectionResponse_ErrorResponse)(nil), + } +} + +func _ServerReflectionResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ServerReflectionResponse) + // message_response + switch x := m.MessageResponse.(type) { + case *ServerReflectionResponse_FileDescriptorResponse: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.FileDescriptorResponse); err != nil { + return err + } + case *ServerReflectionResponse_AllExtensionNumbersResponse: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.AllExtensionNumbersResponse); err != nil { + return err + } + case *ServerReflectionResponse_ListServicesResponse: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ListServicesResponse); err != nil { + return err + } + case *ServerReflectionResponse_ErrorResponse: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ErrorResponse); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ServerReflectionResponse.MessageResponse has unexpected type %T", x) + } + return nil +} + +func _ServerReflectionResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ServerReflectionResponse) + switch tag { + case 4: // message_response.file_descriptor_response + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(FileDescriptorResponse) + err := b.DecodeMessage(msg) + m.MessageResponse = &ServerReflectionResponse_FileDescriptorResponse{msg} + return true, err + case 5: // message_response.all_extension_numbers_response + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ExtensionNumberResponse) + err := b.DecodeMessage(msg) + m.MessageResponse = &ServerReflectionResponse_AllExtensionNumbersResponse{msg} + return true, err + case 6: // message_response.list_services_response + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ListServiceResponse) + err := b.DecodeMessage(msg) + m.MessageResponse = &ServerReflectionResponse_ListServicesResponse{msg} + return true, err + case 7: // message_response.error_response + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ErrorResponse) + err := b.DecodeMessage(msg) + m.MessageResponse = &ServerReflectionResponse_ErrorResponse{msg} + return true, err + default: + return false, nil + } +} + +func _ServerReflectionResponse_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ServerReflectionResponse) + // message_response + switch x := m.MessageResponse.(type) { + case *ServerReflectionResponse_FileDescriptorResponse: + s := proto.Size(x.FileDescriptorResponse) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ServerReflectionResponse_AllExtensionNumbersResponse: + s := proto.Size(x.AllExtensionNumbersResponse) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ServerReflectionResponse_ListServicesResponse: + s := proto.Size(x.ListServicesResponse) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *ServerReflectionResponse_ErrorResponse: + s := proto.Size(x.ErrorResponse) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +type FileDescriptorResponse struct { + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` +} + +func (m *FileDescriptorResponse) Reset() { *m = FileDescriptorResponse{} } +func (m *FileDescriptorResponse) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorResponse) ProtoMessage() {} +func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +type ExtensionNumberResponse struct { + // Full name of the base type, including the package name. The format + // is . + BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName" json:"base_type_name,omitempty"` + ExtensionNumber []int32 `protobuf:"varint,2,rep,name=extension_number,json=extensionNumber" json:"extension_number,omitempty"` +} + +func (m *ExtensionNumberResponse) Reset() { *m = ExtensionNumberResponse{} } +func (m *ExtensionNumberResponse) String() string { return proto.CompactTextString(m) } +func (*ExtensionNumberResponse) ProtoMessage() {} +func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +// A list of ServiceResponse sent by the server answering list_services request. +type ListServiceResponse struct { + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service" json:"service,omitempty"` +} + +func (m *ListServiceResponse) Reset() { *m = ListServiceResponse{} } +func (m *ListServiceResponse) String() string { return proto.CompactTextString(m) } +func (*ListServiceResponse) ProtoMessage() {} +func (*ListServiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *ListServiceResponse) GetService() []*ServiceResponse { + if m != nil { + return m.Service + } + return nil +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +type ServiceResponse struct { + // Full name of a registered service, including its package name. The format + // is . + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *ServiceResponse) Reset() { *m = ServiceResponse{} } +func (m *ServiceResponse) String() string { return proto.CompactTextString(m) } +func (*ServiceResponse) ProtoMessage() {} +func (*ServiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +// The error code and error message sent by the server when an error occurs. +type ErrorResponse struct { + // This field uses the error codes defined in grpc::StatusCode. + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode" json:"error_code,omitempty"` + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"` +} + +func (m *ErrorResponse) Reset() { *m = ErrorResponse{} } +func (m *ErrorResponse) String() string { return proto.CompactTextString(m) } +func (*ErrorResponse) ProtoMessage() {} +func (*ErrorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func init() { + proto.RegisterType((*ServerReflectionRequest)(nil), "grpc.reflection.v1alpha.ServerReflectionRequest") + proto.RegisterType((*ExtensionRequest)(nil), "grpc.reflection.v1alpha.ExtensionRequest") + proto.RegisterType((*ServerReflectionResponse)(nil), "grpc.reflection.v1alpha.ServerReflectionResponse") + proto.RegisterType((*FileDescriptorResponse)(nil), "grpc.reflection.v1alpha.FileDescriptorResponse") + proto.RegisterType((*ExtensionNumberResponse)(nil), "grpc.reflection.v1alpha.ExtensionNumberResponse") + proto.RegisterType((*ListServiceResponse)(nil), "grpc.reflection.v1alpha.ListServiceResponse") + proto.RegisterType((*ServiceResponse)(nil), "grpc.reflection.v1alpha.ServiceResponse") + proto.RegisterType((*ErrorResponse)(nil), "grpc.reflection.v1alpha.ErrorResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for ServerReflection service + +type ServerReflectionClient interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) +} + +type serverReflectionClient struct { + cc *grpc.ClientConn +} + +func NewServerReflectionClient(cc *grpc.ClientConn) ServerReflectionClient { + return &serverReflectionClient{cc} +} + +func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) { + stream, err := grpc.NewClientStream(ctx, &_ServerReflection_serviceDesc.Streams[0], c.cc, "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo", opts...) + if err != nil { + return nil, err + } + x := &serverReflectionServerReflectionInfoClient{stream} + return x, nil +} + +type ServerReflection_ServerReflectionInfoClient interface { + Send(*ServerReflectionRequest) error + Recv() (*ServerReflectionResponse, error) + grpc.ClientStream +} + +type serverReflectionServerReflectionInfoClient struct { + grpc.ClientStream +} + +func (x *serverReflectionServerReflectionInfoClient) Send(m *ServerReflectionRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoClient) Recv() (*ServerReflectionResponse, error) { + m := new(ServerReflectionResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for ServerReflection service + +type ServerReflectionServer interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error +} + +func RegisterServerReflectionServer(s *grpc.Server, srv ServerReflectionServer) { + s.RegisterService(&_ServerReflection_serviceDesc, srv) +} + +func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ServerReflectionServer).ServerReflectionInfo(&serverReflectionServerReflectionInfoServer{stream}) +} + +type ServerReflection_ServerReflectionInfoServer interface { + Send(*ServerReflectionResponse) error + Recv() (*ServerReflectionRequest, error) + grpc.ServerStream +} + +type serverReflectionServerReflectionInfoServer struct { + grpc.ServerStream +} + +func (x *serverReflectionServerReflectionInfoServer) Send(m *ServerReflectionResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoServer) Recv() (*ServerReflectionRequest, error) { + m := new(ServerReflectionRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _ServerReflection_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.reflection.v1alpha.ServerReflection", + HandlerType: (*ServerReflectionServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerReflectionInfo", + Handler: _ServerReflection_ServerReflectionInfo_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("reflection.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 646 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xd3, 0x4c, + 0x10, 0xfd, 0xd2, 0xe6, 0x47, 0x99, 0xfc, 0xf9, 0xdb, 0x86, 0xc4, 0x05, 0x15, 0x21, 0x43, 0x21, + 0x45, 0x28, 0xb4, 0x46, 0xe2, 0x01, 0x52, 0x40, 0x45, 0x2a, 0x2d, 0x72, 0xb8, 0x41, 0x5c, 0x58, + 0x8e, 0xb3, 0x4e, 0x0d, 0x8e, 0xd7, 0xec, 0xba, 0x81, 0x5c, 0xf1, 0x10, 0x3c, 0x14, 0xaf, 0xc4, + 0x25, 0xbb, 0xeb, 0x9f, 0x38, 0xae, 0x0d, 0xea, 0x95, 0xad, 0xb3, 0x33, 0x7b, 0x66, 0xe6, 0x9c, + 0x59, 0x50, 0x28, 0x76, 0x3c, 0x6c, 0x87, 0x2e, 0xf1, 0xc7, 0x01, 0x25, 0x21, 0x41, 0xc3, 0x05, + 0x0d, 0xec, 0x71, 0x06, 0x5e, 0x9d, 0x58, 0x5e, 0x70, 0x65, 0x69, 0xbf, 0x77, 0x60, 0x38, 0xc5, + 0x74, 0x85, 0xa9, 0x91, 0x1e, 0x1a, 0xf8, 0xeb, 0x35, 0x66, 0x21, 0x42, 0x50, 0xbd, 0x22, 0x2c, + 0x54, 0x2b, 0x0f, 0x2a, 0xa3, 0xa6, 0x21, 0xff, 0xd1, 0x53, 0x50, 0x1c, 0xd7, 0xc3, 0xe6, 0x6c, + 0x6d, 0x8a, 0xaf, 0x6f, 0x2d, 0xb1, 0xba, 0x2b, 0xce, 0xcf, 0xfe, 0x33, 0xba, 0x02, 0x99, 0xac, + 0xdf, 0xc4, 0x38, 0x7a, 0x09, 0x03, 0x19, 0x6b, 0x13, 0x3f, 0xb4, 0x5c, 0xdf, 0xf5, 0x17, 0x26, + 0x5b, 0x2f, 0x67, 0xc4, 0x53, 0xab, 0x71, 0x46, 0x5f, 0x9c, 0x9f, 0xa6, 0xc7, 0x53, 0x79, 0x8a, + 0x16, 0xb0, 0x9f, 0xcf, 0xc3, 0xdf, 0x43, 0xec, 0x33, 0x5e, 0x9b, 0x5a, 0xe3, 0xa9, 0x2d, 0xfd, + 0x68, 0x5c, 0xd2, 0xd0, 0xf8, 0x75, 0x12, 0x19, 0x77, 0xc1, 0x59, 0x86, 0xdb, 0x2c, 0x69, 0x04, + 0x9a, 0xc0, 0x81, 0xe5, 0x79, 0x9b, 0xcb, 0x4d, 0xff, 0x7a, 0x39, 0xc3, 0x94, 0x99, 0xc4, 0x31, + 0xc3, 0x75, 0x80, 0xd5, 0x7a, 0x5c, 0xe7, 0x3e, 0x0f, 0x4b, 0xd3, 0x2e, 0xa2, 0xa0, 0x4b, 0xe7, + 0x03, 0x0f, 0x41, 0x87, 0xd0, 0xf1, 0x5c, 0x16, 0x9a, 0x8c, 0x0f, 0xd1, 0xb5, 0x31, 0x53, 0x1b, + 0x71, 0x4e, 0x5b, 0xc0, 0xd3, 0x18, 0x9d, 0xfc, 0x0f, 0xbd, 0x25, 0x66, 0xcc, 0x5a, 0x60, 0x93, + 0x46, 0x85, 0x69, 0x0e, 0x28, 0xf9, 0x62, 0xd1, 0x13, 0xe8, 0x65, 0xba, 0x96, 0x35, 0x44, 0xd3, + 0xef, 0x6e, 0x60, 0x49, 0x7b, 0x04, 0x4a, 0xbe, 0x6c, 0x75, 0x87, 0x47, 0xd6, 0x8c, 0x1e, 0xde, + 0x2e, 0x54, 0xfb, 0x55, 0x05, 0xf5, 0xa6, 0xc4, 0x2c, 0x20, 0x3e, 0xc3, 0xe8, 0x00, 0x60, 0x65, + 0x79, 0xee, 0xdc, 0xcc, 0x28, 0xdd, 0x94, 0xc8, 0x99, 0x90, 0xfb, 0x13, 0x28, 0x84, 0xba, 0x0b, + 0xd7, 0xb7, 0xbc, 0xa4, 0x6e, 0x49, 0xd3, 0xd2, 0x8f, 0x4b, 0x15, 0x28, 0xb1, 0x93, 0xd1, 0x4b, + 0x6e, 0x4a, 0x9a, 0xfd, 0x02, 0xaa, 0xd4, 0x79, 0x8e, 0x99, 0x4d, 0xdd, 0x20, 0x24, 0x94, 0x73, + 0x44, 0x75, 0x49, 0x87, 0xb4, 0xf4, 0xe7, 0xa5, 0x24, 0xc2, 0x64, 0xaf, 0xd2, 0xbc, 0xa4, 0x1d, + 0x3e, 0x76, 0x69, 0xb9, 0x9b, 0x27, 0xe8, 0x1b, 0xdc, 0x2f, 0xd6, 0x3a, 0xa5, 0xac, 0xfd, 0xa3, + 0xaf, 0x9c, 0x01, 0x32, 0x9c, 0xf7, 0x0a, 0xec, 0x91, 0x12, 0xcf, 0x61, 0xb0, 0x65, 0x90, 0x0d, + 0x61, 0x5d, 0x12, 0x3e, 0x2b, 0x25, 0x3c, 0xdf, 0x18, 0x28, 0x43, 0xd6, 0xcf, 0xfa, 0x2a, 0x65, + 0xb9, 0x84, 0x2e, 0xa6, 0x34, 0x3b, 0xc1, 0x86, 0xbc, 0xfd, 0x71, 0x79, 0x3b, 0x22, 0x3c, 0x73, + 0x6f, 0x07, 0x67, 0x81, 0x09, 0x02, 0x65, 0x63, 0xd8, 0x08, 0xd3, 0xce, 0x61, 0x50, 0x3c, 0x77, + 0xa4, 0xc3, 0x9d, 0xbc, 0x94, 0xf2, 0xe1, 0xe1, 0x8e, 0xda, 0x1d, 0xb5, 0x8d, 0xbd, 0x6d, 0x51, + 0xde, 0x8b, 0x23, 0xed, 0x33, 0x0c, 0x4b, 0x46, 0x8a, 0x1e, 0x41, 0x77, 0x66, 0x31, 0x2c, 0x17, + 0xc0, 0x94, 0x6f, 0x4c, 0xe4, 0xcc, 0xb6, 0x40, 0x85, 0xff, 0x2f, 0xc4, 0xfb, 0x52, 0xbc, 0x03, + 0xbb, 0x45, 0x3b, 0xf0, 0x11, 0xf6, 0x0a, 0xa6, 0xc9, 0x1f, 0x80, 0x46, 0x2c, 0x8b, 0x2c, 0xb4, + 0xa5, 0x8f, 0xfe, 0xea, 0xea, 0x4c, 0xaa, 0x91, 0x24, 0x6a, 0x87, 0xd0, 0xcb, 0x5f, 0xcb, 0x1f, + 0xce, 0x4c, 0xd1, 0xf2, 0x5f, 0x9b, 0x42, 0x67, 0x6b, 0xe2, 0x62, 0xf3, 0x22, 0xc5, 0x6c, 0x32, + 0x8f, 0x42, 0x6b, 0x46, 0x53, 0x22, 0xa7, 0x1c, 0x40, 0x0f, 0x21, 0x12, 0xc4, 0x8c, 0x55, 0x90, + 0x6b, 0xc7, 0x27, 0x20, 0xc1, 0x77, 0x11, 0xa6, 0xff, 0xac, 0x80, 0x92, 0x5f, 0x37, 0xf4, 0x03, + 0xfa, 0x79, 0xec, 0xad, 0xef, 0x10, 0x74, 0xeb, 0x8d, 0xbd, 0x7b, 0x72, 0x8b, 0x8c, 0xa8, 0xab, + 0x51, 0xe5, 0xb8, 0x32, 0xab, 0x4b, 0xe9, 0x5f, 0xfc, 0x09, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x3f, + 0x7b, 0x08, 0x87, 0x06, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.proto b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.proto new file mode 100644 index 00000000..276ff0e2 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.proto @@ -0,0 +1,151 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Service exported by server reflection + +syntax = "proto3"; + +package grpc.reflection.v1alpha; + +service ServerReflection { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + rpc ServerReflectionInfo(stream ServerReflectionRequest) + returns (stream ServerReflectionResponse); +} + +// The message sent by the client when calling ServerReflectionInfo method. +message ServerReflectionRequest { + string host = 1; + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + oneof message_request { + // Find a proto file by the file name. + string file_by_filename = 3; + + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + string file_containing_symbol = 4; + + // Find the proto file which defines an extension extending the given + // message type with the given field number. + ExtensionRequest file_containing_extension = 5; + + // Finds the tag numbers used by all known extensions of extendee_type, and + // appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + string all_extension_numbers_of_type = 6; + + // List the full names of registered services. The content will not be + // checked. + string list_services = 7; + } +} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +message ExtensionRequest { + // Fully-qualified type name. The format should be . + string containing_type = 1; + int32 extension_number = 2; +} + +// The message sent by the server to answer ServerReflectionInfo method. +message ServerReflectionResponse { + string valid_host = 1; + ServerReflectionRequest original_request = 2; + // The server set one of the following fields accroding to the message_request + // in the request. + oneof message_response { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. As + // the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + FileDescriptorResponse file_descriptor_response = 4; + + // This message is used to answer all_extension_numbers_of_type requst. + ExtensionNumberResponse all_extension_numbers_response = 5; + + // This message is used to answer list_services request. + ListServiceResponse list_services_response = 6; + + // This message is used when an error occurs. + ErrorResponse error_response = 7; + } +} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +message FileDescriptorResponse { + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + repeated bytes file_descriptor_proto = 1; +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +message ExtensionNumberResponse { + // Full name of the base type, including the package name. The format + // is . + string base_type_name = 1; + repeated int32 extension_number = 2; +} + +// A list of ServiceResponse sent by the server answering list_services request. +message ListServiceResponse { + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + repeated ServiceResponse service = 1; +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +message ServiceResponse { + // Full name of a registered service, including its package name. The format + // is . + string name = 1; +} + +// The error code and error message sent by the server when an error occurs. +message ErrorResponse { + // This field uses the error codes defined in grpc::StatusCode. + int32 error_code = 1; + string error_message = 2; +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.pb.go new file mode 100644 index 00000000..ac49de4a --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.pb.go @@ -0,0 +1,56 @@ +// Code generated by protoc-gen-go. +// source: proto2.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ToBeExtened struct { + Foo *int32 `protobuf:"varint,1,req,name=foo" json:"foo,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ToBeExtened) Reset() { *m = ToBeExtened{} } +func (m *ToBeExtened) String() string { return proto.CompactTextString(m) } +func (*ToBeExtened) ProtoMessage() {} +func (*ToBeExtened) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +var extRange_ToBeExtened = []proto.ExtensionRange{ + {10, 20}, +} + +func (*ToBeExtened) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ToBeExtened +} + +func (m *ToBeExtened) GetFoo() int32 { + if m != nil && m.Foo != nil { + return *m.Foo + } + return 0 +} + +func init() { + proto.RegisterType((*ToBeExtened)(nil), "grpc.testing.ToBeExtened") +} + +func init() { proto.RegisterFile("proto2.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 85 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x28, 0xca, 0x2f, + 0xc9, 0x37, 0xd2, 0x03, 0x53, 0x42, 0x3c, 0xe9, 0x45, 0x05, 0xc9, 0x7a, 0x25, 0xa9, 0xc5, 0x25, + 0x99, 0x79, 0xe9, 0x4a, 0xaa, 0x5c, 0xdc, 0x21, 0xf9, 0x4e, 0xa9, 0xae, 0x15, 0x25, 0xa9, 0x79, + 0xa9, 0x29, 0x42, 0x02, 0x5c, 0xcc, 0x69, 0xf9, 0xf9, 0x12, 0x8c, 0x0a, 0x4c, 0x1a, 0xac, 0x41, + 0x20, 0xa6, 0x16, 0x0b, 0x07, 0x97, 0x80, 0x28, 0x20, 0x00, 0x00, 0xff, 0xff, 0xc9, 0xed, 0xbc, + 0xc2, 0x43, 0x00, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.proto b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.proto new file mode 100644 index 00000000..f79adc49 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; + +package grpc.testing; + +message ToBeExtened { + required int32 foo = 1; + extensions 10 to 20; +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.pb.go new file mode 100644 index 00000000..0120ca97 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.pb.go @@ -0,0 +1,88 @@ +// Code generated by protoc-gen-go. +// source: proto2_ext.proto +// DO NOT EDIT! + +/* +Package grpc_testing is a generated protocol buffer package. + +It is generated from these files: + proto2_ext.proto + proto2.proto + test.proto + +It has these top-level messages: + Extension + ToBeExtened + SearchResponse + SearchRequest +*/ +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Extension struct { + Baz *int32 `protobuf:"varint,1,opt,name=baz" json:"baz,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Extension) Reset() { *m = Extension{} } +func (m *Extension) String() string { return proto.CompactTextString(m) } +func (*Extension) ProtoMessage() {} +func (*Extension) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Extension) GetBaz() int32 { + if m != nil && m.Baz != nil { + return *m.Baz + } + return 0 +} + +var E_Bar = &proto.ExtensionDesc{ + ExtendedType: (*ToBeExtened)(nil), + ExtensionType: (*int32)(nil), + Field: 13, + Name: "grpc.testing.bar", + Tag: "varint,13,opt,name=bar", +} + +var E_Baz = &proto.ExtensionDesc{ + ExtendedType: (*ToBeExtened)(nil), + ExtensionType: (*Extension)(nil), + Field: 17, + Name: "grpc.testing.baz", + Tag: "bytes,17,opt,name=baz", +} + +func init() { + proto.RegisterType((*Extension)(nil), "grpc.testing.Extension") + proto.RegisterExtension(E_Bar) + proto.RegisterExtension(E_Baz) +} + +func init() { proto.RegisterFile("proto2_ext.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 130 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0x28, 0x28, 0xca, 0x2f, + 0xc9, 0x37, 0x8a, 0x4f, 0xad, 0x28, 0xd1, 0x03, 0x33, 0x85, 0x78, 0xd2, 0x8b, 0x0a, 0x92, 0xf5, + 0x4a, 0x52, 0x8b, 0x4b, 0x32, 0xf3, 0xd2, 0xa5, 0x78, 0x20, 0xf2, 0x10, 0x39, 0x25, 0x59, 0x2e, + 0x4e, 0xd7, 0x8a, 0x92, 0xd4, 0xbc, 0xe2, 0xcc, 0xfc, 0x3c, 0x21, 0x01, 0x2e, 0xe6, 0xa4, 0xc4, + 0x2a, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xd6, 0x20, 0x10, 0xd3, 0x4a, 0x1b, 0x24, 0x52, 0x24, 0x24, + 0xa9, 0x87, 0x6c, 0x84, 0x5e, 0x48, 0xbe, 0x53, 0x2a, 0x58, 0x57, 0x6a, 0x8a, 0x04, 0x2f, 0x4c, + 0x71, 0x91, 0x95, 0x0b, 0x58, 0x3b, 0x3e, 0xc5, 0x82, 0x40, 0xc5, 0xdc, 0x46, 0xe2, 0xa8, 0x0a, + 0xe0, 0xf6, 0x83, 0xad, 0x04, 0x04, 0x00, 0x00, 0xff, 0xff, 0x59, 0xfa, 0x16, 0xbc, 0xc0, 0x00, + 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.proto b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.proto new file mode 100644 index 00000000..c2dd737a --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/proto2_ext.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; + +package grpc.testing; + +import "proto2.proto"; +extend ToBeExtened { + optional int32 bar = 13; + optional Extension baz = 17; +} + +message Extension { + optional int32 baz = 1; +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/test.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_testing/test.pb.go new file mode 100644 index 00000000..add7abd0 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/test.pb.go @@ -0,0 +1,220 @@ +// Code generated by protoc-gen-go. +// source: test.proto +// DO NOT EDIT! + +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type SearchResponse struct { + Results []*SearchResponse_Result `protobuf:"bytes,1,rep,name=results" json:"results,omitempty"` +} + +func (m *SearchResponse) Reset() { *m = SearchResponse{} } +func (m *SearchResponse) String() string { return proto.CompactTextString(m) } +func (*SearchResponse) ProtoMessage() {} +func (*SearchResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +func (m *SearchResponse) GetResults() []*SearchResponse_Result { + if m != nil { + return m.Results + } + return nil +} + +type SearchResponse_Result struct { + Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title" json:"title,omitempty"` + Snippets []string `protobuf:"bytes,3,rep,name=snippets" json:"snippets,omitempty"` +} + +func (m *SearchResponse_Result) Reset() { *m = SearchResponse_Result{} } +func (m *SearchResponse_Result) String() string { return proto.CompactTextString(m) } +func (*SearchResponse_Result) ProtoMessage() {} +func (*SearchResponse_Result) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0, 0} } + +type SearchRequest struct { + Query string `protobuf:"bytes,1,opt,name=query" json:"query,omitempty"` +} + +func (m *SearchRequest) Reset() { *m = SearchRequest{} } +func (m *SearchRequest) String() string { return proto.CompactTextString(m) } +func (*SearchRequest) ProtoMessage() {} +func (*SearchRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +func init() { + proto.RegisterType((*SearchResponse)(nil), "grpc.testing.SearchResponse") + proto.RegisterType((*SearchResponse_Result)(nil), "grpc.testing.SearchResponse.Result") + proto.RegisterType((*SearchRequest)(nil), "grpc.testing.SearchRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for SearchService service + +type SearchServiceClient interface { + Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) + StreamingSearch(ctx context.Context, opts ...grpc.CallOption) (SearchService_StreamingSearchClient, error) +} + +type searchServiceClient struct { + cc *grpc.ClientConn +} + +func NewSearchServiceClient(cc *grpc.ClientConn) SearchServiceClient { + return &searchServiceClient{cc} +} + +func (c *searchServiceClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) { + out := new(SearchResponse) + err := grpc.Invoke(ctx, "/grpc.testing.SearchService/Search", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *searchServiceClient) StreamingSearch(ctx context.Context, opts ...grpc.CallOption) (SearchService_StreamingSearchClient, error) { + stream, err := grpc.NewClientStream(ctx, &_SearchService_serviceDesc.Streams[0], c.cc, "/grpc.testing.SearchService/StreamingSearch", opts...) + if err != nil { + return nil, err + } + x := &searchServiceStreamingSearchClient{stream} + return x, nil +} + +type SearchService_StreamingSearchClient interface { + Send(*SearchRequest) error + Recv() (*SearchResponse, error) + grpc.ClientStream +} + +type searchServiceStreamingSearchClient struct { + grpc.ClientStream +} + +func (x *searchServiceStreamingSearchClient) Send(m *SearchRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *searchServiceStreamingSearchClient) Recv() (*SearchResponse, error) { + m := new(SearchResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for SearchService service + +type SearchServiceServer interface { + Search(context.Context, *SearchRequest) (*SearchResponse, error) + StreamingSearch(SearchService_StreamingSearchServer) error +} + +func RegisterSearchServiceServer(s *grpc.Server, srv SearchServiceServer) { + s.RegisterService(&_SearchService_serviceDesc, srv) +} + +func _SearchService_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SearchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SearchServiceServer).Search(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.SearchService/Search", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SearchServiceServer).Search(ctx, req.(*SearchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SearchService_StreamingSearch_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SearchServiceServer).StreamingSearch(&searchServiceStreamingSearchServer{stream}) +} + +type SearchService_StreamingSearchServer interface { + Send(*SearchResponse) error + Recv() (*SearchRequest, error) + grpc.ServerStream +} + +type searchServiceStreamingSearchServer struct { + grpc.ServerStream +} + +func (x *searchServiceStreamingSearchServer) Send(m *SearchResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *searchServiceStreamingSearchServer) Recv() (*SearchRequest, error) { + m := new(SearchRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _SearchService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.SearchService", + HandlerType: (*SearchServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Search", + Handler: _SearchService_Search_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamingSearch", + Handler: _SearchService_StreamingSearch_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor2, +} + +func init() { proto.RegisterFile("test.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e, + 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x49, 0x2f, 0x2a, 0x48, 0xd6, 0x03, 0x09, 0x64, + 0xe6, 0xa5, 0x2b, 0xcd, 0x65, 0xe4, 0xe2, 0x0b, 0x4e, 0x4d, 0x2c, 0x4a, 0xce, 0x08, 0x4a, 0x2d, + 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x15, 0xb2, 0xe5, 0x62, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, + 0x96, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x52, 0xd6, 0x43, 0xd6, 0xa2, 0x87, 0xaa, 0x5c, 0x2f, + 0x08, 0xac, 0x36, 0x08, 0xa6, 0x47, 0xca, 0x87, 0x8b, 0x0d, 0x22, 0x24, 0x24, 0xc0, 0xc5, 0x5c, + 0x5a, 0x94, 0x03, 0x34, 0x84, 0x51, 0x83, 0x33, 0x08, 0xc4, 0x14, 0x12, 0xe1, 0x62, 0x2d, 0xc9, + 0x2c, 0xc9, 0x49, 0x95, 0x60, 0x02, 0x8b, 0x41, 0x38, 0x42, 0x52, 0x5c, 0x1c, 0xc5, 0x79, 0x99, + 0x05, 0x05, 0xa9, 0x40, 0x1b, 0x99, 0x81, 0x36, 0x72, 0x06, 0xc1, 0xf9, 0x4a, 0xaa, 0x5c, 0xbc, + 0x30, 0xfb, 0x0a, 0x4b, 0x81, 0x0e, 0x00, 0x19, 0x01, 0x64, 0x14, 0x55, 0x42, 0x8d, 0x85, 0x70, + 0x8c, 0x96, 0x31, 0xc2, 0xd4, 0x05, 0xa7, 0x16, 0x95, 0x65, 0x26, 0xa7, 0x0a, 0x39, 0x73, 0xb1, + 0x41, 0x04, 0x84, 0xa4, 0xb1, 0x3b, 0x1f, 0x6c, 0x9c, 0x94, 0x0c, 0x3e, 0xbf, 0x09, 0x05, 0x70, + 0xf1, 0x07, 0x97, 0x14, 0xa5, 0x26, 0xe6, 0x02, 0xe5, 0x28, 0x36, 0x4d, 0x83, 0xd1, 0x80, 0x31, + 0x89, 0x0d, 0x1c, 0x09, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x20, 0xd6, 0x09, 0xb8, 0x92, + 0x01, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_testing/test.proto b/vendor/google.golang.org/grpc/reflection/grpc_testing/test.proto new file mode 100644 index 00000000..d74d0fc1 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_testing/test.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package grpc.testing; + +message SearchResponse { + message Result { + string url = 1; + string title = 2; + repeated string snippets = 3; + } + repeated Result results = 1; +} + +message SearchRequest { + string query = 1; +} + +service SearchService { + rpc Search(SearchRequest) returns (SearchResponse); + rpc StreamingSearch(stream SearchRequest) returns (stream SearchResponse); +} diff --git a/vendor/google.golang.org/grpc/reflection/serverreflection.go b/vendor/google.golang.org/grpc/reflection/serverreflection.go new file mode 100644 index 00000000..0daa096f --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/serverreflection.go @@ -0,0 +1,395 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* +Package reflection implements server reflection service. + +The service implemented is defined in: +https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto. + +To register server reflection on a gRPC server: + import "google.golang.org/grpc/reflection" + + s := grpc.NewServer() + pb.RegisterYourOwnServer(s, &server{}) + + // Register reflection service on gRPC server. + reflection.Register(s) + + s.Serve(lis) + +*/ +package reflection // import "google.golang.org/grpc/reflection" + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "reflect" + "strings" + + "github.com/golang/protobuf/proto" + dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +type serverReflectionServer struct { + s *grpc.Server + // TODO add more cache if necessary + serviceInfo map[string]*grpc.ServiceInfo // cache for s.GetServiceInfo() +} + +// Register registers the server reflection service on the given gRPC server. +func Register(s *grpc.Server) { + rpb.RegisterServerReflectionServer(s, &serverReflectionServer{ + s: s, + }) +} + +// protoMessage is used for type assertion on proto messages. +// Generated proto message implements function Descriptor(), but Descriptor() +// is not part of interface proto.Message. This interface is needed to +// call Descriptor(). +type protoMessage interface { + Descriptor() ([]byte, []int) +} + +// fileDescForType gets the file descriptor for the given type. +// The given type should be a proto message. +func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { + m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage) + if !ok { + return nil, fmt.Errorf("failed to create message from type: %v", st) + } + enc, _ := m.Descriptor() + + return s.decodeFileDesc(enc) +} + +// decodeFileDesc does decompression and unmarshalling on the given +// file descriptor byte slice. +func (s *serverReflectionServer) decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) { + raw, err := decompress(enc) + if err != nil { + return nil, fmt.Errorf("failed to decompress enc: %v", err) + } + + fd := new(dpb.FileDescriptorProto) + if err := proto.Unmarshal(raw, fd); err != nil { + return nil, fmt.Errorf("bad descriptor: %v", err) + } + return fd, nil +} + +// decompress does gzip decompression. +func decompress(b []byte) ([]byte, error) { + r, err := gzip.NewReader(bytes.NewReader(b)) + if err != nil { + return nil, fmt.Errorf("bad gzipped descriptor: %v\n", err) + } + out, err := ioutil.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("bad gzipped descriptor: %v\n", err) + } + return out, nil +} + +func (s *serverReflectionServer) typeForName(name string) (reflect.Type, error) { + pt := proto.MessageType(name) + if pt == nil { + return nil, fmt.Errorf("unknown type: %q", name) + } + st := pt.Elem() + + return st, nil +} + +func (s *serverReflectionServer) fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { + m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + if !ok { + return nil, fmt.Errorf("failed to create message from type: %v", st) + } + + var extDesc *proto.ExtensionDesc + for id, desc := range proto.RegisteredExtensions(m) { + if id == ext { + extDesc = desc + break + } + } + + if extDesc == nil { + return nil, fmt.Errorf("failed to find registered extension for extension number %v", ext) + } + + extT := reflect.TypeOf(extDesc.ExtensionType).Elem() + + return s.fileDescForType(extT) +} + +func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { + m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + if !ok { + return nil, fmt.Errorf("failed to create message from type: %v", st) + } + + exts := proto.RegisteredExtensions(m) + out := make([]int32, 0, len(exts)) + for id := range exts { + out = append(out, id) + } + return out, nil +} + +// fileDescEncodingByFilename finds the file descriptor for given filename, +// does marshalling on it and returns the marshalled result. +func (s *serverReflectionServer) fileDescEncodingByFilename(name string) ([]byte, error) { + enc := proto.FileDescriptor(name) + if enc == nil { + return nil, fmt.Errorf("unknown file: %v", name) + } + fd, err := s.decodeFileDesc(enc) + if err != nil { + return nil, err + } + return proto.Marshal(fd) +} + +// serviceMetadataForSymbol finds the metadata for name in s.serviceInfo. +// name should be a service name or a method name. +func (s *serverReflectionServer) serviceMetadataForSymbol(name string) (interface{}, error) { + if s.serviceInfo == nil { + s.serviceInfo = s.s.GetServiceInfo() + } + + // Check if it's a service name. + if info, ok := s.serviceInfo[name]; ok { + return info.Metadata, nil + } + + // Check if it's a method name. + pos := strings.LastIndex(name, ".") + // Not a valid method name. + if pos == -1 { + return nil, fmt.Errorf("unknown symbol: %v", name) + } + + info, ok := s.serviceInfo[name[:pos]] + // Substring before last "." is not a service name. + if !ok { + return nil, fmt.Errorf("unknown symbol: %v", name) + } + + // Search for method name in info.Methods. + var found bool + for _, m := range info.Methods { + if m.Name == name[pos+1:] { + found = true + break + } + } + if found { + return info.Metadata, nil + } + + return nil, fmt.Errorf("unknown symbol: %v", name) +} + +// fileDescEncodingContainingSymbol finds the file descriptor containing the given symbol, +// does marshalling on it and returns the marshalled result. +// The given symbol can be a type, a service or a method. +func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string) ([]byte, error) { + var ( + fd *dpb.FileDescriptorProto + ) + // Check if it's a type name. + if st, err := s.typeForName(name); err == nil { + fd, err = s.fileDescForType(st) + if err != nil { + return nil, err + } + } else { // Check if it's a service name or a method name. + meta, err := s.serviceMetadataForSymbol(name) + + // Metadata not found. + if err != nil { + return nil, err + } + + // Metadata not valid. + enc, ok := meta.([]byte) + if !ok { + return nil, fmt.Errorf("invalid file descriptor for symbol: %v", name) + } + + fd, err = s.decodeFileDesc(enc) + if err != nil { + return nil, err + } + } + + return proto.Marshal(fd) +} + +// fileDescEncodingContainingExtension finds the file descriptor containing given extension, +// does marshalling on it and returns the marshalled result. +func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32) ([]byte, error) { + st, err := s.typeForName(typeName) + if err != nil { + return nil, err + } + fd, err := s.fileDescContainingExtension(st, extNum) + if err != nil { + return nil, err + } + return proto.Marshal(fd) +} + +// allExtensionNumbersForTypeName returns all extension numbers for the given type. +func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) { + st, err := s.typeForName(name) + if err != nil { + return nil, err + } + extNums, err := s.allExtensionNumbersForType(st) + if err != nil { + return nil, err + } + return extNums, nil +} + +// ServerReflectionInfo is the reflection service handler. +func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflection_ServerReflectionInfoServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + out := &rpb.ServerReflectionResponse{ + ValidHost: in.Host, + OriginalRequest: in, + } + switch req := in.MessageRequest.(type) { + case *rpb.ServerReflectionRequest_FileByFilename: + b, err := s.fileDescEncodingByFilename(req.FileByFilename) + if err != nil { + out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &rpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: [][]byte{b}}, + } + } + case *rpb.ServerReflectionRequest_FileContainingSymbol: + b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol) + if err != nil { + out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &rpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: [][]byte{b}}, + } + } + case *rpb.ServerReflectionRequest_FileContainingExtension: + typeName := req.FileContainingExtension.ContainingType + extNum := req.FileContainingExtension.ExtensionNumber + b, err := s.fileDescEncodingContainingExtension(typeName, extNum) + if err != nil { + out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &rpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: [][]byte{b}}, + } + } + case *rpb.ServerReflectionRequest_AllExtensionNumbersOfType: + extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) + if err != nil { + out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &rpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &rpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &rpb.ExtensionNumberResponse{ + BaseTypeName: req.AllExtensionNumbersOfType, + ExtensionNumber: extNums, + }, + } + } + case *rpb.ServerReflectionRequest_ListServices: + if s.serviceInfo == nil { + s.serviceInfo = s.s.GetServiceInfo() + } + serviceResponses := make([]*rpb.ServiceResponse, 0, len(s.serviceInfo)) + for n := range s.serviceInfo { + serviceResponses = append(serviceResponses, &rpb.ServiceResponse{ + Name: n, + }) + } + out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &rpb.ListServiceResponse{ + Service: serviceResponses, + }, + } + default: + return grpc.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest) + } + + if err := stream.Send(out); err != nil { + return err + } + } +} diff --git a/vendor/google.golang.org/grpc/reflection/serverreflection_test.go b/vendor/google.golang.org/grpc/reflection/serverreflection_test.go new file mode 100644 index 00000000..ca9610e2 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/serverreflection_test.go @@ -0,0 +1,492 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package reflection + +import ( + "fmt" + "net" + "reflect" + "sort" + "testing" + + "github.com/golang/protobuf/proto" + dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "golang.org/x/net/context" + "google.golang.org/grpc" + rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" + pb "google.golang.org/grpc/reflection/grpc_testing" +) + +var ( + s = &serverReflectionServer{} + // fileDescriptor of each test proto file. + fdTest *dpb.FileDescriptorProto + fdProto2 *dpb.FileDescriptorProto + fdProto2Ext *dpb.FileDescriptorProto + // fileDescriptor marshalled. + fdTestByte []byte + fdProto2Byte []byte + fdProto2ExtByte []byte +) + +func loadFileDesc(filename string) (*dpb.FileDescriptorProto, []byte) { + enc := proto.FileDescriptor(filename) + if enc == nil { + panic(fmt.Sprintf("failed to find fd for file: %v", filename)) + } + fd, err := s.decodeFileDesc(enc) + if err != nil { + panic(fmt.Sprintf("failed to decode enc: %v", err)) + } + b, err := proto.Marshal(fd) + if err != nil { + panic(fmt.Sprintf("failed to marshal fd: %v", err)) + } + return fd, b +} + +func init() { + fdTest, fdTestByte = loadFileDesc("test.proto") + fdProto2, fdProto2Byte = loadFileDesc("proto2.proto") + fdProto2Ext, fdProto2ExtByte = loadFileDesc("proto2_ext.proto") +} + +func TestFileDescForType(t *testing.T) { + for _, test := range []struct { + st reflect.Type + wantFd *dpb.FileDescriptorProto + }{ + {reflect.TypeOf(pb.SearchResponse_Result{}), fdTest}, + {reflect.TypeOf(pb.ToBeExtened{}), fdProto2}, + } { + fd, err := s.fileDescForType(test.st) + if err != nil || !reflect.DeepEqual(fd, test.wantFd) { + t.Errorf("fileDescForType(%q) = %q, %v, want %q, ", test.st, fd, err, test.wantFd) + } + } +} + +func TestTypeForName(t *testing.T) { + for _, test := range []struct { + name string + want reflect.Type + }{ + {"grpc.testing.SearchResponse", reflect.TypeOf(pb.SearchResponse{})}, + } { + r, err := s.typeForName(test.name) + if err != nil || r != test.want { + t.Errorf("typeForName(%q) = %q, %v, want %q, ", test.name, r, err, test.want) + } + } +} + +func TestTypeForNameNotFound(t *testing.T) { + for _, test := range []string{ + "grpc.testing.not_exiting", + } { + _, err := s.typeForName(test) + if err == nil { + t.Errorf("typeForName(%q) = _, %v, want _, ", test, err) + } + } +} + +func TestFileDescContainingExtension(t *testing.T) { + for _, test := range []struct { + st reflect.Type + extNum int32 + want *dpb.FileDescriptorProto + }{ + {reflect.TypeOf(pb.ToBeExtened{}), 17, fdProto2Ext}, + } { + fd, err := s.fileDescContainingExtension(test.st, test.extNum) + if err != nil || !reflect.DeepEqual(fd, test.want) { + t.Errorf("fileDescContainingExtension(%q) = %q, %v, want %q, ", test.st, fd, err, test.want) + } + } +} + +// intArray is used to sort []int32 +type intArray []int32 + +func (s intArray) Len() int { return len(s) } +func (s intArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s intArray) Less(i, j int) bool { return s[i] < s[j] } + +func TestAllExtensionNumbersForType(t *testing.T) { + for _, test := range []struct { + st reflect.Type + want []int32 + }{ + {reflect.TypeOf(pb.ToBeExtened{}), []int32{13, 17}}, + } { + r, err := s.allExtensionNumbersForType(test.st) + sort.Sort(intArray(r)) + if err != nil || !reflect.DeepEqual(r, test.want) { + t.Errorf("allExtensionNumbersForType(%q) = %v, %v, want %v, ", test.st, r, err, test.want) + } + } +} + +// Do end2end tests. + +type server struct{} + +func (s *server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.SearchResponse, error) { + return &pb.SearchResponse{}, nil +} + +func (s *server) StreamingSearch(stream pb.SearchService_StreamingSearchServer) error { + return nil +} + +func TestReflectionEnd2end(t *testing.T) { + // Start server. + lis, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("failed to listen: %v", err) + } + s := grpc.NewServer() + pb.RegisterSearchServiceServer(s, &server{}) + // Register reflection service on s. + Register(s) + go s.Serve(lis) + + // Create client. + conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure()) + if err != nil { + t.Fatalf("cannot connect to server: %v", err) + } + defer conn.Close() + + c := rpb.NewServerReflectionClient(conn) + stream, err := c.ServerReflectionInfo(context.Background()) + + testFileByFilename(t, stream) + testFileByFilenameError(t, stream) + testFileContainingSymbol(t, stream) + testFileContainingSymbolError(t, stream) + testFileContainingExtension(t, stream) + testFileContainingExtensionError(t, stream) + testAllExtensionNumbersOfType(t, stream) + testAllExtensionNumbersOfTypeError(t, stream) + testListServices(t, stream) + + s.Stop() +} + +func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []struct { + filename string + want []byte + }{ + {"test.proto", fdTestByte}, + {"proto2.proto", fdProto2Byte}, + {"proto2_ext.proto", fdProto2ExtByte}, + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: test.filename, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_FileDescriptorResponse: + if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { + t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", test.filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) + } + default: + t.Errorf("FileByFilename(%v) = %v, want type ", test.filename, r.MessageResponse) + } + } +} + +func testFileByFilenameError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []string{ + "test.poto", + "proo2.proto", + "proto2_et.proto", + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: test, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_ErrorResponse: + default: + t.Errorf("FileByFilename(%v) = %v, want type ", test, r.MessageResponse) + } + } +} + +func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []struct { + symbol string + want []byte + }{ + {"grpc.testing.SearchService", fdTestByte}, + {"grpc.testing.SearchService.Search", fdTestByte}, + {"grpc.testing.SearchService.StreamingSearch", fdTestByte}, + {"grpc.testing.SearchResponse", fdTestByte}, + {"grpc.testing.ToBeExtened", fdProto2Byte}, + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: test.symbol, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_FileDescriptorResponse: + if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { + t.Errorf("FileContainingSymbol(%v)\nreceived: %q,\nwant: %q", test.symbol, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) + } + default: + t.Errorf("FileContainingSymbol(%v) = %v, want type ", test.symbol, r.MessageResponse) + } + } +} + +func testFileContainingSymbolError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []string{ + "grpc.testing.SerchService", + "grpc.testing.SearchService.SearchE", + "grpc.tesing.SearchResponse", + "gpc.testing.ToBeExtened", + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: test, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_ErrorResponse: + default: + t.Errorf("FileContainingSymbol(%v) = %v, want type ", test, r.MessageResponse) + } + } +} + +func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []struct { + typeName string + extNum int32 + want []byte + }{ + {"grpc.testing.ToBeExtened", 17, fdProto2ExtByte}, + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &rpb.ExtensionRequest{ + ContainingType: test.typeName, + ExtensionNumber: test.extNum, + }, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_FileDescriptorResponse: + if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { + t.Errorf("FileContainingExtension(%v, %v)\nreceived: %q,\nwant: %q", test.typeName, test.extNum, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) + } + default: + t.Errorf("FileContainingExtension(%v, %v) = %v, want type ", test.typeName, test.extNum, r.MessageResponse) + } + } +} + +func testFileContainingExtensionError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []struct { + typeName string + extNum int32 + }{ + {"grpc.testing.ToBExtened", 17}, + {"grpc.testing.ToBeExtened", 15}, + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &rpb.ExtensionRequest{ + ContainingType: test.typeName, + ExtensionNumber: test.extNum, + }, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_ErrorResponse: + default: + t.Errorf("FileContainingExtension(%v, %v) = %v, want type ", test.typeName, test.extNum, r.MessageResponse) + } + } +} + +func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []struct { + typeName string + want []int32 + }{ + {"grpc.testing.ToBeExtened", []int32{13, 17}}, + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: test.typeName, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_AllExtensionNumbersResponse: + extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber + sort.Sort(intArray(extNum)) + if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName || + !reflect.DeepEqual(extNum, test.want) { + t.Errorf("AllExtensionNumbersOfType(%v)\nreceived: %v,\nwant: {%q %v}", r.GetAllExtensionNumbersResponse(), test.typeName, test.typeName, test.want) + } + default: + t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type ", test.typeName, r.MessageResponse) + } + } +} + +func testAllExtensionNumbersOfTypeError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + for _, test := range []string{ + "grpc.testing.ToBeExtenedE", + } { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: test, + }, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_ErrorResponse: + default: + t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type ", test, r.MessageResponse) + } + } +} + +func testListServices(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { + if err := stream.Send(&rpb.ServerReflectionRequest{ + MessageRequest: &rpb.ServerReflectionRequest_ListServices{}, + }); err != nil { + t.Fatalf("failed to send request: %v", err) + } + r, err := stream.Recv() + if err != nil { + // io.EOF is not ok. + t.Fatalf("failed to recv response: %v", err) + } + + switch r.MessageResponse.(type) { + case *rpb.ServerReflectionResponse_ListServicesResponse: + services := r.GetListServicesResponse().Service + want := []string{"grpc.testing.SearchService", "grpc.reflection.v1alpha.ServerReflection"} + // Compare service names in response with want. + if len(services) != len(want) { + t.Errorf("= %v, want service names: %v", services, want) + } + m := make(map[string]int) + for _, e := range services { + m[e.Name]++ + } + for _, e := range want { + if m[e] > 0 { + m[e]-- + continue + } + t.Errorf("ListService\nreceived: %v,\nwant: %q", services, want) + } + default: + t.Errorf("ListServices = %v, want type ", r.MessageResponse) + } +} diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go new file mode 100644 index 00000000..d6287175 --- /dev/null +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -0,0 +1,449 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "compress/gzip" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "math" + "os" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/transport" +) + +// Codec defines the interface gRPC uses to encode and decode messages. +type Codec interface { + // Marshal returns the wire format of v. + Marshal(v interface{}) ([]byte, error) + // Unmarshal parses the wire format into v. + Unmarshal(data []byte, v interface{}) error + // String returns the name of the Codec implementation. The returned + // string will be used as part of content type in transmission. + String() string +} + +// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC. +type protoCodec struct{} + +func (protoCodec) Marshal(v interface{}) ([]byte, error) { + return proto.Marshal(v.(proto.Message)) +} + +func (protoCodec) Unmarshal(data []byte, v interface{}) error { + return proto.Unmarshal(data, v.(proto.Message)) +} + +func (protoCodec) String() string { + return "proto" +} + +// Compressor defines the interface gRPC uses to compress a message. +type Compressor interface { + // Do compresses p into w. + Do(w io.Writer, p []byte) error + // Type returns the compression algorithm the Compressor uses. + Type() string +} + +// NewGZIPCompressor creates a Compressor based on GZIP. +func NewGZIPCompressor() Compressor { + return &gzipCompressor{} +} + +type gzipCompressor struct { +} + +func (c *gzipCompressor) Do(w io.Writer, p []byte) error { + z := gzip.NewWriter(w) + if _, err := z.Write(p); err != nil { + return err + } + return z.Close() +} + +func (c *gzipCompressor) Type() string { + return "gzip" +} + +// Decompressor defines the interface gRPC uses to decompress a message. +type Decompressor interface { + // Do reads the data from r and uncompress them. + Do(r io.Reader) ([]byte, error) + // Type returns the compression algorithm the Decompressor uses. + Type() string +} + +type gzipDecompressor struct { +} + +// NewGZIPDecompressor creates a Decompressor based on GZIP. +func NewGZIPDecompressor() Decompressor { + return &gzipDecompressor{} +} + +func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { + z, err := gzip.NewReader(r) + if err != nil { + return nil, err + } + defer z.Close() + return ioutil.ReadAll(z) +} + +func (d *gzipDecompressor) Type() string { + return "gzip" +} + +// callInfo contains all related configuration and information about an RPC. +type callInfo struct { + failFast bool + headerMD metadata.MD + trailerMD metadata.MD + traceInfo traceInfo // in trace.go +} + +var defaultCallInfo = callInfo{failFast: true} + +// CallOption configures a Call before it starts or extracts information from +// a Call after it completes. +type CallOption interface { + // before is called before the call is sent to any server. If before + // returns a non-nil error, the RPC fails with that error. + before(*callInfo) error + + // after is called after the call has completed. after cannot return an + // error, so any failures should be reported via output parameters. + after(*callInfo) +} + +type beforeCall func(c *callInfo) error + +func (o beforeCall) before(c *callInfo) error { return o(c) } +func (o beforeCall) after(c *callInfo) {} + +type afterCall func(c *callInfo) + +func (o afterCall) before(c *callInfo) error { return nil } +func (o afterCall) after(c *callInfo) { o(c) } + +// Header returns a CallOptions that retrieves the header metadata +// for a unary RPC. +func Header(md *metadata.MD) CallOption { + return afterCall(func(c *callInfo) { + *md = c.headerMD + }) +} + +// Trailer returns a CallOptions that retrieves the trailer metadata +// for a unary RPC. +func Trailer(md *metadata.MD) CallOption { + return afterCall(func(c *callInfo) { + *md = c.trailerMD + }) +} + +// FailFast configures the action to take when an RPC is attempted on broken +// connections or unreachable servers. If failfast is true, the RPC will fail +// immediately. Otherwise, the RPC client will block the call until a +// connection is available (or the call is canceled or times out) and will retry +// the call if it fails due to a transient error. Please refer to +// https://github.com/grpc/grpc/blob/master/doc/fail_fast.md +func FailFast(failFast bool) CallOption { + return beforeCall(func(c *callInfo) error { + c.failFast = failFast + return nil + }) +} + +// The format of the payload: compressed or not? +type payloadFormat uint8 + +const ( + compressionNone payloadFormat = iota // no compression + compressionMade +) + +// parser reads complete gRPC messages from the underlying reader. +type parser struct { + // r is the underlying reader. + // See the comment on recvMsg for the permissible + // error types. + r io.Reader + + // The header of a gRPC message. Find more detail + // at http://www.grpc.io/docs/guides/wire.html. + header [5]byte +} + +// recvMsg reads a complete gRPC message from the stream. +// +// It returns the message and its payload (compression/encoding) +// format. The caller owns the returned msg memory. +// +// If there is an error, possible values are: +// * io.EOF, when no messages remain +// * io.ErrUnexpectedEOF +// * of type transport.ConnectionError +// * of type transport.StreamError +// No other error values or types must be returned, which also means +// that the underlying io.Reader must not return an incompatible +// error. +func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) { + if _, err := io.ReadFull(p.r, p.header[:]); err != nil { + return 0, nil, err + } + + pf = payloadFormat(p.header[0]) + length := binary.BigEndian.Uint32(p.header[1:]) + + if length == 0 { + return pf, nil, nil + } + // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead + // of making it for each message: + msg = make([]byte, int(length)) + if _, err := io.ReadFull(p.r, msg); err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return 0, nil, err + } + return pf, msg, nil +} + +// encode serializes msg and prepends the message header. If msg is nil, it +// generates the message header of 0 message length. +func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer) ([]byte, error) { + var b []byte + var length uint + if msg != nil { + var err error + // TODO(zhaoq): optimize to reduce memory alloc and copying. + b, err = c.Marshal(msg) + if err != nil { + return nil, err + } + if cp != nil { + if err := cp.Do(cbuf, b); err != nil { + return nil, err + } + b = cbuf.Bytes() + } + length = uint(len(b)) + } + if length > math.MaxUint32 { + return nil, Errorf(codes.InvalidArgument, "grpc: message too large (%d bytes)", length) + } + + const ( + payloadLen = 1 + sizeLen = 4 + ) + + var buf = make([]byte, payloadLen+sizeLen+len(b)) + + // Write payload format + if cp == nil { + buf[0] = byte(compressionNone) + } else { + buf[0] = byte(compressionMade) + } + // Write length of b into buf + binary.BigEndian.PutUint32(buf[1:], uint32(length)) + // Copy encoded msg to buf + copy(buf[5:], b) + + return buf, nil +} + +func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) error { + switch pf { + case compressionNone: + case compressionMade: + if dc == nil || recvCompress != dc.Type() { + return transport.StreamErrorf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) + } + default: + return transport.StreamErrorf(codes.Internal, "grpc: received unexpected payload format %d", pf) + } + return nil +} + +func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}) error { + pf, d, err := p.recvMsg() + if err != nil { + return err + } + if err := checkRecvPayload(pf, s.RecvCompress(), dc); err != nil { + return err + } + if pf == compressionMade { + d, err = dc.Do(bytes.NewReader(d)) + if err != nil { + return transport.StreamErrorf(codes.Internal, "grpc: failed to decompress the received message %v", err) + } + } + if err := c.Unmarshal(d, m); err != nil { + return transport.StreamErrorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) + } + return nil +} + +// rpcError defines the status from an RPC. +type rpcError struct { + code codes.Code + desc string +} + +func (e *rpcError) Error() string { + return fmt.Sprintf("rpc error: code = %d desc = %s", e.code, e.desc) +} + +// Code returns the error code for err if it was produced by the rpc system. +// Otherwise, it returns codes.Unknown. +func Code(err error) codes.Code { + if err == nil { + return codes.OK + } + if e, ok := err.(*rpcError); ok { + return e.code + } + return codes.Unknown +} + +// ErrorDesc returns the error description of err if it was produced by the rpc system. +// Otherwise, it returns err.Error() or empty string when err is nil. +func ErrorDesc(err error) string { + if err == nil { + return "" + } + if e, ok := err.(*rpcError); ok { + return e.desc + } + return err.Error() +} + +// Errorf returns an error containing an error code and a description; +// Errorf returns nil if c is OK. +func Errorf(c codes.Code, format string, a ...interface{}) error { + if c == codes.OK { + return nil + } + return &rpcError{ + code: c, + desc: fmt.Sprintf(format, a...), + } +} + +// toRPCErr converts an error into a rpcError. +func toRPCErr(err error) error { + switch e := err.(type) { + case *rpcError: + return err + case transport.StreamError: + return &rpcError{ + code: e.Code, + desc: e.Desc, + } + case transport.ConnectionError: + return &rpcError{ + code: codes.Internal, + desc: e.Desc, + } + default: + switch err { + case context.DeadlineExceeded: + return &rpcError{ + code: codes.DeadlineExceeded, + desc: err.Error(), + } + case context.Canceled: + return &rpcError{ + code: codes.Canceled, + desc: err.Error(), + } + case ErrClientConnClosing: + return &rpcError{ + code: codes.FailedPrecondition, + desc: err.Error(), + } + } + + } + return Errorf(codes.Unknown, "%v", err) +} + +// convertCode converts a standard Go error into its canonical code. Note that +// this is only used to translate the error returned by the server applications. +func convertCode(err error) codes.Code { + switch err { + case nil: + return codes.OK + case io.EOF: + return codes.OutOfRange + case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF: + return codes.FailedPrecondition + case os.ErrInvalid: + return codes.InvalidArgument + case context.Canceled: + return codes.Canceled + case context.DeadlineExceeded: + return codes.DeadlineExceeded + } + switch { + case os.IsExist(err): + return codes.AlreadyExists + case os.IsNotExist(err): + return codes.NotFound + case os.IsPermission(err): + return codes.PermissionDenied + } + return codes.Unknown +} + +// SupportPackageIsVersion3 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the grpc package. +// +// This constant may be renamed in the future if a change in the generated code +// requires a synchronised update of grpc-go and protoc-gen-go. This constant +// should not be referenced from any other code. +const SupportPackageIsVersion3 = true diff --git a/vendor/google.golang.org/grpc/rpc_util_test.go b/vendor/google.golang.org/grpc/rpc_util_test.go new file mode 100644 index 00000000..5a802d65 --- /dev/null +++ b/vendor/google.golang.org/grpc/rpc_util_test.go @@ -0,0 +1,233 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "io" + "reflect" + "testing" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + perfpb "google.golang.org/grpc/test/codec_perf" + "google.golang.org/grpc/transport" +) + +func TestSimpleParsing(t *testing.T) { + bigMsg := bytes.Repeat([]byte{'x'}, 1<<24) + for _, test := range []struct { + // input + p []byte + // outputs + err error + b []byte + pt payloadFormat + }{ + {nil, io.EOF, nil, compressionNone}, + {[]byte{0, 0, 0, 0, 0}, nil, nil, compressionNone}, + {[]byte{0, 0, 0, 0, 1, 'a'}, nil, []byte{'a'}, compressionNone}, + {[]byte{1, 0}, io.ErrUnexpectedEOF, nil, compressionNone}, + {[]byte{0, 0, 0, 0, 10, 'a'}, io.ErrUnexpectedEOF, nil, compressionNone}, + // Check that messages with length >= 2^24 are parsed. + {append([]byte{0, 1, 0, 0, 0}, bigMsg...), nil, bigMsg, compressionNone}, + } { + buf := bytes.NewReader(test.p) + parser := &parser{r: buf} + pt, b, err := parser.recvMsg() + if err != test.err || !bytes.Equal(b, test.b) || pt != test.pt { + t.Fatalf("parser{%v}.recvMsg() = %v, %v, %v\nwant %v, %v, %v", test.p, pt, b, err, test.pt, test.b, test.err) + } + } +} + +func TestMultipleParsing(t *testing.T) { + // Set a byte stream consists of 3 messages with their headers. + p := []byte{0, 0, 0, 0, 1, 'a', 0, 0, 0, 0, 2, 'b', 'c', 0, 0, 0, 0, 1, 'd'} + b := bytes.NewReader(p) + parser := &parser{r: b} + + wantRecvs := []struct { + pt payloadFormat + data []byte + }{ + {compressionNone, []byte("a")}, + {compressionNone, []byte("bc")}, + {compressionNone, []byte("d")}, + } + for i, want := range wantRecvs { + pt, data, err := parser.recvMsg() + if err != nil || pt != want.pt || !reflect.DeepEqual(data, want.data) { + t.Fatalf("after %d calls, parser{%v}.recvMsg() = %v, %v, %v\nwant %v, %v, ", + i, p, pt, data, err, want.pt, want.data) + } + } + + pt, data, err := parser.recvMsg() + if err != io.EOF { + t.Fatalf("after %d recvMsgs calls, parser{%v}.recvMsg() = %v, %v, %v\nwant _, _, %v", + len(wantRecvs), p, pt, data, err, io.EOF) + } +} + +func TestEncode(t *testing.T) { + for _, test := range []struct { + // input + msg proto.Message + cp Compressor + // outputs + b []byte + err error + }{ + {nil, nil, []byte{0, 0, 0, 0, 0}, nil}, + } { + b, err := encode(protoCodec{}, test.msg, nil, nil) + if err != test.err || !bytes.Equal(b, test.b) { + t.Fatalf("encode(_, _, %v, _) = %v, %v\nwant %v, %v", test.cp, b, err, test.b, test.err) + } + } +} + +func TestCompress(t *testing.T) { + for _, test := range []struct { + // input + data []byte + cp Compressor + dc Decompressor + // outputs + err error + }{ + {make([]byte, 1024), &gzipCompressor{}, &gzipDecompressor{}, nil}, + } { + b := new(bytes.Buffer) + if err := test.cp.Do(b, test.data); err != test.err { + t.Fatalf("Compressor.Do(_, %v) = %v, want %v", test.data, err, test.err) + } + if b.Len() >= len(test.data) { + t.Fatalf("The compressor fails to compress data.") + } + if p, err := test.dc.Do(b); err != nil || !bytes.Equal(test.data, p) { + t.Fatalf("Decompressor.Do(%v) = %v, %v, want %v, ", b, p, err, test.data) + } + } +} + +func TestToRPCErr(t *testing.T) { + for _, test := range []struct { + // input + errIn error + // outputs + errOut *rpcError + }{ + {transport.StreamErrorf(codes.Unknown, ""), Errorf(codes.Unknown, "").(*rpcError)}, + {transport.ErrConnClosing, Errorf(codes.Internal, transport.ErrConnClosing.Desc).(*rpcError)}, + } { + err := toRPCErr(test.errIn) + rpcErr, ok := err.(*rpcError) + if !ok { + t.Fatalf("toRPCErr{%v} returned type %T, want %T", test.errIn, err, rpcError{}) + } + if *rpcErr != *test.errOut { + t.Fatalf("toRPCErr{%v} = %v \nwant %v", test.errIn, err, test.errOut) + } + } +} + +func TestContextErr(t *testing.T) { + for _, test := range []struct { + // input + errIn error + // outputs + errOut transport.StreamError + }{ + {context.DeadlineExceeded, transport.StreamErrorf(codes.DeadlineExceeded, "%v", context.DeadlineExceeded)}, + {context.Canceled, transport.StreamErrorf(codes.Canceled, "%v", context.Canceled)}, + } { + err := transport.ContextErr(test.errIn) + if err != test.errOut { + t.Fatalf("ContextErr{%v} = %v \nwant %v", test.errIn, err, test.errOut) + } + } +} + +func TestErrorsWithSameParameters(t *testing.T) { + const description = "some description" + e1 := Errorf(codes.AlreadyExists, description) + e2 := Errorf(codes.AlreadyExists, description) + if e1 == e2 { + t.Fatalf("Error interfaces should not be considered equal - e1: %p - %v e2: %p - %v", e1, e1, e2, e2) + } + if Code(e1) != Code(e2) || ErrorDesc(e1) != ErrorDesc(e2) { + t.Fatalf("Expected errors to have same code and description - e1: %p - %v e2: %p - %v", e1, e1, e2, e2) + } +} + +// bmEncode benchmarks encoding a Protocol Buffer message containing mSize +// bytes. +func bmEncode(b *testing.B, mSize int) { + msg := &perfpb.Buffer{Body: make([]byte, mSize)} + encoded, _ := encode(protoCodec{}, msg, nil, nil) + encodedSz := int64(len(encoded)) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + encode(protoCodec{}, msg, nil, nil) + } + b.SetBytes(encodedSz) +} + +func BenchmarkEncode1B(b *testing.B) { + bmEncode(b, 1) +} + +func BenchmarkEncode1KiB(b *testing.B) { + bmEncode(b, 1024) +} + +func BenchmarkEncode8KiB(b *testing.B) { + bmEncode(b, 8*1024) +} + +func BenchmarkEncode64KiB(b *testing.B) { + bmEncode(b, 64*1024) +} + +func BenchmarkEncode512KiB(b *testing.B) { + bmEncode(b, 512*1024) +} + +func BenchmarkEncode1MiB(b *testing.B) { + bmEncode(b, 1024*1024) +} diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go new file mode 100644 index 00000000..f7b8319b --- /dev/null +++ b/vendor/google.golang.org/grpc/server.go @@ -0,0 +1,835 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "net/http" + "reflect" + "runtime" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/http2" + "golang.org/x/net/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/transport" +) + +type methodHandler func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor UnaryServerInterceptor) (interface{}, error) + +// MethodDesc represents an RPC service's method specification. +type MethodDesc struct { + MethodName string + Handler methodHandler +} + +// ServiceDesc represents an RPC service's specification. +type ServiceDesc struct { + ServiceName string + // The pointer to the service interface. Used to check whether the user + // provided implementation satisfies the interface requirements. + HandlerType interface{} + Methods []MethodDesc + Streams []StreamDesc + Metadata interface{} +} + +// service consists of the information of the server serving this service and +// the methods in this service. +type service struct { + server interface{} // the server for service methods + md map[string]*MethodDesc + sd map[string]*StreamDesc + mdata interface{} +} + +// Server is a gRPC server to serve RPC requests. +type Server struct { + opts options + + mu sync.Mutex // guards following + lis map[net.Listener]bool + conns map[io.Closer]bool + m map[string]*service // service name -> service info + events trace.EventLog +} + +type options struct { + creds credentials.TransportCredentials + codec Codec + cp Compressor + dc Decompressor + unaryInt UnaryServerInterceptor + streamInt StreamServerInterceptor + maxConcurrentStreams uint32 + useHandlerImpl bool // use http.Handler-based server +} + +// A ServerOption sets options. +type ServerOption func(*options) + +// CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling. +func CustomCodec(codec Codec) ServerOption { + return func(o *options) { + o.codec = codec + } +} + +// RPCCompressor returns a ServerOption that sets a compressor for outbound message. +func RPCCompressor(cp Compressor) ServerOption { + return func(o *options) { + o.cp = cp + } +} + +// RPCDecompressor returns a ServerOption that sets a decompressor for inbound message. +func RPCDecompressor(dc Decompressor) ServerOption { + return func(o *options) { + o.dc = dc + } +} + +// MaxConcurrentStreams returns a ServerOption that will apply a limit on the number +// of concurrent streams to each ServerTransport. +func MaxConcurrentStreams(n uint32) ServerOption { + return func(o *options) { + o.maxConcurrentStreams = n + } +} + +// Creds returns a ServerOption that sets credentials for server connections. +func Creds(c credentials.TransportCredentials) ServerOption { + return func(o *options) { + o.creds = c + } +} + +// UnaryInterceptor returns a ServerOption that sets the UnaryServerInterceptor for the +// server. Only one unary interceptor can be installed. The construction of multiple +// interceptors (e.g., chaining) can be implemented at the caller. +func UnaryInterceptor(i UnaryServerInterceptor) ServerOption { + return func(o *options) { + if o.unaryInt != nil { + panic("The unary server interceptor has been set.") + } + o.unaryInt = i + } +} + +// StreamInterceptor returns a ServerOption that sets the StreamServerInterceptor for the +// server. Only one stream interceptor can be installed. +func StreamInterceptor(i StreamServerInterceptor) ServerOption { + return func(o *options) { + if o.streamInt != nil { + panic("The stream server interceptor has been set.") + } + o.streamInt = i + } +} + +// NewServer creates a gRPC server which has no service registered and has not +// started to accept requests yet. +func NewServer(opt ...ServerOption) *Server { + var opts options + for _, o := range opt { + o(&opts) + } + if opts.codec == nil { + // Set the default codec. + opts.codec = protoCodec{} + } + s := &Server{ + lis: make(map[net.Listener]bool), + opts: opts, + conns: make(map[io.Closer]bool), + m: make(map[string]*service), + } + if EnableTracing { + _, file, line, _ := runtime.Caller(1) + s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) + } + return s +} + +// printf records an event in s's event log, unless s has been stopped. +// REQUIRES s.mu is held. +func (s *Server) printf(format string, a ...interface{}) { + if s.events != nil { + s.events.Printf(format, a...) + } +} + +// errorf records an error in s's event log, unless s has been stopped. +// REQUIRES s.mu is held. +func (s *Server) errorf(format string, a ...interface{}) { + if s.events != nil { + s.events.Errorf(format, a...) + } +} + +// RegisterService register a service and its implementation to the gRPC +// server. Called from the IDL generated code. This must be called before +// invoking Serve. +func (s *Server) RegisterService(sd *ServiceDesc, ss interface{}) { + ht := reflect.TypeOf(sd.HandlerType).Elem() + st := reflect.TypeOf(ss) + if !st.Implements(ht) { + grpclog.Fatalf("grpc: Server.RegisterService found the handler of type %v that does not satisfy %v", st, ht) + } + s.register(sd, ss) +} + +func (s *Server) register(sd *ServiceDesc, ss interface{}) { + s.mu.Lock() + defer s.mu.Unlock() + s.printf("RegisterService(%q)", sd.ServiceName) + if _, ok := s.m[sd.ServiceName]; ok { + grpclog.Fatalf("grpc: Server.RegisterService found duplicate service registration for %q", sd.ServiceName) + } + srv := &service{ + server: ss, + md: make(map[string]*MethodDesc), + sd: make(map[string]*StreamDesc), + mdata: sd.Metadata, + } + for i := range sd.Methods { + d := &sd.Methods[i] + srv.md[d.MethodName] = d + } + for i := range sd.Streams { + d := &sd.Streams[i] + srv.sd[d.StreamName] = d + } + s.m[sd.ServiceName] = srv +} + +// MethodInfo contains information about an RPC. +type MethodInfo struct { + // Name is the method name only, without the service name or package name. + Name string + // IsClientStream indicates whether the RPC is a client streaming RPC. + IsClientStream bool + // IsServerStream indicates whether the RPC is a server streaming RPC. + IsServerStream bool +} + +// ServiceInfo contains unary RPC method info, streaming RPC methid info and metadata for a service. +type ServiceInfo struct { + Methods []MethodInfo + // Metadata is the metadata specified in ServiceDesc when registering service. + Metadata interface{} +} + +// GetServiceInfo returns a map from service names to ServiceInfo. +// Service names include the package names, in the form of .. +func (s *Server) GetServiceInfo() map[string]*ServiceInfo { + ret := make(map[string]*ServiceInfo) + for n, srv := range s.m { + methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd)) + for m := range srv.md { + methods = append(methods, MethodInfo{ + Name: m, + IsClientStream: false, + IsServerStream: false, + }) + } + for m, d := range srv.sd { + methods = append(methods, MethodInfo{ + Name: m, + IsClientStream: d.ClientStreams, + IsServerStream: d.ServerStreams, + }) + } + + ret[n] = &ServiceInfo{ + Methods: methods, + Metadata: srv.mdata, + } + } + return ret +} + +var ( + // ErrServerStopped indicates that the operation is now illegal because of + // the server being stopped. + ErrServerStopped = errors.New("grpc: the server has been stopped") +) + +func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { + if s.opts.creds == nil { + return rawConn, nil, nil + } + return s.opts.creds.ServerHandshake(rawConn) +} + +// Serve accepts incoming connections on the listener lis, creating a new +// ServerTransport and service goroutine for each. The service goroutines +// read gRPC requests and then call the registered handlers to reply to them. +// Service returns when lis.Accept fails. lis will be closed when +// this method returns. +func (s *Server) Serve(lis net.Listener) error { + s.mu.Lock() + s.printf("serving") + if s.lis == nil { + s.mu.Unlock() + lis.Close() + return ErrServerStopped + } + s.lis[lis] = true + s.mu.Unlock() + defer func() { + lis.Close() + s.mu.Lock() + delete(s.lis, lis) + s.mu.Unlock() + }() + for { + rawConn, err := lis.Accept() + if err != nil { + s.mu.Lock() + s.printf("done serving; Accept = %v", err) + s.mu.Unlock() + return err + } + // Start a new goroutine to deal with rawConn + // so we don't stall this Accept loop goroutine. + go s.handleRawConn(rawConn) + } +} + +// handleRawConn is run in its own goroutine and handles a just-accepted +// connection that has not had any I/O performed on it yet. +func (s *Server) handleRawConn(rawConn net.Conn) { + conn, authInfo, err := s.useTransportAuthenticator(rawConn) + if err != nil { + s.mu.Lock() + s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) + s.mu.Unlock() + grpclog.Printf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) + rawConn.Close() + return + } + + s.mu.Lock() + if s.conns == nil { + s.mu.Unlock() + conn.Close() + return + } + s.mu.Unlock() + + if s.opts.useHandlerImpl { + s.serveUsingHandler(conn) + } else { + s.serveNewHTTP2Transport(conn, authInfo) + } +} + +// serveNewHTTP2Transport sets up a new http/2 transport (using the +// gRPC http2 server transport in transport/http2_server.go) and +// serves streams on it. +// This is run in its own goroutine (it does network I/O in +// transport.NewServerTransport). +func (s *Server) serveNewHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) { + st, err := transport.NewServerTransport("http2", c, s.opts.maxConcurrentStreams, authInfo) + if err != nil { + s.mu.Lock() + s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err) + s.mu.Unlock() + c.Close() + grpclog.Println("grpc: Server.Serve failed to create ServerTransport: ", err) + return + } + if !s.addConn(st) { + st.Close() + return + } + s.serveStreams(st) +} + +func (s *Server) serveStreams(st transport.ServerTransport) { + defer s.removeConn(st) + defer st.Close() + var wg sync.WaitGroup + st.HandleStreams(func(stream *transport.Stream) { + wg.Add(1) + go func() { + defer wg.Done() + s.handleStream(st, stream, s.traceInfo(st, stream)) + }() + }) + wg.Wait() +} + +var _ http.Handler = (*Server)(nil) + +// serveUsingHandler is called from handleRawConn when s is configured +// to handle requests via the http.Handler interface. It sets up a +// net/http.Server to handle the just-accepted conn. The http.Server +// is configured to route all incoming requests (all HTTP/2 streams) +// to ServeHTTP, which creates a new ServerTransport for each stream. +// serveUsingHandler blocks until conn closes. +// +// This codepath is only used when Server.TestingUseHandlerImpl has +// been configured. This lets the end2end tests exercise the ServeHTTP +// method as one of the environment types. +// +// conn is the *tls.Conn that's already been authenticated. +func (s *Server) serveUsingHandler(conn net.Conn) { + if !s.addConn(conn) { + conn.Close() + return + } + defer s.removeConn(conn) + h2s := &http2.Server{ + MaxConcurrentStreams: s.opts.maxConcurrentStreams, + } + h2s.ServeConn(conn, &http2.ServeConnOpts{ + Handler: s, + }) +} + +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + st, err := transport.NewServerHandlerTransport(w, r) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if !s.addConn(st) { + st.Close() + return + } + defer s.removeConn(st) + s.serveStreams(st) +} + +// traceInfo returns a traceInfo and associates it with stream, if tracing is enabled. +// If tracing is not enabled, it returns nil. +func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Stream) (trInfo *traceInfo) { + if !EnableTracing { + return nil + } + trInfo = &traceInfo{ + tr: trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()), + } + trInfo.firstLine.client = false + trInfo.firstLine.remoteAddr = st.RemoteAddr() + stream.TraceContext(trInfo.tr) + if dl, ok := stream.Context().Deadline(); ok { + trInfo.firstLine.deadline = dl.Sub(time.Now()) + } + return trInfo +} + +func (s *Server) addConn(c io.Closer) bool { + s.mu.Lock() + defer s.mu.Unlock() + if s.conns == nil { + return false + } + s.conns[c] = true + return true +} + +func (s *Server) removeConn(c io.Closer) { + s.mu.Lock() + defer s.mu.Unlock() + if s.conns != nil { + delete(s.conns, c) + } +} + +func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options) error { + var cbuf *bytes.Buffer + if cp != nil { + cbuf = new(bytes.Buffer) + } + p, err := encode(s.opts.codec, msg, cp, cbuf) + if err != nil { + // This typically indicates a fatal issue (e.g., memory + // corruption or hardware faults) the application program + // cannot handle. + // + // TODO(zhaoq): There exist other options also such as only closing the + // faulty stream locally and remotely (Other streams can keep going). Find + // the optimal option. + grpclog.Fatalf("grpc: Server failed to encode response %v", err) + } + return t.Write(stream, p, opts) +} + +func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { + if trInfo != nil { + defer trInfo.tr.Finish() + trInfo.firstLine.client = false + trInfo.tr.LazyLog(&trInfo.firstLine, false) + defer func() { + if err != nil && err != io.EOF { + trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + trInfo.tr.SetError() + } + }() + } + if s.opts.cp != nil { + // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. + stream.SetSendCompress(s.opts.cp.Type()) + } + p := &parser{r: stream} + for { + pf, req, err := p.recvMsg() + if err == io.EOF { + // The entire stream is done (for unary RPC only). + return err + } + if err == io.ErrUnexpectedEOF { + err = transport.StreamError{Code: codes.Internal, Desc: "io.ErrUnexpectedEOF"} + } + if err != nil { + switch err := err.(type) { + case transport.ConnectionError: + // Nothing to do here. + case transport.StreamError: + if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) + } + default: + panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) + } + return err + } + + if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { + switch err := err.(type) { + case transport.StreamError: + if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) + } + default: + if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) + } + + } + return err + } + statusCode := codes.OK + statusDesc := "" + df := func(v interface{}) error { + if pf == compressionMade { + var err error + req, err = s.opts.dc.Do(bytes.NewReader(req)) + if err != nil { + if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) + } + return err + } + } + if err := s.opts.codec.Unmarshal(req, v); err != nil { + return err + } + if trInfo != nil { + trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) + } + return nil + } + reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) + if appErr != nil { + if err, ok := appErr.(*rpcError); ok { + statusCode = err.code + statusDesc = err.desc + } else { + statusCode = convertCode(appErr) + statusDesc = appErr.Error() + } + if trInfo != nil && statusCode != codes.OK { + trInfo.tr.LazyLog(stringer(statusDesc), true) + trInfo.tr.SetError() + } + if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) + return err + } + return nil + } + if trInfo != nil { + trInfo.tr.LazyLog(stringer("OK"), false) + } + opts := &transport.Options{ + Last: true, + Delay: false, + } + if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil { + switch err := err.(type) { + case transport.ConnectionError: + // Nothing to do here. + case transport.StreamError: + statusCode = err.Code + statusDesc = err.Desc + default: + statusCode = codes.Unknown + statusDesc = err.Error() + } + return err + } + if trInfo != nil { + trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) + } + return t.WriteStatus(stream, statusCode, statusDesc) + } +} + +func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { + if s.opts.cp != nil { + stream.SetSendCompress(s.opts.cp.Type()) + } + ss := &serverStream{ + t: t, + s: stream, + p: &parser{r: stream}, + codec: s.opts.codec, + cp: s.opts.cp, + dc: s.opts.dc, + trInfo: trInfo, + } + if ss.cp != nil { + ss.cbuf = new(bytes.Buffer) + } + if trInfo != nil { + trInfo.tr.LazyLog(&trInfo.firstLine, false) + defer func() { + ss.mu.Lock() + if err != nil && err != io.EOF { + ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + ss.trInfo.tr.SetError() + } + ss.trInfo.tr.Finish() + ss.trInfo.tr = nil + ss.mu.Unlock() + }() + } + var appErr error + if s.opts.streamInt == nil { + appErr = sd.Handler(srv.server, ss) + } else { + info := &StreamServerInfo{ + FullMethod: stream.Method(), + IsClientStream: sd.ClientStreams, + IsServerStream: sd.ServerStreams, + } + appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler) + } + if appErr != nil { + if err, ok := appErr.(*rpcError); ok { + ss.statusCode = err.code + ss.statusDesc = err.desc + } else if err, ok := appErr.(transport.StreamError); ok { + ss.statusCode = err.Code + ss.statusDesc = err.Desc + } else { + ss.statusCode = convertCode(appErr) + ss.statusDesc = appErr.Error() + } + } + if trInfo != nil { + ss.mu.Lock() + if ss.statusCode != codes.OK { + ss.trInfo.tr.LazyLog(stringer(ss.statusDesc), true) + ss.trInfo.tr.SetError() + } else { + ss.trInfo.tr.LazyLog(stringer("OK"), false) + } + ss.mu.Unlock() + } + return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) + +} + +func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { + sm := stream.Method() + if sm != "" && sm[0] == '/' { + sm = sm[1:] + } + pos := strings.LastIndex(sm, "/") + if pos == -1 { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{sm}}, true) + trInfo.tr.SetError() + } + if err := t.WriteStatus(stream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", stream.Method())); err != nil { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + trInfo.tr.SetError() + } + grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) + } + if trInfo != nil { + trInfo.tr.Finish() + } + return + } + service := sm[:pos] + method := sm[pos+1:] + srv, ok := s.m[service] + if !ok { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true) + trInfo.tr.SetError() + } + if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + trInfo.tr.SetError() + } + grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) + } + if trInfo != nil { + trInfo.tr.Finish() + } + return + } + // Unary RPC or Streaming RPC? + if md, ok := srv.md[method]; ok { + s.processUnaryRPC(t, stream, srv, md, trInfo) + return + } + if sd, ok := srv.sd[method]; ok { + s.processStreamingRPC(t, stream, srv, sd, trInfo) + return + } + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"Unknown method %v", []interface{}{method}}, true) + trInfo.tr.SetError() + } + if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown method %v", method)); err != nil { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + trInfo.tr.SetError() + } + grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) + } + if trInfo != nil { + trInfo.tr.Finish() + } +} + +// Stop stops the gRPC server. It immediately closes all open +// connections and listeners. +// It cancels all active RPCs on the server side and the corresponding +// pending RPCs on the client side will get notified by connection +// errors. +func (s *Server) Stop() { + s.mu.Lock() + listeners := s.lis + s.lis = nil + cs := s.conns + s.conns = nil + s.mu.Unlock() + + for lis := range listeners { + lis.Close() + } + for c := range cs { + c.Close() + } + + s.mu.Lock() + if s.events != nil { + s.events.Finish() + s.events = nil + } + s.mu.Unlock() +} + +func init() { + internal.TestingCloseConns = func(arg interface{}) { + arg.(*Server).testingCloseConns() + } + internal.TestingUseHandlerImpl = func(arg interface{}) { + arg.(*Server).opts.useHandlerImpl = true + } +} + +// testingCloseConns closes all existing transports but keeps s.lis +// accepting new connections. +func (s *Server) testingCloseConns() { + s.mu.Lock() + for c := range s.conns { + c.Close() + delete(s.conns, c) + } + s.mu.Unlock() +} + +// SendHeader sends header metadata. It may be called at most once from a unary +// RPC handler. The ctx is the RPC handler's Context or one derived from it. +func SendHeader(ctx context.Context, md metadata.MD) error { + if md.Len() == 0 { + return nil + } + stream, ok := transport.StreamFromContext(ctx) + if !ok { + return fmt.Errorf("grpc: failed to fetch the stream from the context %v", ctx) + } + t := stream.ServerTransport() + if t == nil { + grpclog.Fatalf("grpc: SendHeader: %v has no ServerTransport to send header metadata.", stream) + } + return t.WriteHeader(stream, md) +} + +// SetTrailer sets the trailer metadata that will be sent when an RPC returns. +// It may be called at most once from a unary RPC handler. The ctx is the RPC +// handler's Context or one derived from it. +func SetTrailer(ctx context.Context, md metadata.MD) error { + if md.Len() == 0 { + return nil + } + stream, ok := transport.StreamFromContext(ctx) + if !ok { + return fmt.Errorf("grpc: failed to fetch the stream from the context %v", ctx) + } + return stream.SetTrailer(md) +} diff --git a/vendor/google.golang.org/grpc/server_test.go b/vendor/google.golang.org/grpc/server_test.go new file mode 100644 index 00000000..eb598a51 --- /dev/null +++ b/vendor/google.golang.org/grpc/server_test.go @@ -0,0 +1,113 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "net" + "reflect" + "strings" + "testing" +) + +type emptyServiceServer interface{} + +type testServer struct{} + +func TestStopBeforeServe(t *testing.T) { + lis, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("failed to create listener: %v", err) + } + + server := NewServer() + server.Stop() + err = server.Serve(lis) + if err != ErrServerStopped { + t.Fatalf("server.Serve() error = %v, want %v", err, ErrServerStopped) + } + + // server.Serve is responsible for closing the listener, even if the + // server was already stopped. + err = lis.Close() + if got, want := ErrorDesc(err), "use of closed network connection"; !strings.Contains(got, want) { + t.Errorf("Close() error = %q, want %q", got, want) + } +} + +func TestGetServiceInfo(t *testing.T) { + testSd := ServiceDesc{ + ServiceName: "grpc.testing.EmptyService", + HandlerType: (*emptyServiceServer)(nil), + Methods: []MethodDesc{ + { + MethodName: "EmptyCall", + Handler: nil, + }, + }, + Streams: []StreamDesc{ + { + StreamName: "EmptyStream", + Handler: nil, + ServerStreams: false, + ClientStreams: true, + }, + }, + Metadata: []int{0, 2, 1, 3}, + } + + server := NewServer() + server.RegisterService(&testSd, &testServer{}) + + info := server.GetServiceInfo() + want := map[string]*ServiceInfo{ + "grpc.testing.EmptyService": &ServiceInfo{ + Methods: []MethodInfo{ + MethodInfo{ + Name: "EmptyCall", + IsClientStream: false, + IsServerStream: false, + }, + MethodInfo{ + Name: "EmptyStream", + IsClientStream: true, + IsServerStream: false, + }}, + Metadata: []int{0, 2, 1, 3}, + }, + } + + if !reflect.DeepEqual(info, want) { + t.Errorf("GetServiceInfo() = %q, want %q", info, want) + } +} diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go new file mode 100644 index 00000000..7a3bef51 --- /dev/null +++ b/vendor/google.golang.org/grpc/stream.go @@ -0,0 +1,462 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "errors" + "io" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/transport" +) + +// StreamHandler defines the handler called by gRPC server to complete the +// execution of a streaming RPC. +type StreamHandler func(srv interface{}, stream ServerStream) error + +// StreamDesc represents a streaming RPC service's method specification. +type StreamDesc struct { + StreamName string + Handler StreamHandler + + // At least one of these is true. + ServerStreams bool + ClientStreams bool +} + +// Stream defines the common interface a client or server stream has to satisfy. +type Stream interface { + // Context returns the context for this stream. + Context() context.Context + // SendMsg blocks until it sends m, the stream is done or the stream + // breaks. + // On error, it aborts the stream and returns an RPC status on client + // side. On server side, it simply returns the error to the caller. + // SendMsg is called by generated code. Also Users can call SendMsg + // directly when it is really needed in their use cases. + SendMsg(m interface{}) error + // RecvMsg blocks until it receives a message or the stream is + // done. On client side, it returns io.EOF when the stream is done. On + // any other error, it aborts the stream and returns an RPC status. On + // server side, it simply returns the error to the caller. + RecvMsg(m interface{}) error +} + +// ClientStream defines the interface a client stream has to satisfy. +type ClientStream interface { + // Header returns the header metadata received from the server if there + // is any. It blocks if the metadata is not ready to read. + Header() (metadata.MD, error) + // Trailer returns the trailer metadata from the server. It must be called + // after stream.Recv() returns non-nil error (including io.EOF) for + // bi-directional streaming and server streaming or stream.CloseAndRecv() + // returns for client streaming in order to receive trailer metadata if + // present. Otherwise, it could returns an empty MD even though trailer + // is present. + Trailer() metadata.MD + // CloseSend closes the send direction of the stream. It closes the stream + // when non-nil error is met. + CloseSend() error + Stream +} + +// NewClientStream creates a new Stream for the client side. This is called +// by generated code. +func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) { + var ( + t transport.ClientTransport + s *transport.Stream + err error + put func() + ) + c := defaultCallInfo + for _, o := range opts { + if err := o.before(&c); err != nil { + return nil, toRPCErr(err) + } + } + callHdr := &transport.CallHdr{ + Host: cc.authority, + Method: method, + Flush: desc.ServerStreams && desc.ClientStreams, + } + if cc.dopts.cp != nil { + callHdr.SendCompress = cc.dopts.cp.Type() + } + cs := &clientStream{ + opts: opts, + c: c, + desc: desc, + codec: cc.dopts.codec, + cp: cc.dopts.cp, + dc: cc.dopts.dc, + tracing: EnableTracing, + } + if cc.dopts.cp != nil { + callHdr.SendCompress = cc.dopts.cp.Type() + cs.cbuf = new(bytes.Buffer) + } + if cs.tracing { + cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) + cs.trInfo.firstLine.client = true + if deadline, ok := ctx.Deadline(); ok { + cs.trInfo.firstLine.deadline = deadline.Sub(time.Now()) + } + cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false) + ctx = trace.NewContext(ctx, cs.trInfo.tr) + } + gopts := BalancerGetOptions{ + BlockingWait: !c.failFast, + } + for { + t, put, err = cc.getTransport(ctx, gopts) + if err != nil { + // TODO(zhaoq): Probably revisit the error handling. + if _, ok := err.(*rpcError); ok { + return nil, err + } + if err == errConnClosing { + if c.failFast { + return nil, Errorf(codes.Unavailable, "%v", errConnClosing) + } + continue + } + // All the other errors are treated as Internal errors. + return nil, Errorf(codes.Internal, "%v", err) + } + + s, err = t.NewStream(ctx, callHdr) + if err != nil { + if put != nil { + put() + put = nil + } + if _, ok := err.(transport.ConnectionError); ok { + if c.failFast { + cs.finish(err) + return nil, toRPCErr(err) + } + continue + } + return nil, toRPCErr(err) + } + break + } + cs.put = put + cs.t = t + cs.s = s + cs.p = &parser{r: s} + // Listen on ctx.Done() to detect cancellation when there is no pending + // I/O operations on this stream. + go func() { + select { + case <-t.Error(): + // Incur transport error, simply exit. + case <-s.Context().Done(): + err := s.Context().Err() + cs.finish(err) + cs.closeTransportStream(transport.ContextErr(err)) + } + }() + return cs, nil +} + +// clientStream implements a client side Stream. +type clientStream struct { + opts []CallOption + c callInfo + t transport.ClientTransport + s *transport.Stream + p *parser + desc *StreamDesc + codec Codec + cp Compressor + cbuf *bytes.Buffer + dc Decompressor + + tracing bool // set to EnableTracing when the clientStream is created. + + mu sync.Mutex + put func() + closed bool + // trInfo.tr is set when the clientStream is created (if EnableTracing is true), + // and is set to nil when the clientStream's finish method is called. + trInfo traceInfo +} + +func (cs *clientStream) Context() context.Context { + return cs.s.Context() +} + +func (cs *clientStream) Header() (metadata.MD, error) { + m, err := cs.s.Header() + if err != nil { + if _, ok := err.(transport.ConnectionError); !ok { + cs.closeTransportStream(err) + } + } + return m, err +} + +func (cs *clientStream) Trailer() metadata.MD { + return cs.s.Trailer() +} + +func (cs *clientStream) SendMsg(m interface{}) (err error) { + if cs.tracing { + cs.mu.Lock() + if cs.trInfo.tr != nil { + cs.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) + } + cs.mu.Unlock() + } + defer func() { + if err != nil { + cs.finish(err) + } + if err == nil || err == io.EOF { + return + } + if _, ok := err.(transport.ConnectionError); !ok { + cs.closeTransportStream(err) + } + err = toRPCErr(err) + }() + out, err := encode(cs.codec, m, cs.cp, cs.cbuf) + defer func() { + if cs.cbuf != nil { + cs.cbuf.Reset() + } + }() + if err != nil { + return transport.StreamErrorf(codes.Internal, "grpc: %v", err) + } + return cs.t.Write(cs.s, out, &transport.Options{Last: false}) +} + +func (cs *clientStream) RecvMsg(m interface{}) (err error) { + err = recv(cs.p, cs.codec, cs.s, cs.dc, m) + defer func() { + // err != nil indicates the termination of the stream. + if err != nil { + cs.finish(err) + } + }() + if err == nil { + if cs.tracing { + cs.mu.Lock() + if cs.trInfo.tr != nil { + cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) + } + cs.mu.Unlock() + } + if !cs.desc.ClientStreams || cs.desc.ServerStreams { + return + } + // Special handling for client streaming rpc. + err = recv(cs.p, cs.codec, cs.s, cs.dc, m) + cs.closeTransportStream(err) + if err == nil { + return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) + } + if err == io.EOF { + if cs.s.StatusCode() == codes.OK { + cs.finish(err) + return nil + } + return Errorf(cs.s.StatusCode(), "%s", cs.s.StatusDesc()) + } + return toRPCErr(err) + } + if _, ok := err.(transport.ConnectionError); !ok { + cs.closeTransportStream(err) + } + if err == io.EOF { + if cs.s.StatusCode() == codes.OK { + // Returns io.EOF to indicate the end of the stream. + return + } + return Errorf(cs.s.StatusCode(), "%s", cs.s.StatusDesc()) + } + return toRPCErr(err) +} + +func (cs *clientStream) CloseSend() (err error) { + err = cs.t.Write(cs.s, nil, &transport.Options{Last: true}) + defer func() { + if err != nil { + cs.finish(err) + } + }() + if err == nil || err == io.EOF { + return + } + if _, ok := err.(transport.ConnectionError); !ok { + cs.closeTransportStream(err) + } + err = toRPCErr(err) + return +} + +func (cs *clientStream) closeTransportStream(err error) { + cs.mu.Lock() + if cs.closed { + cs.mu.Unlock() + return + } + cs.closed = true + cs.mu.Unlock() + cs.t.CloseStream(cs.s, err) +} + +func (cs *clientStream) finish(err error) { + cs.mu.Lock() + defer cs.mu.Unlock() + for _, o := range cs.opts { + o.after(&cs.c) + } + if cs.put != nil { + cs.put() + cs.put = nil + } + if !cs.tracing { + return + } + if cs.trInfo.tr != nil { + if err == nil || err == io.EOF { + cs.trInfo.tr.LazyPrintf("RPC: [OK]") + } else { + cs.trInfo.tr.LazyPrintf("RPC: [%v]", err) + cs.trInfo.tr.SetError() + } + cs.trInfo.tr.Finish() + cs.trInfo.tr = nil + } +} + +// ServerStream defines the interface a server stream has to satisfy. +type ServerStream interface { + // SendHeader sends the header metadata. It should not be called + // after SendProto. It fails if called multiple times or if + // called after SendProto. + SendHeader(metadata.MD) error + // SetTrailer sets the trailer metadata which will be sent with the + // RPC status. + SetTrailer(metadata.MD) + Stream +} + +// serverStream implements a server side Stream. +type serverStream struct { + t transport.ServerTransport + s *transport.Stream + p *parser + codec Codec + cp Compressor + dc Decompressor + cbuf *bytes.Buffer + statusCode codes.Code + statusDesc string + trInfo *traceInfo + + mu sync.Mutex // protects trInfo.tr after the service handler runs. +} + +func (ss *serverStream) Context() context.Context { + return ss.s.Context() +} + +func (ss *serverStream) SendHeader(md metadata.MD) error { + return ss.t.WriteHeader(ss.s, md) +} + +func (ss *serverStream) SetTrailer(md metadata.MD) { + if md.Len() == 0 { + return + } + ss.s.SetTrailer(md) + return +} + +func (ss *serverStream) SendMsg(m interface{}) (err error) { + defer func() { + if ss.trInfo != nil { + ss.mu.Lock() + if ss.trInfo.tr != nil { + if err == nil { + ss.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) + } else { + ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + ss.trInfo.tr.SetError() + } + } + ss.mu.Unlock() + } + }() + out, err := encode(ss.codec, m, ss.cp, ss.cbuf) + defer func() { + if ss.cbuf != nil { + ss.cbuf.Reset() + } + }() + if err != nil { + err = transport.StreamErrorf(codes.Internal, "grpc: %v", err) + return err + } + return ss.t.Write(ss.s, out, &transport.Options{Last: false}) +} + +func (ss *serverStream) RecvMsg(m interface{}) (err error) { + defer func() { + if ss.trInfo != nil { + ss.mu.Lock() + if ss.trInfo.tr != nil { + if err == nil { + ss.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) + } else if err != io.EOF { + ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + ss.trInfo.tr.SetError() + } + } + ss.mu.Unlock() + } + }() + return recv(ss.p, ss.codec, ss.s, ss.dc, m) +} diff --git a/vendor/google.golang.org/grpc/stress/client/main.go b/vendor/google.golang.org/grpc/stress/client/main.go new file mode 100644 index 00000000..4579aab4 --- /dev/null +++ b/vendor/google.golang.org/grpc/stress/client/main.go @@ -0,0 +1,298 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// client starts an interop client to do stress test and a metrics server to report qps. +package main + +import ( + "flag" + "fmt" + "math/rand" + "net" + "strconv" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/interop" + testpb "google.golang.org/grpc/interop/grpc_testing" + metricspb "google.golang.org/grpc/stress/grpc_testing" +) + +var ( + serverAddresses = flag.String("server_addresses", "localhost:8080", "a list of server addresses") + testCases = flag.String("test_cases", "", "a list of test cases along with the relative weights") + testDurationSecs = flag.Int("test_duration_secs", -1, "test duration in seconds") + numChannelsPerServer = flag.Int("num_channels_per_server", 1, "Number of channels (i.e connections) to each server") + numStubsPerChannel = flag.Int("num_stubs_per_channel", 1, "Number of client stubs per each connection to server") + metricsPort = flag.Int("metrics_port", 8081, "The port at which the stress client exposes QPS metrics") +) + +// testCaseWithWeight contains the test case type and its weight. +type testCaseWithWeight struct { + name string + weight int +} + +// parseTestCases converts test case string to a list of struct testCaseWithWeight. +func parseTestCases(testCaseString string) []testCaseWithWeight { + testCaseStrings := strings.Split(testCaseString, ",") + testCases := make([]testCaseWithWeight, len(testCaseStrings)) + for i, str := range testCaseStrings { + testCase := strings.Split(str, ":") + if len(testCase) != 2 { + panic(fmt.Sprintf("invalid test case with weight: %s", str)) + } + // Check if test case is supported. + switch testCase[0] { + case + "empty_unary", + "large_unary", + "client_streaming", + "server_streaming", + "empty_stream": + default: + panic(fmt.Sprintf("unknown test type: %s", testCase[0])) + } + testCases[i].name = testCase[0] + w, err := strconv.Atoi(testCase[1]) + if err != nil { + panic(fmt.Sprintf("%v", err)) + } + testCases[i].weight = w + } + return testCases +} + +// weightedRandomTestSelector defines a weighted random selector for test case types. +type weightedRandomTestSelector struct { + tests []testCaseWithWeight + totalWeight int +} + +// newWeightedRandomTestSelector constructs a weightedRandomTestSelector with the given list of testCaseWithWeight. +func newWeightedRandomTestSelector(tests []testCaseWithWeight) *weightedRandomTestSelector { + var totalWeight int + for _, t := range tests { + totalWeight += t.weight + } + rand.Seed(time.Now().UnixNano()) + return &weightedRandomTestSelector{tests, totalWeight} +} + +func (selector weightedRandomTestSelector) getNextTest() string { + random := rand.Intn(selector.totalWeight) + var weightSofar int + for _, test := range selector.tests { + weightSofar += test.weight + if random < weightSofar { + return test.name + } + } + panic("no test case selected by weightedRandomTestSelector") +} + +// gauge stores the qps of one interop client (one stub). +type gauge struct { + mutex sync.RWMutex + val int64 +} + +func (g *gauge) set(v int64) { + g.mutex.Lock() + defer g.mutex.Unlock() + g.val = v +} + +func (g *gauge) get() int64 { + g.mutex.RLock() + defer g.mutex.RUnlock() + return g.val +} + +// server implements metrics server functions. +type server struct { + mutex sync.RWMutex + // gauges is a map from /stress_test/server_/channel_/stub_/qps to its qps gauge. + gauges map[string]*gauge +} + +// newMetricsServer returns a new metrics server. +func newMetricsServer() *server { + return &server{gauges: make(map[string]*gauge)} +} + +// GetAllGauges returns all gauges. +func (s *server) GetAllGauges(in *metricspb.EmptyMessage, stream metricspb.MetricsService_GetAllGaugesServer) error { + s.mutex.RLock() + defer s.mutex.RUnlock() + + for name, gauge := range s.gauges { + if err := stream.Send(&metricspb.GaugeResponse{Name: name, Value: &metricspb.GaugeResponse_LongValue{LongValue: gauge.get()}}); err != nil { + return err + } + } + return nil +} + +// GetGauge returns the gauge for the given name. +func (s *server) GetGauge(ctx context.Context, in *metricspb.GaugeRequest) (*metricspb.GaugeResponse, error) { + s.mutex.RLock() + defer s.mutex.RUnlock() + + if g, ok := s.gauges[in.Name]; ok { + return &metricspb.GaugeResponse{Name: in.Name, Value: &metricspb.GaugeResponse_LongValue{LongValue: g.get()}}, nil + } + return nil, grpc.Errorf(codes.InvalidArgument, "gauge with name %s not found", in.Name) +} + +// createGauge creates a guage using the given name in metrics server. +func (s *server) createGauge(name string) *gauge { + s.mutex.Lock() + defer s.mutex.Unlock() + + if _, ok := s.gauges[name]; ok { + // gauge already exists. + panic(fmt.Sprintf("gauge %s already exists", name)) + } + var g gauge + s.gauges[name] = &g + return &g +} + +func startServer(server *server, port int) { + lis, err := net.Listen("tcp", ":"+strconv.Itoa(port)) + if err != nil { + grpclog.Fatalf("failed to listen: %v", err) + } + + s := grpc.NewServer() + metricspb.RegisterMetricsServiceServer(s, server) + s.Serve(lis) + +} + +// performRPCs uses weightedRandomTestSelector to select test case and runs the tests. +func performRPCs(gauge *gauge, conn *grpc.ClientConn, selector *weightedRandomTestSelector, stop <-chan bool) { + client := testpb.NewTestServiceClient(conn) + var numCalls int64 + startTime := time.Now() + for { + done := make(chan bool, 1) + go func() { + test := selector.getNextTest() + switch test { + case "empty_unary": + interop.DoEmptyUnaryCall(client) + case "large_unary": + interop.DoLargeUnaryCall(client) + case "client_streaming": + interop.DoClientStreaming(client) + case "server_streaming": + interop.DoServerStreaming(client) + case "empty_stream": + interop.DoEmptyStream(client) + } + done <- true + }() + select { + case <-stop: + return + case <-done: + numCalls++ + gauge.set(int64(float64(numCalls) / time.Since(startTime).Seconds())) + } + } +} + +func logParameterInfo(addresses []string, tests []testCaseWithWeight) { + grpclog.Printf("server_addresses: %s", *serverAddresses) + grpclog.Printf("test_cases: %s", *testCases) + grpclog.Printf("test_duration-secs: %d", *testDurationSecs) + grpclog.Printf("num_channels_per_server: %d", *numChannelsPerServer) + grpclog.Printf("num_stubs_per_channel: %d", *numStubsPerChannel) + grpclog.Printf("metrics_port: %d", *metricsPort) + + grpclog.Println("addresses:") + for i, addr := range addresses { + grpclog.Printf("%d. %s\n", i+1, addr) + } + grpclog.Println("tests:") + for i, test := range tests { + grpclog.Printf("%d. %v\n", i+1, test) + } +} + +func main() { + flag.Parse() + addresses := strings.Split(*serverAddresses, ",") + tests := parseTestCases(*testCases) + logParameterInfo(addresses, tests) + testSelector := newWeightedRandomTestSelector(tests) + metricsServer := newMetricsServer() + + var wg sync.WaitGroup + wg.Add(len(addresses) * *numChannelsPerServer * *numStubsPerChannel) + stop := make(chan bool) + + for serverIndex, address := range addresses { + for connIndex := 0; connIndex < *numChannelsPerServer; connIndex++ { + conn, err := grpc.Dial(address, grpc.WithInsecure()) + if err != nil { + grpclog.Fatalf("Fail to dial: %v", err) + } + defer conn.Close() + for clientIndex := 0; clientIndex < *numStubsPerChannel; clientIndex++ { + name := fmt.Sprintf("/stress_test/server_%d/channel_%d/stub_%d/qps", serverIndex+1, connIndex+1, clientIndex+1) + go func() { + defer wg.Done() + g := metricsServer.createGauge(name) + performRPCs(g, conn, testSelector, stop) + }() + } + + } + } + go startServer(metricsServer, *metricsPort) + if *testDurationSecs > 0 { + time.Sleep(time.Duration(*testDurationSecs) * time.Second) + close(stop) + } + wg.Wait() + grpclog.Printf(" ===== ALL DONE ===== ") + +} diff --git a/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.pb.go b/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.pb.go new file mode 100644 index 00000000..4ad4ccdb --- /dev/null +++ b/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.pb.go @@ -0,0 +1,361 @@ +// Code generated by protoc-gen-go. +// source: metrics.proto +// DO NOT EDIT! + +/* +Package grpc_testing is a generated protocol buffer package. + +It is generated from these files: + metrics.proto + +It has these top-level messages: + GaugeResponse + GaugeRequest + EmptyMessage +*/ +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Reponse message containing the gauge name and value +type GaugeResponse struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Types that are valid to be assigned to Value: + // *GaugeResponse_LongValue + // *GaugeResponse_DoubleValue + // *GaugeResponse_StringValue + Value isGaugeResponse_Value `protobuf_oneof:"value"` +} + +func (m *GaugeResponse) Reset() { *m = GaugeResponse{} } +func (m *GaugeResponse) String() string { return proto.CompactTextString(m) } +func (*GaugeResponse) ProtoMessage() {} +func (*GaugeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type isGaugeResponse_Value interface { + isGaugeResponse_Value() +} + +type GaugeResponse_LongValue struct { + LongValue int64 `protobuf:"varint,2,opt,name=long_value,json=longValue,oneof"` +} +type GaugeResponse_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,3,opt,name=double_value,json=doubleValue,oneof"` +} +type GaugeResponse_StringValue struct { + StringValue string `protobuf:"bytes,4,opt,name=string_value,json=stringValue,oneof"` +} + +func (*GaugeResponse_LongValue) isGaugeResponse_Value() {} +func (*GaugeResponse_DoubleValue) isGaugeResponse_Value() {} +func (*GaugeResponse_StringValue) isGaugeResponse_Value() {} + +func (m *GaugeResponse) GetValue() isGaugeResponse_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *GaugeResponse) GetLongValue() int64 { + if x, ok := m.GetValue().(*GaugeResponse_LongValue); ok { + return x.LongValue + } + return 0 +} + +func (m *GaugeResponse) GetDoubleValue() float64 { + if x, ok := m.GetValue().(*GaugeResponse_DoubleValue); ok { + return x.DoubleValue + } + return 0 +} + +func (m *GaugeResponse) GetStringValue() string { + if x, ok := m.GetValue().(*GaugeResponse_StringValue); ok { + return x.StringValue + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*GaugeResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _GaugeResponse_OneofMarshaler, _GaugeResponse_OneofUnmarshaler, _GaugeResponse_OneofSizer, []interface{}{ + (*GaugeResponse_LongValue)(nil), + (*GaugeResponse_DoubleValue)(nil), + (*GaugeResponse_StringValue)(nil), + } +} + +func _GaugeResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*GaugeResponse) + // value + switch x := m.Value.(type) { + case *GaugeResponse_LongValue: + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.LongValue)) + case *GaugeResponse_DoubleValue: + b.EncodeVarint(3<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.DoubleValue)) + case *GaugeResponse_StringValue: + b.EncodeVarint(4<<3 | proto.WireBytes) + b.EncodeStringBytes(x.StringValue) + case nil: + default: + return fmt.Errorf("GaugeResponse.Value has unexpected type %T", x) + } + return nil +} + +func _GaugeResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*GaugeResponse) + switch tag { + case 2: // value.long_value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Value = &GaugeResponse_LongValue{int64(x)} + return true, err + case 3: // value.double_value + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Value = &GaugeResponse_DoubleValue{math.Float64frombits(x)} + return true, err + case 4: // value.string_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Value = &GaugeResponse_StringValue{x} + return true, err + default: + return false, nil + } +} + +func _GaugeResponse_OneofSizer(msg proto.Message) (n int) { + m := msg.(*GaugeResponse) + // value + switch x := m.Value.(type) { + case *GaugeResponse_LongValue: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.LongValue)) + case *GaugeResponse_DoubleValue: + n += proto.SizeVarint(3<<3 | proto.WireFixed64) + n += 8 + case *GaugeResponse_StringValue: + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.StringValue))) + n += len(x.StringValue) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Request message containing the gauge name +type GaugeRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GaugeRequest) Reset() { *m = GaugeRequest{} } +func (m *GaugeRequest) String() string { return proto.CompactTextString(m) } +func (*GaugeRequest) ProtoMessage() {} +func (*GaugeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type EmptyMessage struct { +} + +func (m *EmptyMessage) Reset() { *m = EmptyMessage{} } +func (m *EmptyMessage) String() string { return proto.CompactTextString(m) } +func (*EmptyMessage) ProtoMessage() {} +func (*EmptyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func init() { + proto.RegisterType((*GaugeResponse)(nil), "grpc.testing.GaugeResponse") + proto.RegisterType((*GaugeRequest)(nil), "grpc.testing.GaugeRequest") + proto.RegisterType((*EmptyMessage)(nil), "grpc.testing.EmptyMessage") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for MetricsService service + +type MetricsServiceClient interface { + // Returns the values of all the gauges that are currently being maintained by + // the service + GetAllGauges(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (MetricsService_GetAllGaugesClient, error) + // Returns the value of one gauge + GetGauge(ctx context.Context, in *GaugeRequest, opts ...grpc.CallOption) (*GaugeResponse, error) +} + +type metricsServiceClient struct { + cc *grpc.ClientConn +} + +func NewMetricsServiceClient(cc *grpc.ClientConn) MetricsServiceClient { + return &metricsServiceClient{cc} +} + +func (c *metricsServiceClient) GetAllGauges(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (MetricsService_GetAllGaugesClient, error) { + stream, err := grpc.NewClientStream(ctx, &_MetricsService_serviceDesc.Streams[0], c.cc, "/grpc.testing.MetricsService/GetAllGauges", opts...) + if err != nil { + return nil, err + } + x := &metricsServiceGetAllGaugesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type MetricsService_GetAllGaugesClient interface { + Recv() (*GaugeResponse, error) + grpc.ClientStream +} + +type metricsServiceGetAllGaugesClient struct { + grpc.ClientStream +} + +func (x *metricsServiceGetAllGaugesClient) Recv() (*GaugeResponse, error) { + m := new(GaugeResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *metricsServiceClient) GetGauge(ctx context.Context, in *GaugeRequest, opts ...grpc.CallOption) (*GaugeResponse, error) { + out := new(GaugeResponse) + err := grpc.Invoke(ctx, "/grpc.testing.MetricsService/GetGauge", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for MetricsService service + +type MetricsServiceServer interface { + // Returns the values of all the gauges that are currently being maintained by + // the service + GetAllGauges(*EmptyMessage, MetricsService_GetAllGaugesServer) error + // Returns the value of one gauge + GetGauge(context.Context, *GaugeRequest) (*GaugeResponse, error) +} + +func RegisterMetricsServiceServer(s *grpc.Server, srv MetricsServiceServer) { + s.RegisterService(&_MetricsService_serviceDesc, srv) +} + +func _MetricsService_GetAllGauges_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(EmptyMessage) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MetricsServiceServer).GetAllGauges(m, &metricsServiceGetAllGaugesServer{stream}) +} + +type MetricsService_GetAllGaugesServer interface { + Send(*GaugeResponse) error + grpc.ServerStream +} + +type metricsServiceGetAllGaugesServer struct { + grpc.ServerStream +} + +func (x *metricsServiceGetAllGaugesServer) Send(m *GaugeResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _MetricsService_GetGauge_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GaugeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MetricsServiceServer).GetGauge(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.MetricsService/GetGauge", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MetricsServiceServer).GetGauge(ctx, req.(*GaugeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _MetricsService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.MetricsService", + HandlerType: (*MetricsServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetGauge", + Handler: _MetricsService_GetGauge_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetAllGauges", + Handler: _MetricsService_GetAllGauges_Handler, + ServerStreams: true, + }, + }, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("metrics.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 253 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x29, + 0xca, 0x4c, 0x2e, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x49, 0x2f, 0x2a, 0x48, 0xd6, + 0x2b, 0x49, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0x57, 0x9a, 0xce, 0xc8, 0xc5, 0xeb, 0x9e, 0x58, 0x9a, + 0x9e, 0x1a, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x2a, 0x24, 0xc4, 0xc5, 0x92, 0x97, 0x98, + 0x9b, 0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0x66, 0x0b, 0xc9, 0x73, 0x71, 0xe5, 0xe4, + 0xe7, 0xa5, 0xc7, 0x97, 0x25, 0xe6, 0x94, 0xa6, 0x4a, 0x30, 0x01, 0x65, 0x98, 0x3d, 0x18, 0x82, + 0x38, 0x41, 0x62, 0x61, 0x20, 0x21, 0x21, 0x65, 0x2e, 0x9e, 0x94, 0xfc, 0xd2, 0xa4, 0x9c, 0x54, + 0xa8, 0x12, 0x66, 0xa0, 0x12, 0x46, 0xa0, 0x12, 0x6e, 0x88, 0x28, 0x5c, 0x51, 0x31, 0xd0, 0x25, + 0x70, 0x73, 0x58, 0x40, 0x36, 0x80, 0x14, 0x41, 0x44, 0xc1, 0x8a, 0x9c, 0xd8, 0xb9, 0x58, 0xc1, + 0xb2, 0x4a, 0x4a, 0x5c, 0x3c, 0x50, 0x87, 0x15, 0x96, 0x02, 0x1d, 0x8b, 0xcd, 0x5d, 0x4a, 0x7c, + 0x5c, 0x3c, 0xae, 0xb9, 0x05, 0x25, 0x95, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x46, 0x0b, + 0x18, 0xb9, 0xf8, 0x7c, 0x21, 0xbe, 0x0d, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x15, 0xf2, 0x04, + 0x1a, 0x93, 0x5a, 0xe2, 0x98, 0x93, 0x03, 0x36, 0xac, 0x58, 0x48, 0x4a, 0x0f, 0xd9, 0xff, 0x7a, + 0xc8, 0xda, 0xa5, 0xa4, 0x51, 0xe5, 0x50, 0xc2, 0xc5, 0x80, 0x51, 0xc8, 0x99, 0x8b, 0x03, 0x68, + 0x14, 0x58, 0x14, 0xdd, 0x18, 0x64, 0x97, 0xe2, 0x35, 0x26, 0x89, 0x0d, 0x1c, 0x0b, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x5e, 0x7d, 0xb2, 0xc9, 0x96, 0x01, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.proto b/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.proto new file mode 100644 index 00000000..1202b20b --- /dev/null +++ b/vendor/google.golang.org/grpc/stress/grpc_testing/metrics.proto @@ -0,0 +1,64 @@ +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Contains the definitions for a metrics service and the type of metrics +// exposed by the service. +// +// Currently, 'Gauge' (i.e a metric that represents the measured value of +// something at an instant of time) is the only metric type supported by the +// service. +syntax = "proto3"; + +package grpc.testing; + +// Reponse message containing the gauge name and value +message GaugeResponse { + string name = 1; + oneof value { + int64 long_value = 2; + double double_value = 3; + string string_value = 4; + } +} + +// Request message containing the gauge name +message GaugeRequest { + string name = 1; +} + +message EmptyMessage {} + +service MetricsService { + // Returns the values of all the gauges that are currently being maintained by + // the service + rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse); + + // Returns the value of one gauge + rpc GetGauge(GaugeRequest) returns (GaugeResponse); +} diff --git a/vendor/google.golang.org/grpc/stress/metrics_client/main.go b/vendor/google.golang.org/grpc/stress/metrics_client/main.go new file mode 100644 index 00000000..983a8ff2 --- /dev/null +++ b/vendor/google.golang.org/grpc/stress/metrics_client/main.go @@ -0,0 +1,97 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "flag" + "fmt" + "io" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/grpclog" + metricspb "google.golang.org/grpc/stress/grpc_testing" +) + +var ( + metricsServerAddress = flag.String("metrics_server_address", "", "The metrics server addresses in the fomrat :") + totalOnly = flag.Bool("total_only", false, "If true, this prints only the total value of all gauges") +) + +func printMetrics(client metricspb.MetricsServiceClient, totalOnly bool) { + stream, err := client.GetAllGauges(context.Background(), &metricspb.EmptyMessage{}) + if err != nil { + grpclog.Fatalf("failed to call GetAllGuages: %v", err) + } + + var ( + overallQPS int64 + rpcStatus error + ) + for { + gaugeResponse, err := stream.Recv() + if err != nil { + rpcStatus = err + break + } + if _, ok := gaugeResponse.GetValue().(*metricspb.GaugeResponse_LongValue); !ok { + panic(fmt.Sprintf("gauge %s is not a long value", gaugeResponse.Name)) + } + v := gaugeResponse.GetLongValue() + if !totalOnly { + grpclog.Printf("%s: %d", gaugeResponse.Name, v) + } + overallQPS += v + } + if rpcStatus != io.EOF { + grpclog.Fatalf("failed to finish server streaming: %v", rpcStatus) + } + grpclog.Printf("overall qps: %d", overallQPS) +} + +func main() { + flag.Parse() + if *metricsServerAddress == "" { + grpclog.Fatalf("Metrics server address is empty.") + } + + conn, err := grpc.Dial(*metricsServerAddress, grpc.WithInsecure()) + if err != nil { + grpclog.Fatalf("cannot connect to metrics server: %v", err) + } + defer conn.Close() + + c := metricspb.NewMetricsServiceClient(conn) + printMetrics(c, *totalOnly) +} diff --git a/vendor/google.golang.org/grpc/test/codec_perf/perf.pb.go b/vendor/google.golang.org/grpc/test/codec_perf/perf.pb.go new file mode 100644 index 00000000..c88756ed --- /dev/null +++ b/vendor/google.golang.org/grpc/test/codec_perf/perf.pb.go @@ -0,0 +1,63 @@ +// Code generated by protoc-gen-go. +// source: perf.proto +// DO NOT EDIT! + +/* +Package codec_perf is a generated protocol buffer package. + +It is generated from these files: + perf.proto + +It has these top-level messages: + Buffer +*/ +package codec_perf + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Buffer is a message that contains a body of bytes that is used to exercise +// encoding and decoding overheads. +type Buffer struct { + Body []byte `protobuf:"bytes,1,opt,name=body" json:"body,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Buffer) Reset() { *m = Buffer{} } +func (m *Buffer) String() string { return proto.CompactTextString(m) } +func (*Buffer) ProtoMessage() {} +func (*Buffer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Buffer) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +func init() { + proto.RegisterType((*Buffer)(nil), "codec.perf.Buffer") +} + +func init() { proto.RegisterFile("perf.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 73 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x48, 0x2d, 0x4a, + 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4a, 0xce, 0x4f, 0x49, 0x4d, 0xd6, 0x03, 0x89, + 0x28, 0xc9, 0x70, 0xb1, 0x39, 0x95, 0xa6, 0xa5, 0xa5, 0x16, 0x09, 0x09, 0x71, 0xb1, 0x24, 0xe5, + 0xa7, 0x54, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0xd9, 0x80, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x3a, 0x58, 0x92, 0x53, 0x36, 0x00, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/test/codec_perf/perf.proto b/vendor/google.golang.org/grpc/test/codec_perf/perf.proto new file mode 100644 index 00000000..4cf561f7 --- /dev/null +++ b/vendor/google.golang.org/grpc/test/codec_perf/perf.proto @@ -0,0 +1,11 @@ +// Messages used for performance tests that may not reference grpc directly for +// reasons of import cycles. +syntax = "proto2"; + +package codec.perf; + +// Buffer is a message that contains a body of bytes that is used to exercise +// encoding and decoding overheads. +message Buffer { + optional bytes body = 1; +} diff --git a/vendor/google.golang.org/grpc/test/end2end_test.go b/vendor/google.golang.org/grpc/test/end2end_test.go new file mode 100644 index 00000000..cc8bae5f --- /dev/null +++ b/vendor/google.golang.org/grpc/test/end2end_test.go @@ -0,0 +1,2133 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc_test + +import ( + "bytes" + "crypto/tls" + "errors" + "flag" + "fmt" + "io" + "log" + "math" + "net" + "os" + "reflect" + "runtime" + "sort" + "strings" + "sync" + "syscall" + "testing" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + "golang.org/x/net/http2" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/health" + healthpb "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/internal" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" + testpb "google.golang.org/grpc/test/grpc_testing" + "google.golang.org/grpc/transport" +) + +var ( + // For headers: + testMetadata = metadata.MD{ + "key1": []string{"value1"}, + "key2": []string{"value2"}, + } + // For trailers: + testTrailerMetadata = metadata.MD{ + "tkey1": []string{"trailerValue1"}, + "tkey2": []string{"trailerValue2"}, + } + // capital "Key" is illegal in HTTP/2. + malformedHTTP2Metadata = metadata.MD{ + "Key": []string{"foo"}, + } + testAppUA = "myApp1/1.0 myApp2/0.9" +) + +var raceMode bool // set by race_test.go in race mode + +type testServer struct { + security string // indicate the authentication protocol used by this server. +} + +func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { + if md, ok := metadata.FromContext(ctx); ok { + // For testing purpose, returns an error if there is attached metadata other than + // the user agent set by the client application. + if _, ok := md["user-agent"]; !ok { + return nil, grpc.Errorf(codes.DataLoss, "missing expected user-agent") + } + var str []string + for _, entry := range md["user-agent"] { + str = append(str, "ua", entry) + } + grpc.SendHeader(ctx, metadata.Pairs(str...)) + } + return new(testpb.Empty), nil +} + +func newPayload(t testpb.PayloadType, size int32) (*testpb.Payload, error) { + if size < 0 { + return nil, fmt.Errorf("Requested a response with invalid length %d", size) + } + body := make([]byte, size) + switch t { + case testpb.PayloadType_COMPRESSABLE: + case testpb.PayloadType_UNCOMPRESSABLE: + return nil, fmt.Errorf("PayloadType UNCOMPRESSABLE is not supported") + default: + return nil, fmt.Errorf("Unsupported payload type: %d", t) + } + return &testpb.Payload{ + Type: t.Enum(), + Body: body, + }, nil +} + +func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + md, ok := metadata.FromContext(ctx) + if ok { + if _, exists := md[":authority"]; !exists { + return nil, grpc.Errorf(codes.DataLoss, "expected an :authority metadata: %v", md) + } + if err := grpc.SendHeader(ctx, md); err != nil { + return nil, fmt.Errorf("grpc.SendHeader(_, %v) = %v, want %v", md, err, nil) + } + grpc.SetTrailer(ctx, testTrailerMetadata) + } + pr, ok := peer.FromContext(ctx) + if !ok { + return nil, fmt.Errorf("failed to get peer from ctx") + } + if pr.Addr == net.Addr(nil) { + return nil, fmt.Errorf("failed to get peer address") + } + if s.security != "" { + // Check Auth info + var authType, serverName string + switch info := pr.AuthInfo.(type) { + case credentials.TLSInfo: + authType = info.AuthType() + serverName = info.State.ServerName + default: + return nil, fmt.Errorf("Unknown AuthInfo type") + } + if authType != s.security { + return nil, fmt.Errorf("Wrong auth type: got %q, want %q", authType, s.security) + } + if serverName != "x.test.youtube.com" { + return nil, fmt.Errorf("Unknown server name %q", serverName) + } + } + // Simulate some service delay. + time.Sleep(time.Second) + + payload, err := newPayload(in.GetResponseType(), in.GetResponseSize()) + if err != nil { + return nil, err + } + + return &testpb.SimpleResponse{ + Payload: payload, + }, nil +} + +func (s *testServer) StreamingOutputCall(args *testpb.StreamingOutputCallRequest, stream testpb.TestService_StreamingOutputCallServer) error { + if md, ok := metadata.FromContext(stream.Context()); ok { + if _, exists := md[":authority"]; !exists { + return grpc.Errorf(codes.DataLoss, "expected an :authority metadata: %v", md) + } + // For testing purpose, returns an error if there is attached metadata except for authority. + if len(md) > 1 { + return grpc.Errorf(codes.DataLoss, "got extra metadata") + } + } + cs := args.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + + payload, err := newPayload(args.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: payload, + }); err != nil { + return err + } + } + return nil +} + +func (s *testServer) StreamingInputCall(stream testpb.TestService_StreamingInputCallServer) error { + var sum int + for { + in, err := stream.Recv() + if err == io.EOF { + return stream.SendAndClose(&testpb.StreamingInputCallResponse{ + AggregatedPayloadSize: proto.Int32(int32(sum)), + }) + } + if err != nil { + return err + } + p := in.GetPayload().GetBody() + sum += len(p) + } +} + +func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { + md, ok := metadata.FromContext(stream.Context()) + if ok { + if err := stream.SendHeader(md); err != nil { + return fmt.Errorf("%v.SendHeader(%v) = %v, want %v", stream, md, err, nil) + } + stream.SetTrailer(md) + } + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + return nil + } + if err != nil { + return err + } + cs := in.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + + payload, err := newPayload(in.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: payload, + }); err != nil { + return err + } + } + } +} + +func (s *testServer) HalfDuplexCall(stream testpb.TestService_HalfDuplexCallServer) error { + var msgBuf []*testpb.StreamingOutputCallRequest + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + break + } + if err != nil { + return err + } + msgBuf = append(msgBuf, in) + } + for _, m := range msgBuf { + cs := m.GetResponseParameters() + for _, c := range cs { + if us := c.GetIntervalUs(); us > 0 { + time.Sleep(time.Duration(us) * time.Microsecond) + } + + payload, err := newPayload(m.GetResponseType(), c.GetSize()) + if err != nil { + return err + } + + if err := stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: payload, + }); err != nil { + return err + } + } + } + return nil +} + +const tlsDir = "testdata/" + +func unixDialer(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("unix", addr, timeout) +} + +type env struct { + name string + network string // The type of network such as tcp, unix, etc. + dialer func(addr string, timeout time.Duration) (net.Conn, error) + security string // The security protocol such as TLS, SSH, etc. + httpHandler bool // whether to use the http.Handler ServerTransport; requires TLS +} + +func (e env) runnable() bool { + if runtime.GOOS == "windows" && strings.HasPrefix(e.name, "unix-") { + return false + } + return true +} + +func (e env) getDialer() func(addr string, timeout time.Duration) (net.Conn, error) { + if e.dialer != nil { + return e.dialer + } + return func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("tcp", addr, timeout) + } +} + +var ( + tcpClearEnv = env{name: "tcp-clear", network: "tcp"} + tcpTLSEnv = env{name: "tcp-tls", network: "tcp", security: "tls"} + unixClearEnv = env{name: "unix-clear", network: "unix", dialer: unixDialer} + unixTLSEnv = env{name: "unix-tls", network: "unix", dialer: unixDialer, security: "tls"} + handlerEnv = env{name: "handler-tls", network: "tcp", security: "tls", httpHandler: true} + allEnv = []env{tcpClearEnv, tcpTLSEnv, unixClearEnv, unixTLSEnv, handlerEnv} +) + +var onlyEnv = flag.String("only_env", "", "If non-empty, one of 'tcp-clear', 'tcp-tls', 'unix-clear', 'unix-tls', or 'handler-tls' to only run the tests for that environment. Empty means all.") + +func listTestEnv() (envs []env) { + if *onlyEnv != "" { + for _, e := range allEnv { + if e.name == *onlyEnv { + if !e.runnable() { + panic(fmt.Sprintf("--only_env environment %q does not run on %s", *onlyEnv, runtime.GOOS)) + } + return []env{e} + } + } + panic(fmt.Sprintf("invalid --only_env value %q", *onlyEnv)) + } + for _, e := range allEnv { + if e.runnable() { + envs = append(envs, e) + } + } + return envs +} + +// test is an end-to-end test. It should be created with the newTest +// func, modified as needed, and then started with its startServer method. +// It should be cleaned up with the tearDown method. +type test struct { + t *testing.T + e env + + ctx context.Context // valid for life of test, before tearDown + cancel context.CancelFunc + + // Configurable knobs, after newTest returns: + testServer testpb.TestServiceServer // nil means none + healthServer *health.HealthServer // nil means disabled + maxStream uint32 + userAgent string + clientCompression bool + serverCompression bool + unaryInt grpc.UnaryServerInterceptor + streamInt grpc.StreamServerInterceptor + + // srv and srvAddr are set once startServer is called. + srv *grpc.Server + srvAddr string + + cc *grpc.ClientConn // nil until requested via clientConn + restoreLogs func() // nil unless declareLogNoise is used +} + +func (te *test) tearDown() { + if te.cancel != nil { + te.cancel() + te.cancel = nil + } + if te.cc != nil { + te.cc.Close() + te.cc = nil + } + if te.restoreLogs != nil { + te.restoreLogs() + te.restoreLogs = nil + } + te.srv.Stop() +} + +// newTest returns a new test using the provided testing.T and +// environment. It is returned with default values. Tests should +// modify it before calling its startServer and clientConn methods. +func newTest(t *testing.T, e env) *test { + te := &test{ + t: t, + e: e, + testServer: &testServer{security: e.security}, + maxStream: math.MaxUint32, + } + te.ctx, te.cancel = context.WithCancel(context.Background()) + return te +} + +// startServer starts a gRPC server listening. Callers should defer a +// call to te.tearDown to clean up. +func (te *test) startServer() { + e := te.e + te.t.Logf("Running test in %s environment...", e.name) + sopts := []grpc.ServerOption{grpc.MaxConcurrentStreams(te.maxStream)} + if te.serverCompression { + sopts = append(sopts, + grpc.RPCCompressor(grpc.NewGZIPCompressor()), + grpc.RPCDecompressor(grpc.NewGZIPDecompressor()), + ) + } + if te.unaryInt != nil { + sopts = append(sopts, grpc.UnaryInterceptor(te.unaryInt)) + } + if te.streamInt != nil { + sopts = append(sopts, grpc.StreamInterceptor(te.streamInt)) + } + la := "localhost:0" + switch e.network { + case "unix": + la = "/tmp/testsock" + fmt.Sprintf("%d", time.Now()) + syscall.Unlink(la) + } + lis, err := net.Listen(e.network, la) + if err != nil { + te.t.Fatalf("Failed to listen: %v", err) + } + if te.e.security == "tls" { + creds, err := credentials.NewServerTLSFromFile(tlsDir+"server1.pem", tlsDir+"server1.key") + if err != nil { + te.t.Fatalf("Failed to generate credentials %v", err) + } + sopts = append(sopts, grpc.Creds(creds)) + } + s := grpc.NewServer(sopts...) + te.srv = s + if e.httpHandler { + internal.TestingUseHandlerImpl(s) + } + if te.healthServer != nil { + healthpb.RegisterHealthServer(s, te.healthServer) + } + if te.testServer != nil { + testpb.RegisterTestServiceServer(s, te.testServer) + } + addr := la + switch e.network { + case "unix": + default: + _, port, err := net.SplitHostPort(lis.Addr().String()) + if err != nil { + te.t.Fatalf("Failed to parse listener address: %v", err) + } + addr = "localhost:" + port + } + + go s.Serve(lis) + te.srvAddr = addr +} + +func (te *test) clientConn() *grpc.ClientConn { + if te.cc != nil { + return te.cc + } + opts := []grpc.DialOption{ + grpc.WithDialer(te.e.dialer), + grpc.WithUserAgent(te.userAgent), + } + + if te.clientCompression { + opts = append(opts, + grpc.WithCompressor(grpc.NewGZIPCompressor()), + grpc.WithDecompressor(grpc.NewGZIPDecompressor()), + ) + } + if te.e.security == "tls" { + creds, err := credentials.NewClientTLSFromFile(tlsDir+"ca.pem", "x.test.youtube.com") + if err != nil { + te.t.Fatalf("Failed to load credentials: %v", err) + } + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + var err error + te.cc, err = grpc.Dial(te.srvAddr, opts...) + if err != nil { + te.t.Fatalf("Dial(%q) = %v", te.srvAddr, err) + } + return te.cc +} + +func (te *test) declareLogNoise(phrases ...string) { + te.restoreLogs = declareLogNoise(te.t, phrases...) +} + +func (te *test) withServerTester(fn func(st *serverTester)) { + var c net.Conn + var err error + c, err = te.e.getDialer()(te.srvAddr, 10*time.Second) + if err != nil { + te.t.Fatal(err) + } + defer c.Close() + if te.e.security == "tls" { + c = tls.Client(c, &tls.Config{ + InsecureSkipVerify: true, + NextProtos: []string{http2.NextProtoTLS}, + }) + } + st := newServerTesterFromConn(te.t, c) + st.greet() + fn(st) +} + +func TestTimeoutOnDeadServer(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testTimeoutOnDeadServer(t, e) + } +} + +func testTimeoutOnDeadServer(t *testing.T, e env) { + te := newTest(t, e) + te.userAgent = testAppUA + te.declareLogNoise( + "transport: http2Client.notifyError got notified that the client transport was broken EOF", + "grpc: Conn.transportMonitor exits due to: grpc: the client connection is closing", + "grpc: Conn.resetTransport failed to create client transport: connection error", + "grpc: Conn.resetTransport failed to create client transport: connection error: desc = \"transport: dial unix", + ) + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.FailFast(false)); err != nil { + t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, ", err) + } + te.srv.Stop() + // Set -1 as the timeout to make sure if transportMonitor gets error + // notification in time the failure path of the 1st invoke of + // ClientConn.wait hits the deadline exceeded error. + ctx, _ := context.WithTimeout(context.Background(), -1) + if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.FailFast(false)); grpc.Code(err) != codes.DeadlineExceeded { + t.Fatalf("TestService/EmptyCall(%v, _) = _, %v, want _, error code: %d", ctx, err, codes.DeadlineExceeded) + } + awaitNewConnLogOutput() +} + +func TestFailFast(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testFailFast(t, e) + } +} + +func testFailFast(t *testing.T, e env) { + te := newTest(t, e) + te.userAgent = testAppUA + te.declareLogNoise( + "transport: http2Client.notifyError got notified that the client transport was broken EOF", + "grpc: Conn.transportMonitor exits due to: grpc: the client connection is closing", + "grpc: Conn.resetTransport failed to create client transport: connection error", + "grpc: Conn.resetTransport failed to create client transport: connection error: desc = \"transport: dial unix", + ) + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil { + t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, ", err) + } + // Stop the server and tear down all the exisiting connections. + te.srv.Stop() + // Loop until the server teardown is propagated to the client. + for { + if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); grpc.Code(err) == codes.Unavailable { + break + } + time.Sleep(10 * time.Millisecond) + } + // The client keeps reconnecting and ongoing fail-fast RPCs should fail with code.Unavailable. + if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); grpc.Code(err) != codes.Unavailable { + t.Fatalf("TestService/EmptyCall(_, _, _) = _, %v, want _, error code: %d", err, codes.Unavailable) + } + if _, err := tc.StreamingInputCall(context.Background()); grpc.Code(err) != codes.Unavailable { + t.Fatalf("TestService/StreamingInputCall(_) = _, %v, want _, error code: %d", err, codes.Unavailable) + } + + awaitNewConnLogOutput() +} + +func healthCheck(d time.Duration, cc *grpc.ClientConn, serviceName string) (*healthpb.HealthCheckResponse, error) { + ctx, _ := context.WithTimeout(context.Background(), d) + hc := healthpb.NewHealthClient(cc) + req := &healthpb.HealthCheckRequest{ + Service: serviceName, + } + return hc.Check(ctx, req) +} + +func TestHealthCheckOnSuccess(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testHealthCheckOnSuccess(t, e) + } +} + +func testHealthCheckOnSuccess(t *testing.T, e env) { + te := newTest(t, e) + hs := health.NewHealthServer() + hs.SetServingStatus("grpc.health.v1.Health", 1) + te.healthServer = hs + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + if _, err := healthCheck(1*time.Second, cc, "grpc.health.v1.Health"); err != nil { + t.Fatalf("Health/Check(_, _) = _, %v, want _, ", err) + } +} + +func TestHealthCheckOnFailure(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testHealthCheckOnFailure(t, e) + } +} + +func testHealthCheckOnFailure(t *testing.T, e env) { + defer leakCheck(t)() + te := newTest(t, e) + te.declareLogNoise( + "Failed to dial ", + "grpc: the client connection is closing; please retry", + ) + hs := health.NewHealthServer() + hs.SetServingStatus("grpc.health.v1.HealthCheck", 1) + te.healthServer = hs + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + wantErr := grpc.Errorf(codes.DeadlineExceeded, "context deadline exceeded") + if _, err := healthCheck(0*time.Second, cc, "grpc.health.v1.Health"); !equalErrors(err, wantErr) { + t.Fatalf("Health/Check(_, _) = _, %v, want _, error code %d", err, codes.DeadlineExceeded) + } + awaitNewConnLogOutput() +} + +func TestHealthCheckOff(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + // TODO(bradfitz): Temporarily skip this env due to #619. + if e.name == "handler-tls" { + continue + } + testHealthCheckOff(t, e) + } +} + +func testHealthCheckOff(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + want := grpc.Errorf(codes.Unimplemented, "unknown service grpc.health.v1.Health") + if _, err := healthCheck(1*time.Second, te.clientConn(), ""); !equalErrors(err, want) { + t.Fatalf("Health/Check(_, _) = _, %v, want _, %v", err, want) + } +} + +func TestHealthCheckServingStatus(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testHealthCheckServingStatus(t, e) + } +} + +func testHealthCheckServingStatus(t *testing.T, e env) { + te := newTest(t, e) + hs := health.NewHealthServer() + te.healthServer = hs + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + out, err := healthCheck(1*time.Second, cc, "") + if err != nil { + t.Fatalf("Health/Check(_, _) = _, %v, want _, ", err) + } + if out.Status != healthpb.HealthCheckResponse_SERVING { + t.Fatalf("Got the serving status %v, want SERVING", out.Status) + } + wantErr := grpc.Errorf(codes.NotFound, "unknown service") + if _, err := healthCheck(1*time.Second, cc, "grpc.health.v1.Health"); !equalErrors(err, wantErr) { + t.Fatalf("Health/Check(_, _) = _, %v, want _, error code %d", err, codes.NotFound) + } + hs.SetServingStatus("grpc.health.v1.Health", healthpb.HealthCheckResponse_SERVING) + out, err = healthCheck(1*time.Second, cc, "grpc.health.v1.Health") + if err != nil { + t.Fatalf("Health/Check(_, _) = _, %v, want _, ", err) + } + if out.Status != healthpb.HealthCheckResponse_SERVING { + t.Fatalf("Got the serving status %v, want SERVING", out.Status) + } + hs.SetServingStatus("grpc.health.v1.Health", healthpb.HealthCheckResponse_NOT_SERVING) + out, err = healthCheck(1*time.Second, cc, "grpc.health.v1.Health") + if err != nil { + t.Fatalf("Health/Check(_, _) = _, %v, want _, ", err) + } + if out.Status != healthpb.HealthCheckResponse_NOT_SERVING { + t.Fatalf("Got the serving status %v, want NOT_SERVING", out.Status) + } + +} + +func TestErrorChanNoIO(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testErrorChanNoIO(t, e) + } +} + +func testErrorChanNoIO(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + + tc := testpb.NewTestServiceClient(te.clientConn()) + if _, err := tc.FullDuplexCall(context.Background()); err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } +} + +func TestEmptyUnaryWithUserAgent(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testEmptyUnaryWithUserAgent(t, e) + } +} + +func testEmptyUnaryWithUserAgent(t *testing.T, e env) { + te := newTest(t, e) + te.userAgent = testAppUA + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + var header metadata.MD + reply, err := tc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Header(&header)) + if err != nil || !proto.Equal(&testpb.Empty{}, reply) { + t.Fatalf("TestService/EmptyCall(_, _) = %v, %v, want %v, ", reply, err, &testpb.Empty{}) + } + if v, ok := header["ua"]; !ok || v[0] != testAppUA { + t.Fatalf("header[\"ua\"] = %q, %t, want %q, true", v, ok, testAppUA) + } + + te.srv.Stop() +} + +func TestFailedEmptyUnary(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testFailedEmptyUnary(t, e) + } +} + +func testFailedEmptyUnary(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + ctx := metadata.NewContext(context.Background(), testMetadata) + wantErr := grpc.Errorf(codes.DataLoss, "missing expected user-agent") + if _, err := tc.EmptyCall(ctx, &testpb.Empty{}); !equalErrors(err, wantErr) { + t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, %v", err, wantErr) + } +} + +func TestLargeUnary(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testLargeUnary(t, e) + } +} + +func testLargeUnary(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + const argSize = 271828 + const respSize = 314159 + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + reply, err := tc.UnaryCall(context.Background(), req) + if err != nil { + t.Fatalf("TestService/UnaryCall(_, _) = _, %v, want _, ", err) + } + pt := reply.GetPayload().GetType() + ps := len(reply.GetPayload().GetBody()) + if pt != testpb.PayloadType_COMPRESSABLE || ps != respSize { + t.Fatalf("Got the reply with type %d len %d; want %d, %d", pt, ps, testpb.PayloadType_COMPRESSABLE, respSize) + } +} + +func TestMetadataUnaryRPC(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testMetadataUnaryRPC(t, e) + } +} + +func testMetadataUnaryRPC(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + const argSize = 2718 + const respSize = 314 + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + var header, trailer metadata.MD + ctx := metadata.NewContext(context.Background(), testMetadata) + if _, err := tc.UnaryCall(ctx, req, grpc.Header(&header), grpc.Trailer(&trailer)); err != nil { + t.Fatalf("TestService.UnaryCall(%v, _, _, _) = _, %v; want _, ", ctx, err) + } + // Ignore optional response headers that Servers may set: + if header != nil { + delete(header, "trailer") // RFC 2616 says server SHOULD (but optional) declare trailers + delete(header, "date") // the Date header is also optional + } + if !reflect.DeepEqual(header, testMetadata) { + t.Fatalf("Received header metadata %v, want %v", header, testMetadata) + } + if !reflect.DeepEqual(trailer, testTrailerMetadata) { + t.Fatalf("Received trailer metadata %v, want %v", trailer, testTrailerMetadata) + } +} + +// TestMalformedHTTP2Metedata verfies the returned error when the client +// sends an illegal metadata. +func TestMalformedHTTP2Metadata(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testMalformedHTTP2Metadata(t, e) + } +} + +func testMalformedHTTP2Metadata(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, 2718) + if err != nil { + t.Fatal(err) + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(314), + Payload: payload, + } + ctx := metadata.NewContext(context.Background(), malformedHTTP2Metadata) + if _, err := tc.UnaryCall(ctx, req); grpc.Code(err) != codes.Internal { + t.Fatalf("TestService.UnaryCall(%v, _) = _, %v; want _, %q", ctx, err, codes.Internal) + } +} + +func performOneRPC(t *testing.T, tc testpb.TestServiceClient, wg *sync.WaitGroup) { + defer wg.Done() + const argSize = 2718 + const respSize = 314 + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Error(err) + return + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + reply, err := tc.UnaryCall(context.Background(), req, grpc.FailFast(false)) + if err != nil { + t.Errorf("TestService/UnaryCall(_, _) = _, %v, want _, ", err) + return + } + pt := reply.GetPayload().GetType() + ps := len(reply.GetPayload().GetBody()) + if pt != testpb.PayloadType_COMPRESSABLE || ps != respSize { + t.Errorf("Got reply with type %d len %d; want %d, %d", pt, ps, testpb.PayloadType_COMPRESSABLE, respSize) + return + } +} + +func TestRetry(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testRetry(t, e) + } +} + +// This test mimics a user who sends 1000 RPCs concurrently on a faulty transport. +// TODO(zhaoq): Refactor to make this clearer and add more cases to test racy +// and error-prone paths. +func testRetry(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise("transport: http2Client.notifyError got notified that the client transport was broken") + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + var wg sync.WaitGroup + + numRPC := 1000 + rpcSpacing := 2 * time.Millisecond + if raceMode { + // The race detector has a limit on how many goroutines it can track. + // This test is near the upper limit, and goes over the limit + // depending on the environment (the http.Handler environment uses + // more goroutines) + t.Logf("Shortening test in race mode.") + numRPC /= 2 + rpcSpacing *= 2 + } + + wg.Add(1) + go func() { + // Halfway through starting RPCs, kill all connections: + time.Sleep(time.Duration(numRPC/2) * rpcSpacing) + + // The server shuts down the network connection to make a + // transport error which will be detected by the client side + // code. + internal.TestingCloseConns(te.srv) + wg.Done() + }() + // All these RPCs should succeed eventually. + for i := 0; i < numRPC; i++ { + time.Sleep(rpcSpacing) + wg.Add(1) + go performOneRPC(t, tc, &wg) + } + wg.Wait() +} + +func TestRPCTimeout(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testRPCTimeout(t, e) + } +} + +// TODO(zhaoq): Have a better test coverage of timeout and cancellation mechanism. +func testRPCTimeout(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + const argSize = 2718 + const respSize = 314 + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + for i := -1; i <= 10; i++ { + ctx, _ := context.WithTimeout(context.Background(), time.Duration(i)*time.Millisecond) + if _, err := tc.UnaryCall(ctx, req); grpc.Code(err) != codes.DeadlineExceeded { + t.Fatalf("TestService/UnaryCallv(_, _) = _, %v; want , error code: %d", err, codes.DeadlineExceeded) + } + } +} + +func TestCancel(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testCancel(t, e) + } +} + +func testCancel(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise("grpc: the client connection is closing; please retry") + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + const argSize = 2718 + const respSize = 314 + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + ctx, cancel := context.WithCancel(context.Background()) + time.AfterFunc(1*time.Millisecond, cancel) + if r, err := tc.UnaryCall(ctx, req); grpc.Code(err) != codes.Canceled { + t.Fatalf("TestService/UnaryCall(_, _) = %v, %v; want _, error code: %d", r, err, codes.Canceled) + } + awaitNewConnLogOutput() +} + +func TestCancelNoIO(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testCancelNoIO(t, e) + } +} + +func testCancelNoIO(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise("http2Client.notifyError got notified that the client transport was broken") + te.maxStream = 1 // Only allows 1 live stream per server transport. + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + // Start one blocked RPC for which we'll never send streaming + // input. This will consume the 1 maximum concurrent streams, + // causing future RPCs to hang. + ctx, cancelFirst := context.WithCancel(context.Background()) + _, err := tc.StreamingInputCall(ctx) + if err != nil { + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, ", tc, err) + } + + // Loop until the ClientConn receives the initial settings + // frame from the server, notifying it about the maximum + // concurrent streams. We know when it's received it because + // an RPC will fail with codes.DeadlineExceeded instead of + // succeeding. + // TODO(bradfitz): add internal test hook for this (Issue 534) + for { + ctx, cancelSecond := context.WithTimeout(context.Background(), 250*time.Millisecond) + _, err := tc.StreamingInputCall(ctx) + cancelSecond() + if err == nil { + time.Sleep(50 * time.Millisecond) + continue + } + if grpc.Code(err) == codes.DeadlineExceeded { + break + } + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, %d", tc, err, codes.DeadlineExceeded) + } + // If there are any RPCs in flight before the client receives + // the max streams setting, let them be expired. + // TODO(bradfitz): add internal test hook for this (Issue 534) + time.Sleep(500 * time.Millisecond) + + ch := make(chan struct{}) + go func() { + defer close(ch) + + // This should be blocked until the 1st is canceled. + ctx, cancelThird := context.WithTimeout(context.Background(), 2*time.Second) + if _, err := tc.StreamingInputCall(ctx); err != nil { + t.Errorf("%v.StreamingInputCall(_) = _, %v, want _, ", tc, err) + } + cancelThird() + }() + cancelFirst() + <-ch +} + +// The following tests the gRPC streaming RPC implementations. +// TODO(zhaoq): Have better coverage on error cases. +var ( + reqSizes = []int{27182, 8, 1828, 45904} + respSizes = []int{31415, 9, 2653, 58979} +) + +func TestNoService(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testNoService(t, e) + } +} + +func testNoService(t *testing.T, e env) { + te := newTest(t, e) + te.testServer = nil // register nothing + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + stream, err := tc.FullDuplexCall(te.ctx, grpc.FailFast(false)) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + if _, err := stream.Recv(); grpc.Code(err) != codes.Unimplemented { + t.Fatalf("stream.Recv() = _, %v, want _, error code %d", err, codes.Unimplemented) + } +} + +func TestPingPong(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testPingPong(t, e) + } +} + +func testPingPong(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + stream, err := tc.FullDuplexCall(te.ctx) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + var index int + for index < len(reqSizes) { + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(int32(respSizes[index])), + }, + } + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(reqSizes[index])) + if err != nil { + t.Fatal(err) + } + + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: payload, + } + if err := stream.Send(req); err != nil { + t.Fatalf("%v.Send(%v) = %v, want ", stream, req, err) + } + reply, err := stream.Recv() + if err != nil { + t.Fatalf("%v.Recv() = %v, want ", stream, err) + } + pt := reply.GetPayload().GetType() + if pt != testpb.PayloadType_COMPRESSABLE { + t.Fatalf("Got the reply of type %d, want %d", pt, testpb.PayloadType_COMPRESSABLE) + } + size := len(reply.GetPayload().GetBody()) + if size != int(respSizes[index]) { + t.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) + } + index++ + } + if err := stream.CloseSend(); err != nil { + t.Fatalf("%v.CloseSend() got %v, want %v", stream, err, nil) + } + if _, err := stream.Recv(); err != io.EOF { + t.Fatalf("%v failed to complele the ping pong test: %v", stream, err) + } +} + +func TestMetadataStreamingRPC(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testMetadataStreamingRPC(t, e) + } +} + +func testMetadataStreamingRPC(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + ctx := metadata.NewContext(te.ctx, testMetadata) + stream, err := tc.FullDuplexCall(ctx) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + go func() { + headerMD, err := stream.Header() + if e.security == "tls" { + delete(headerMD, "transport_security_type") + } + delete(headerMD, "trailer") // ignore if present + if err != nil || !reflect.DeepEqual(testMetadata, headerMD) { + t.Errorf("#1 %v.Header() = %v, %v, want %v, ", stream, headerMD, err, testMetadata) + } + // test the cached value. + headerMD, err = stream.Header() + delete(headerMD, "trailer") // ignore if present + if err != nil || !reflect.DeepEqual(testMetadata, headerMD) { + t.Errorf("#2 %v.Header() = %v, %v, want %v, ", stream, headerMD, err, testMetadata) + } + var index int + for index < len(reqSizes) { + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(int32(respSizes[index])), + }, + } + + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(reqSizes[index])) + if err != nil { + t.Fatal(err) + } + + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: payload, + } + if err := stream.Send(req); err != nil { + t.Errorf("%v.Send(%v) = %v, want ", stream, req, err) + return + } + index++ + } + // Tell the server we're done sending args. + stream.CloseSend() + }() + for { + if _, err := stream.Recv(); err != nil { + break + } + } + trailerMD := stream.Trailer() + if !reflect.DeepEqual(testMetadata, trailerMD) { + t.Fatalf("%v.Trailer() = %v, want %v", stream, trailerMD, testMetadata) + } +} + +func TestServerStreaming(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testServerStreaming(t, e) + } +} + +func testServerStreaming(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + respParam := make([]*testpb.ResponseParameters, len(respSizes)) + for i, s := range respSizes { + respParam[i] = &testpb.ResponseParameters{ + Size: proto.Int32(int32(s)), + } + } + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + } + stream, err := tc.StreamingOutputCall(context.Background(), req) + if err != nil { + t.Fatalf("%v.StreamingOutputCall(_) = _, %v, want ", tc, err) + } + var rpcStatus error + var respCnt int + var index int + for { + reply, err := stream.Recv() + if err != nil { + rpcStatus = err + break + } + pt := reply.GetPayload().GetType() + if pt != testpb.PayloadType_COMPRESSABLE { + t.Fatalf("Got the reply of type %d, want %d", pt, testpb.PayloadType_COMPRESSABLE) + } + size := len(reply.GetPayload().GetBody()) + if size != int(respSizes[index]) { + t.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) + } + index++ + respCnt++ + } + if rpcStatus != io.EOF { + t.Fatalf("Failed to finish the server streaming rpc: %v, want ", rpcStatus) + } + if respCnt != len(respSizes) { + t.Fatalf("Got %d reply, want %d", len(respSizes), respCnt) + } +} + +func TestFailedServerStreaming(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testFailedServerStreaming(t, e) + } +} + +func testFailedServerStreaming(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + respParam := make([]*testpb.ResponseParameters, len(respSizes)) + for i, s := range respSizes { + respParam[i] = &testpb.ResponseParameters{ + Size: proto.Int32(int32(s)), + } + } + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + } + ctx := metadata.NewContext(te.ctx, testMetadata) + stream, err := tc.StreamingOutputCall(ctx, req) + if err != nil { + t.Fatalf("%v.StreamingOutputCall(_) = _, %v, want ", tc, err) + } + wantErr := grpc.Errorf(codes.DataLoss, "got extra metadata") + if _, err := stream.Recv(); !equalErrors(err, wantErr) { + t.Fatalf("%v.Recv() = _, %v, want _, %v", stream, err, wantErr) + } +} + +// concurrentSendServer is a TestServiceServer whose +// StreamingOutputCall makes ten serial Send calls, sending payloads +// "0".."9", inclusive. TestServerStreaming_Concurrent verifies they +// were received in the correct order, and that there were no races. +// +// All other TestServiceServer methods crash if called. +type concurrentSendServer struct { + testpb.TestServiceServer +} + +func (s concurrentSendServer) StreamingOutputCall(args *testpb.StreamingOutputCallRequest, stream testpb.TestService_StreamingOutputCallServer) error { + for i := 0; i < 10; i++ { + stream.Send(&testpb.StreamingOutputCallResponse{ + Payload: &testpb.Payload{ + Body: []byte{'0' + uint8(i)}, + }, + }) + } + return nil +} + +// Tests doing a bunch of concurrent streaming output calls. +func TestServerStreaming_Concurrent(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testServerStreaming_Concurrent(t, e) + } +} + +func testServerStreaming_Concurrent(t *testing.T, e env) { + te := newTest(t, e) + te.testServer = concurrentSendServer{} + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + doStreamingCall := func() { + req := &testpb.StreamingOutputCallRequest{} + stream, err := tc.StreamingOutputCall(context.Background(), req) + if err != nil { + t.Errorf("%v.StreamingOutputCall(_) = _, %v, want ", tc, err) + return + } + var ngot int + var buf bytes.Buffer + for { + reply, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + ngot++ + if buf.Len() > 0 { + buf.WriteByte(',') + } + buf.Write(reply.GetPayload().GetBody()) + } + if want := 10; ngot != want { + t.Errorf("Got %d replies, want %d", ngot, want) + } + if got, want := buf.String(), "0,1,2,3,4,5,6,7,8,9"; got != want { + t.Errorf("Got replies %q; want %q", got, want) + } + } + + var wg sync.WaitGroup + for i := 0; i < 20; i++ { + wg.Add(1) + go func() { + defer wg.Done() + doStreamingCall() + }() + } + wg.Wait() + +} + +func TestClientStreaming(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testClientStreaming(t, e) + } +} + +func testClientStreaming(t *testing.T, e env) { + te := newTest(t, e) + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + stream, err := tc.StreamingInputCall(te.ctx) + if err != nil { + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want ", tc, err) + } + + var sum int + for _, s := range reqSizes { + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(s)) + if err != nil { + t.Fatal(err) + } + + req := &testpb.StreamingInputCallRequest{ + Payload: payload, + } + if err := stream.Send(req); err != nil { + t.Fatalf("%v.Send(%v) = %v, want ", stream, req, err) + } + sum += s + } + reply, err := stream.CloseAndRecv() + if err != nil { + t.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) + } + if reply.GetAggregatedPayloadSize() != int32(sum) { + t.Fatalf("%v.CloseAndRecv().GetAggregatePayloadSize() = %v; want %v", stream, reply.GetAggregatedPayloadSize(), sum) + } +} + +func TestExceedMaxStreamsLimit(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testExceedMaxStreamsLimit(t, e) + } +} + +func testExceedMaxStreamsLimit(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise( + "http2Client.notifyError got notified that the client transport was broken", + "Conn.resetTransport failed to create client transport", + "grpc: the client connection is closing", + ) + te.maxStream = 1 // Only allows 1 live stream per server transport. + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + + _, err := tc.StreamingInputCall(te.ctx) + if err != nil { + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, ", tc, err) + } + // Loop until receiving the new max stream setting from the server. + for { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + _, err := tc.StreamingInputCall(ctx) + if err == nil { + time.Sleep(time.Second) + continue + } + if grpc.Code(err) == codes.DeadlineExceeded { + break + } + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, %d", tc, err, codes.DeadlineExceeded) + } +} + +func TestStreamsQuotaRecovery(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testStreamsQuotaRecovery(t, e) + } +} + +func testStreamsQuotaRecovery(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise( + "http2Client.notifyError got notified that the client transport was broken", + "Conn.resetTransport failed to create client transport", + "grpc: the client connection is closing", + ) + te.maxStream = 1 // Allows 1 live stream. + te.startServer() + defer te.tearDown() + + cc := te.clientConn() + tc := testpb.NewTestServiceClient(cc) + ctx, cancel := context.WithCancel(context.Background()) + if _, err := tc.StreamingInputCall(ctx); err != nil { + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, ", tc, err) + } + // Loop until the new max stream setting is effective. + for { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + _, err := tc.StreamingInputCall(ctx) + if err == nil { + time.Sleep(time.Second) + continue + } + if grpc.Code(err) == codes.DeadlineExceeded { + break + } + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, %d", tc, err, codes.DeadlineExceeded) + } + cancel() + + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + ctx, cancel := context.WithCancel(context.Background()) + if _, err := tc.StreamingInputCall(ctx); err != nil { + t.Errorf("%v.StreamingInputCall(_) = _, %v, want _, ", tc, err) + } + cancel() + }() + } + wg.Wait() +} + +func TestCompressServerHasNoSupport(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testCompressServerHasNoSupport(t, e) + } +} + +func testCompressServerHasNoSupport(t *testing.T, e env) { + te := newTest(t, e) + te.serverCompression = false + te.clientCompression = true + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + const argSize = 271828 + const respSize = 314159 + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + if _, err := tc.UnaryCall(context.Background(), req); err == nil || grpc.Code(err) != codes.Unimplemented { + t.Fatalf("TestService/UnaryCall(_, _) = _, %v, want _, error code %d", err, codes.Unimplemented) + } + // Streaming RPC + stream, err := tc.FullDuplexCall(context.Background()) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(31415), + }, + } + payload, err = newPayload(testpb.PayloadType_COMPRESSABLE, int32(31415)) + if err != nil { + t.Fatal(err) + } + sreq := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: payload, + } + if err := stream.Send(sreq); err != nil { + t.Fatalf("%v.Send(%v) = %v, want ", stream, sreq, err) + } + if _, err := stream.Recv(); err == nil || grpc.Code(err) != codes.Unimplemented { + t.Fatalf("%v.Recv() = %v, want error code %d", stream, err, codes.Unimplemented) + } +} + +func TestCompressOK(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testCompressOK(t, e) + } +} + +func testCompressOK(t *testing.T, e env) { + te := newTest(t, e) + te.serverCompression = true + te.clientCompression = true + te.startServer() + defer te.tearDown() + tc := testpb.NewTestServiceClient(te.clientConn()) + + // Unary call + const argSize = 271828 + const respSize = 314159 + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, argSize) + if err != nil { + t.Fatal(err) + } + req := &testpb.SimpleRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseSize: proto.Int32(respSize), + Payload: payload, + } + ctx := metadata.NewContext(context.Background(), metadata.Pairs("something", "something")) + if _, err := tc.UnaryCall(ctx, req); err != nil { + t.Fatalf("TestService/UnaryCall(_, _) = _, %v, want _, ", err) + } + // Streaming RPC + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + stream, err := tc.FullDuplexCall(ctx) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(31415), + }, + } + payload, err = newPayload(testpb.PayloadType_COMPRESSABLE, int32(31415)) + if err != nil { + t.Fatal(err) + } + sreq := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: payload, + } + if err := stream.Send(sreq); err != nil { + t.Fatalf("%v.Send(%v) = %v, want ", stream, sreq, err) + } + if _, err := stream.Recv(); err != nil { + t.Fatalf("%v.Recv() = %v, want ", stream, err) + } +} + +func TestUnaryServerInterceptor(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testUnaryServerInterceptor(t, e) + } +} + +func errInjector(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return nil, grpc.Errorf(codes.PermissionDenied, "") +} + +func testUnaryServerInterceptor(t *testing.T, e env) { + te := newTest(t, e) + te.unaryInt = errInjector + te.startServer() + defer te.tearDown() + + tc := testpb.NewTestServiceClient(te.clientConn()) + if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); grpc.Code(err) != codes.PermissionDenied { + t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, error code %d", tc, err, codes.PermissionDenied) + } +} + +func TestStreamServerInterceptor(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + // TODO(bradfitz): Temporarily skip this env due to #619. + if e.name == "handler-tls" { + continue + } + testStreamServerInterceptor(t, e) + } +} + +func fullDuplexOnly(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if info.FullMethod == "/grpc.testing.TestService/FullDuplexCall" { + return handler(srv, ss) + } + // Reject the other methods. + return grpc.Errorf(codes.PermissionDenied, "") +} + +func testStreamServerInterceptor(t *testing.T, e env) { + te := newTest(t, e) + te.streamInt = fullDuplexOnly + te.startServer() + defer te.tearDown() + + tc := testpb.NewTestServiceClient(te.clientConn()) + respParam := []*testpb.ResponseParameters{ + { + Size: proto.Int32(int32(1)), + }, + } + payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(1)) + if err != nil { + t.Fatal(err) + } + req := &testpb.StreamingOutputCallRequest{ + ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), + ResponseParameters: respParam, + Payload: payload, + } + s1, err := tc.StreamingOutputCall(context.Background(), req) + if err != nil { + t.Fatalf("%v.StreamingOutputCall(_) = _, %v, want _, ", tc, err) + } + if _, err := s1.Recv(); grpc.Code(err) != codes.PermissionDenied { + t.Fatalf("%v.StreamingInputCall(_) = _, %v, want _, error code %d", tc, err, codes.PermissionDenied) + } + s2, err := tc.FullDuplexCall(context.Background()) + if err != nil { + t.Fatalf("%v.FullDuplexCall(_) = _, %v, want ", tc, err) + } + if err := s2.Send(req); err != nil { + t.Fatalf("%v.Send(_) = %v, want ", s2, err) + } + if _, err := s2.Recv(); err != nil { + t.Fatalf("%v.Recv() = _, %v, want _, ", s2, err) + } +} + +// funcServer implements methods of TestServiceServer using funcs, +// similar to an http.HandlerFunc. +// Any unimplemented method will crash. Tests implement the method(s) +// they need. +type funcServer struct { + testpb.TestServiceServer + unaryCall func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) + streamingInputCall func(stream testpb.TestService_StreamingInputCallServer) error +} + +func (s *funcServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + return s.unaryCall(ctx, in) +} + +func (s *funcServer) StreamingInputCall(stream testpb.TestService_StreamingInputCallServer) error { + return s.streamingInputCall(stream) +} + +func TestClientRequestBodyError_UnexpectedEOF(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testClientRequestBodyError_UnexpectedEOF(t, e) + } +} + +func testClientRequestBodyError_UnexpectedEOF(t *testing.T, e env) { + te := newTest(t, e) + te.testServer = &funcServer{unaryCall: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + errUnexpectedCall := errors.New("unexpected call func server method") + t.Error(errUnexpectedCall) + return nil, errUnexpectedCall + }} + te.startServer() + defer te.tearDown() + te.withServerTester(func(st *serverTester) { + st.writeHeadersGRPC(1, "/grpc.testing.TestService/UnaryCall") + // Say we have 5 bytes coming, but set END_STREAM flag: + st.writeData(1, true, []byte{0, 0, 0, 0, 5}) + st.wantAnyFrame() // wait for server to crash (it used to crash) + }) +} + +func TestClientRequestBodyError_CloseAfterLength(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testClientRequestBodyError_CloseAfterLength(t, e) + } +} + +func testClientRequestBodyError_CloseAfterLength(t *testing.T, e env) { + te := newTest(t, e) + te.declareLogNoise("Server.processUnaryRPC failed to write status") + te.testServer = &funcServer{unaryCall: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + errUnexpectedCall := errors.New("unexpected call func server method") + t.Error(errUnexpectedCall) + return nil, errUnexpectedCall + }} + te.startServer() + defer te.tearDown() + te.withServerTester(func(st *serverTester) { + st.writeHeadersGRPC(1, "/grpc.testing.TestService/UnaryCall") + // say we're sending 5 bytes, but then close the connection instead. + st.writeData(1, false, []byte{0, 0, 0, 0, 5}) + st.cc.Close() + }) +} + +func TestClientRequestBodyError_Cancel(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testClientRequestBodyError_Cancel(t, e) + } +} + +func testClientRequestBodyError_Cancel(t *testing.T, e env) { + te := newTest(t, e) + gotCall := make(chan bool, 1) + te.testServer = &funcServer{unaryCall: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + gotCall <- true + return new(testpb.SimpleResponse), nil + }} + te.startServer() + defer te.tearDown() + te.withServerTester(func(st *serverTester) { + st.writeHeadersGRPC(1, "/grpc.testing.TestService/UnaryCall") + // Say we have 5 bytes coming, but cancel it instead. + st.writeData(1, false, []byte{0, 0, 0, 0, 5}) + st.writeRSTStream(1, http2.ErrCodeCancel) + + // Verify we didn't a call yet. + select { + case <-gotCall: + t.Fatal("unexpected call") + default: + } + + // And now send an uncanceled (but still invalid), just to get a response. + st.writeHeadersGRPC(3, "/grpc.testing.TestService/UnaryCall") + st.writeData(3, true, []byte{0, 0, 0, 0, 0}) + <-gotCall + st.wantAnyFrame() + }) +} + +func TestClientRequestBodyError_Cancel_StreamingInput(t *testing.T) { + defer leakCheck(t)() + for _, e := range listTestEnv() { + testClientRequestBodyError_Cancel_StreamingInput(t, e) + } +} + +func testClientRequestBodyError_Cancel_StreamingInput(t *testing.T, e env) { + te := newTest(t, e) + recvErr := make(chan error, 1) + te.testServer = &funcServer{streamingInputCall: func(stream testpb.TestService_StreamingInputCallServer) error { + _, err := stream.Recv() + recvErr <- err + return nil + }} + te.startServer() + defer te.tearDown() + te.withServerTester(func(st *serverTester) { + st.writeHeadersGRPC(1, "/grpc.testing.TestService/StreamingInputCall") + // Say we have 5 bytes coming, but cancel it instead. + st.writeData(1, false, []byte{0, 0, 0, 0, 5}) + st.writeRSTStream(1, http2.ErrCodeCancel) + + var got error + select { + case got = <-recvErr: + case <-time.After(3 * time.Second): + t.Fatal("timeout waiting for error") + } + if se, ok := got.(transport.StreamError); !ok || se.Code != codes.Canceled { + t.Errorf("error = %#v; want transport.StreamError with code Canceled", got) + } + }) +} + +// interestingGoroutines returns all goroutines we care about for the purpose +// of leak checking. It excludes testing or runtime ones. +func interestingGoroutines() (gs []string) { + buf := make([]byte, 2<<20) + buf = buf[:runtime.Stack(buf, true)] + for _, g := range strings.Split(string(buf), "\n\n") { + sl := strings.SplitN(g, "\n", 2) + if len(sl) != 2 { + continue + } + stack := strings.TrimSpace(sl[1]) + if strings.HasPrefix(stack, "testing.RunTests") { + continue + } + + if stack == "" || + strings.Contains(stack, "testing.Main(") || + strings.Contains(stack, "runtime.goexit") || + strings.Contains(stack, "created by runtime.gc") || + strings.Contains(stack, "created by google3/base/go/log.init") || + strings.Contains(stack, "interestingGoroutines") || + strings.Contains(stack, "runtime.MHeap_Scavenger") || + strings.Contains(stack, "signal.signal_recv") || + strings.Contains(stack, "sigterm.handler") || + strings.Contains(stack, "runtime_mcall") || + strings.Contains(stack, "goroutine in C code") { + continue + } + gs = append(gs, g) + } + sort.Strings(gs) + return +} + +// leakCheck snapshots the currently-running goroutines and returns a +// function to be run at the end of tests to see whether any +// goroutines leaked. +func leakCheck(t testing.TB) func() { + orig := map[string]bool{} + for _, g := range interestingGoroutines() { + orig[g] = true + } + return func() { + // Loop, waiting for goroutines to shut down. + // Wait up to 5 seconds, but finish as quickly as possible. + deadline := time.Now().Add(5 * time.Second) + for { + var leaked []string + for _, g := range interestingGoroutines() { + if !orig[g] { + leaked = append(leaked, g) + } + } + if len(leaked) == 0 { + return + } + if time.Now().Before(deadline) { + time.Sleep(50 * time.Millisecond) + continue + } + for _, g := range leaked { + t.Errorf("Leaked goroutine: %v", g) + } + return + } + } +} + +type lockingWriter struct { + mu sync.Mutex + w io.Writer +} + +func (lw *lockingWriter) Write(p []byte) (n int, err error) { + lw.mu.Lock() + defer lw.mu.Unlock() + return lw.w.Write(p) +} + +func (lw *lockingWriter) setWriter(w io.Writer) { + lw.mu.Lock() + defer lw.mu.Unlock() + lw.w = w +} + +var testLogOutput = &lockingWriter{w: os.Stderr} + +// awaitNewConnLogOutput waits for any of grpc.NewConn's goroutines to +// terminate, if they're still running. It spams logs with this +// message. We wait for it so our log filter is still +// active. Otherwise the "defer restore()" at the top of various test +// functions restores our log filter and then the goroutine spams. +func awaitNewConnLogOutput() { + awaitLogOutput(50*time.Millisecond, "grpc: the client connection is closing; please retry") +} + +func awaitLogOutput(maxWait time.Duration, phrase string) { + pb := []byte(phrase) + + timer := time.NewTimer(maxWait) + defer timer.Stop() + wakeup := make(chan bool, 1) + for { + if logOutputHasContents(pb, wakeup) { + return + } + select { + case <-timer.C: + // Too slow. Oh well. + return + case <-wakeup: + } + } +} + +func logOutputHasContents(v []byte, wakeup chan<- bool) bool { + testLogOutput.mu.Lock() + defer testLogOutput.mu.Unlock() + fw, ok := testLogOutput.w.(*filterWriter) + if !ok { + return false + } + fw.mu.Lock() + defer fw.mu.Unlock() + if bytes.Contains(fw.buf.Bytes(), v) { + return true + } + fw.wakeup = wakeup + return false +} + +func init() { + grpclog.SetLogger(log.New(testLogOutput, "", log.LstdFlags)) +} + +var verboseLogs = flag.Bool("verbose_logs", false, "show all grpclog output, without filtering") + +func noop() {} + +// declareLogNoise declares that t is expected to emit the following noisy phrases, +// even on success. Those phrases will be filtered from grpclog output +// and only be shown if *verbose_logs or t ends up failing. +// The returned restore function should be called with defer to be run +// before the test ends. +func declareLogNoise(t *testing.T, phrases ...string) (restore func()) { + if *verboseLogs { + return noop + } + fw := &filterWriter{dst: os.Stderr, filter: phrases} + testLogOutput.setWriter(fw) + return func() { + if t.Failed() { + fw.mu.Lock() + defer fw.mu.Unlock() + if fw.buf.Len() > 0 { + t.Logf("Complete log output:\n%s", fw.buf.Bytes()) + } + } + testLogOutput.setWriter(os.Stderr) + } +} + +type filterWriter struct { + dst io.Writer + filter []string + + mu sync.Mutex + buf bytes.Buffer + wakeup chan<- bool // if non-nil, gets true on write +} + +func (fw *filterWriter) Write(p []byte) (n int, err error) { + fw.mu.Lock() + fw.buf.Write(p) + if fw.wakeup != nil { + select { + case fw.wakeup <- true: + default: + } + } + fw.mu.Unlock() + + ps := string(p) + for _, f := range fw.filter { + if strings.Contains(ps, f) { + return len(p), nil + } + } + return fw.dst.Write(p) +} + +func equalErrors(l, r error) bool { + return grpc.Code(l) == grpc.Code(r) && grpc.ErrorDesc(l) == grpc.ErrorDesc(r) +} diff --git a/vendor/google.golang.org/grpc/test/grpc_testing/test.pb.go b/vendor/google.golang.org/grpc/test/grpc_testing/test.pb.go new file mode 100644 index 00000000..0ceb12df --- /dev/null +++ b/vendor/google.golang.org/grpc/test/grpc_testing/test.pb.go @@ -0,0 +1,788 @@ +// Code generated by protoc-gen-go. +// source: test.proto +// DO NOT EDIT! + +/* +Package grpc_testing is a generated protocol buffer package. + +It is generated from these files: + test.proto + +It has these top-level messages: + Empty + Payload + SimpleRequest + SimpleResponse + StreamingInputCallRequest + StreamingInputCallResponse + ResponseParameters + StreamingOutputCallRequest + StreamingOutputCallResponse +*/ +package grpc_testing + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The type of payload that should be returned. +type PayloadType int32 + +const ( + // Compressable text format. + PayloadType_COMPRESSABLE PayloadType = 0 + // Uncompressable binary format. + PayloadType_UNCOMPRESSABLE PayloadType = 1 + // Randomly chosen from all other formats defined in this enum. + PayloadType_RANDOM PayloadType = 2 +) + +var PayloadType_name = map[int32]string{ + 0: "COMPRESSABLE", + 1: "UNCOMPRESSABLE", + 2: "RANDOM", +} +var PayloadType_value = map[string]int32{ + "COMPRESSABLE": 0, + "UNCOMPRESSABLE": 1, + "RANDOM": 2, +} + +func (x PayloadType) Enum() *PayloadType { + p := new(PayloadType) + *p = x + return p +} +func (x PayloadType) String() string { + return proto.EnumName(PayloadType_name, int32(x)) +} +func (x *PayloadType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PayloadType_value, data, "PayloadType") + if err != nil { + return err + } + *x = PayloadType(value) + return nil +} +func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type Empty struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// A block of data, to simply increase gRPC message size. +type Payload struct { + // The type of data in body. + Type *PayloadType `protobuf:"varint,1,opt,name=type,enum=grpc.testing.PayloadType" json:"type,omitempty"` + // Primary contents of payload. + Body []byte `protobuf:"bytes,2,opt,name=body" json:"body,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Payload) Reset() { *m = Payload{} } +func (m *Payload) String() string { return proto.CompactTextString(m) } +func (*Payload) ProtoMessage() {} +func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Payload) GetType() PayloadType { + if m != nil && m.Type != nil { + return *m.Type + } + return PayloadType_COMPRESSABLE +} + +func (m *Payload) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +// Unary request. +type SimpleRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + ResponseType *PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + ResponseSize *int32 `protobuf:"varint,2,opt,name=response_size,json=responseSize" json:"response_size,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + // Whether SimpleResponse should include username. + FillUsername *bool `protobuf:"varint,4,opt,name=fill_username,json=fillUsername" json:"fill_username,omitempty"` + // Whether SimpleResponse should include OAuth scope. + FillOauthScope *bool `protobuf:"varint,5,opt,name=fill_oauth_scope,json=fillOauthScope" json:"fill_oauth_scope,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SimpleRequest) Reset() { *m = SimpleRequest{} } +func (m *SimpleRequest) String() string { return proto.CompactTextString(m) } +func (*SimpleRequest) ProtoMessage() {} +func (*SimpleRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *SimpleRequest) GetResponseType() PayloadType { + if m != nil && m.ResponseType != nil { + return *m.ResponseType + } + return PayloadType_COMPRESSABLE +} + +func (m *SimpleRequest) GetResponseSize() int32 { + if m != nil && m.ResponseSize != nil { + return *m.ResponseSize + } + return 0 +} + +func (m *SimpleRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *SimpleRequest) GetFillUsername() bool { + if m != nil && m.FillUsername != nil { + return *m.FillUsername + } + return false +} + +func (m *SimpleRequest) GetFillOauthScope() bool { + if m != nil && m.FillOauthScope != nil { + return *m.FillOauthScope + } + return false +} + +// Unary response, as configured by the request. +type SimpleResponse struct { + // Payload to increase message size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + // The user the request came from, for verifying authentication was + // successful when the client expected it. + Username *string `protobuf:"bytes,2,opt,name=username" json:"username,omitempty"` + // OAuth scope. + OauthScope *string `protobuf:"bytes,3,opt,name=oauth_scope,json=oauthScope" json:"oauth_scope,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SimpleResponse) Reset() { *m = SimpleResponse{} } +func (m *SimpleResponse) String() string { return proto.CompactTextString(m) } +func (*SimpleResponse) ProtoMessage() {} +func (*SimpleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *SimpleResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *SimpleResponse) GetUsername() string { + if m != nil && m.Username != nil { + return *m.Username + } + return "" +} + +func (m *SimpleResponse) GetOauthScope() string { + if m != nil && m.OauthScope != nil { + return *m.OauthScope + } + return "" +} + +// Client-streaming request. +type StreamingInputCallRequest struct { + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingInputCallRequest) Reset() { *m = StreamingInputCallRequest{} } +func (m *StreamingInputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallRequest) ProtoMessage() {} +func (*StreamingInputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *StreamingInputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Client-streaming response. +type StreamingInputCallResponse struct { + // Aggregated size of payloads received from the client. + AggregatedPayloadSize *int32 `protobuf:"varint,1,opt,name=aggregated_payload_size,json=aggregatedPayloadSize" json:"aggregated_payload_size,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingInputCallResponse) Reset() { *m = StreamingInputCallResponse{} } +func (m *StreamingInputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingInputCallResponse) ProtoMessage() {} +func (*StreamingInputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *StreamingInputCallResponse) GetAggregatedPayloadSize() int32 { + if m != nil && m.AggregatedPayloadSize != nil { + return *m.AggregatedPayloadSize + } + return 0 +} + +// Configuration for a particular response. +type ResponseParameters struct { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + Size *int32 `protobuf:"varint,1,opt,name=size" json:"size,omitempty"` + // Desired interval between consecutive responses in the response stream in + // microseconds. + IntervalUs *int32 `protobuf:"varint,2,opt,name=interval_us,json=intervalUs" json:"interval_us,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ResponseParameters) Reset() { *m = ResponseParameters{} } +func (m *ResponseParameters) String() string { return proto.CompactTextString(m) } +func (*ResponseParameters) ProtoMessage() {} +func (*ResponseParameters) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *ResponseParameters) GetSize() int32 { + if m != nil && m.Size != nil { + return *m.Size + } + return 0 +} + +func (m *ResponseParameters) GetIntervalUs() int32 { + if m != nil && m.IntervalUs != nil { + return *m.IntervalUs + } + return 0 +} + +// Server-streaming request. +type StreamingOutputCallRequest struct { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + ResponseType *PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,enum=grpc.testing.PayloadType" json:"response_type,omitempty"` + // Configuration for each expected response message. + ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters,json=responseParameters" json:"response_parameters,omitempty"` + // Optional input payload sent along with the request. + Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingOutputCallRequest) Reset() { *m = StreamingOutputCallRequest{} } +func (m *StreamingOutputCallRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallRequest) ProtoMessage() {} +func (*StreamingOutputCallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *StreamingOutputCallRequest) GetResponseType() PayloadType { + if m != nil && m.ResponseType != nil { + return *m.ResponseType + } + return PayloadType_COMPRESSABLE +} + +func (m *StreamingOutputCallRequest) GetResponseParameters() []*ResponseParameters { + if m != nil { + return m.ResponseParameters + } + return nil +} + +func (m *StreamingOutputCallRequest) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +// Server-streaming response, as configured by the request and parameters. +type StreamingOutputCallResponse struct { + // Payload to increase response size. + Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StreamingOutputCallResponse) Reset() { *m = StreamingOutputCallResponse{} } +func (m *StreamingOutputCallResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingOutputCallResponse) ProtoMessage() {} +func (*StreamingOutputCallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *StreamingOutputCallResponse) GetPayload() *Payload { + if m != nil { + return m.Payload + } + return nil +} + +func init() { + proto.RegisterType((*Empty)(nil), "grpc.testing.Empty") + proto.RegisterType((*Payload)(nil), "grpc.testing.Payload") + proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest") + proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse") + proto.RegisterType((*StreamingInputCallRequest)(nil), "grpc.testing.StreamingInputCallRequest") + proto.RegisterType((*StreamingInputCallResponse)(nil), "grpc.testing.StreamingInputCallResponse") + proto.RegisterType((*ResponseParameters)(nil), "grpc.testing.ResponseParameters") + proto.RegisterType((*StreamingOutputCallRequest)(nil), "grpc.testing.StreamingOutputCallRequest") + proto.RegisterType((*StreamingOutputCallResponse)(nil), "grpc.testing.StreamingOutputCallResponse") + proto.RegisterEnum("grpc.testing.PayloadType", PayloadType_name, PayloadType_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for TestService service + +type TestServiceClient interface { + // One empty request followed by one empty response. + EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) +} + +type testServiceClient struct { + cc *grpc.ClientConn +} + +func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) { + out := new(SimpleResponse) + err := grpc.Invoke(ctx, "/grpc.testing.TestService/UnaryCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[0], c.cc, "/grpc.testing.TestService/StreamingOutputCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceStreamingOutputCallClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TestService_StreamingOutputCallClient interface { + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceStreamingOutputCallClient struct { + grpc.ClientStream +} + +func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[1], c.cc, "/grpc.testing.TestService/StreamingInputCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceStreamingInputCallClient{stream} + return x, nil +} + +type TestService_StreamingInputCallClient interface { + Send(*StreamingInputCallRequest) error + CloseAndRecv() (*StreamingInputCallResponse, error) + grpc.ClientStream +} + +type testServiceStreamingInputCallClient struct { + grpc.ClientStream +} + +func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(StreamingInputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[2], c.cc, "/grpc.testing.TestService/FullDuplexCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceFullDuplexCallClient{stream} + return x, nil +} + +type TestService_FullDuplexCallClient interface { + Send(*StreamingOutputCallRequest) error + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceFullDuplexCallClient struct { + grpc.ClientStream +} + +func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) { + stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[3], c.cc, "/grpc.testing.TestService/HalfDuplexCall", opts...) + if err != nil { + return nil, err + } + x := &testServiceHalfDuplexCallClient{stream} + return x, nil +} + +type TestService_HalfDuplexCallClient interface { + Send(*StreamingOutputCallRequest) error + Recv() (*StreamingOutputCallResponse, error) + grpc.ClientStream +} + +type testServiceHalfDuplexCallClient struct { + grpc.ClientStream +} + +func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) { + m := new(StreamingOutputCallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for TestService service + +type TestServiceServer interface { + // One empty request followed by one empty response. + EmptyCall(context.Context, *Empty) (*Empty, error) + // One request followed by one response. + // The server returns the client payload as-is. + UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + StreamingInputCall(TestService_StreamingInputCallServer) error + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + FullDuplexCall(TestService_FullDuplexCallServer) error + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + HalfDuplexCall(TestService_HalfDuplexCallServer) error +} + +func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { + s.RegisterService(&_TestService_serviceDesc, srv) +} + +func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).EmptyCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.TestService/EmptyCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SimpleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).UnaryCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.testing.TestService/UnaryCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StreamingOutputCallRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream}) +} + +type TestService_StreamingOutputCallServer interface { + Send(*StreamingOutputCallResponse) error + grpc.ServerStream +} + +type testServiceStreamingOutputCallServer struct { + grpc.ServerStream +} + +func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream}) +} + +type TestService_StreamingInputCallServer interface { + SendAndClose(*StreamingInputCallResponse) error + Recv() (*StreamingInputCallRequest, error) + grpc.ServerStream +} + +type testServiceStreamingInputCallServer struct { + grpc.ServerStream +} + +func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) { + m := new(StreamingInputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream}) +} + +type TestService_FullDuplexCallServer interface { + Send(*StreamingOutputCallResponse) error + Recv() (*StreamingOutputCallRequest, error) + grpc.ServerStream +} + +type testServiceFullDuplexCallServer struct { + grpc.ServerStream +} + +func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) { + m := new(StreamingOutputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream}) +} + +type TestService_HalfDuplexCallServer interface { + Send(*StreamingOutputCallResponse) error + Recv() (*StreamingOutputCallRequest, error) + grpc.ServerStream +} + +type testServiceHalfDuplexCallServer struct { + grpc.ServerStream +} + +func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) { + m := new(StreamingOutputCallRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _TestService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.testing.TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EmptyCall", + Handler: _TestService_EmptyCall_Handler, + }, + { + MethodName: "UnaryCall", + Handler: _TestService_UnaryCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamingOutputCall", + Handler: _TestService_StreamingOutputCall_Handler, + ServerStreams: true, + }, + { + StreamName: "StreamingInputCall", + Handler: _TestService_StreamingInputCall_Handler, + ClientStreams: true, + }, + { + StreamName: "FullDuplexCall", + Handler: _TestService_FullDuplexCall_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "HalfDuplexCall", + Handler: _TestService_HalfDuplexCall_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("test.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 567 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x54, 0x51, 0x6f, 0xd2, 0x50, + 0x14, 0xb6, 0x03, 0x64, 0x1c, 0x58, 0x43, 0x0e, 0x59, 0x64, 0x9d, 0x89, 0x4b, 0x7d, 0xb0, 0x9a, + 0x88, 0x86, 0x44, 0x1f, 0x35, 0x73, 0x63, 0x71, 0x09, 0x03, 0x6c, 0xe1, 0x99, 0x5c, 0xe1, 0x0e, + 0x9b, 0x94, 0xb6, 0xb6, 0xb7, 0x46, 0x7c, 0xf0, 0x8f, 0xf9, 0x67, 0xfc, 0x11, 0xfe, 0x00, 0xef, + 0xbd, 0x6d, 0xa1, 0x40, 0x17, 0x99, 0xc6, 0xbd, 0xb5, 0xdf, 0xf9, 0xce, 0x77, 0xbe, 0xef, 0x9e, + 0xdb, 0x02, 0x30, 0x1a, 0xb2, 0x96, 0x1f, 0x78, 0xcc, 0xc3, 0xda, 0x2c, 0xf0, 0x27, 0x2d, 0x01, + 0xd8, 0xee, 0x4c, 0x2f, 0x43, 0xa9, 0x33, 0xf7, 0xd9, 0x42, 0xef, 0x42, 0x79, 0x40, 0x16, 0x8e, + 0x47, 0xa6, 0xf8, 0x1c, 0x8a, 0x6c, 0xe1, 0xd3, 0xa6, 0x72, 0xa2, 0x18, 0x6a, 0xfb, 0xa8, 0x95, + 0x6d, 0x68, 0x25, 0xa4, 0x21, 0x27, 0x98, 0x92, 0x86, 0x08, 0xc5, 0x8f, 0xde, 0x74, 0xd1, 0xdc, + 0xe3, 0xf4, 0x9a, 0x29, 0x9f, 0xf5, 0x5f, 0x0a, 0x1c, 0x58, 0xf6, 0xdc, 0x77, 0xa8, 0x49, 0x3f, + 0x47, 0xbc, 0x15, 0xdf, 0xc0, 0x41, 0x40, 0x43, 0xdf, 0x73, 0x43, 0x3a, 0xde, 0x4d, 0xbd, 0x96, + 0xf2, 0xc5, 0x1b, 0x3e, 0xce, 0xf4, 0x87, 0xf6, 0x37, 0x2a, 0xc7, 0x95, 0x56, 0x24, 0x8b, 0x63, + 0xf8, 0x02, 0xca, 0x7e, 0xac, 0xd0, 0x2c, 0xf0, 0x72, 0xb5, 0x7d, 0x98, 0x2b, 0x6f, 0xa6, 0x2c, + 0xa1, 0x7a, 0x6d, 0x3b, 0xce, 0x38, 0x0a, 0x69, 0xe0, 0x92, 0x39, 0x6d, 0x16, 0x79, 0xdb, 0xbe, + 0x59, 0x13, 0xe0, 0x28, 0xc1, 0xd0, 0x80, 0xba, 0x24, 0x79, 0x24, 0x62, 0x9f, 0xc6, 0xe1, 0xc4, + 0xe3, 0xee, 0x4b, 0x92, 0xa7, 0x0a, 0xbc, 0x2f, 0x60, 0x4b, 0xa0, 0xfa, 0x77, 0x50, 0xd3, 0xd4, + 0xb1, 0xab, 0xac, 0x23, 0x65, 0x27, 0x47, 0x1a, 0xec, 0x2f, 0xcd, 0x88, 0x88, 0x15, 0x73, 0xf9, + 0x8e, 0x8f, 0xa0, 0x9a, 0xf5, 0x50, 0x90, 0x65, 0xf0, 0x56, 0xf3, 0xbb, 0x70, 0x64, 0xb1, 0x80, + 0x92, 0x39, 0x97, 0xbe, 0x74, 0xfd, 0x88, 0x9d, 0x11, 0xc7, 0x49, 0x37, 0x70, 0x5b, 0x2b, 0xfa, + 0x10, 0xb4, 0x3c, 0xb5, 0x24, 0xd9, 0x6b, 0x78, 0x40, 0x66, 0xb3, 0x80, 0xce, 0x08, 0xa3, 0xd3, + 0x71, 0xd2, 0x13, 0xaf, 0x46, 0x91, 0xab, 0x39, 0x5c, 0x95, 0x13, 0x69, 0xb1, 0x23, 0xfd, 0x12, + 0x30, 0xd5, 0x18, 0x90, 0x80, 0xc7, 0x62, 0x34, 0x08, 0xc5, 0x25, 0xca, 0xb4, 0xca, 0x67, 0x11, + 0xd7, 0x76, 0x79, 0xf5, 0x0b, 0x11, 0x0b, 0x4a, 0x16, 0x0e, 0x29, 0x34, 0x0a, 0xf5, 0x9f, 0x4a, + 0xc6, 0x61, 0x3f, 0x62, 0x1b, 0x81, 0xff, 0xf5, 0xca, 0x7d, 0x80, 0xc6, 0xb2, 0xdf, 0x5f, 0x5a, + 0xe5, 0x3e, 0x0a, 0xfc, 0xf0, 0x4e, 0xd6, 0x55, 0xb6, 0x23, 0x99, 0x18, 0x6c, 0xc7, 0xbc, 0xed, + 0x05, 0xd5, 0x7b, 0x70, 0x9c, 0x9b, 0xf0, 0x2f, 0xaf, 0xd7, 0xb3, 0xb7, 0x50, 0xcd, 0x04, 0xc6, + 0x3a, 0xd4, 0xce, 0xfa, 0x57, 0x03, 0xb3, 0x63, 0x59, 0xa7, 0xef, 0xba, 0x9d, 0xfa, 0x3d, 0xbe, + 0x08, 0x75, 0xd4, 0x5b, 0xc3, 0x14, 0x04, 0xb8, 0x6f, 0x9e, 0xf6, 0xce, 0xfb, 0x57, 0xf5, 0xbd, + 0xf6, 0x8f, 0x22, 0x54, 0x87, 0x5c, 0xdd, 0xe2, 0x4b, 0xb0, 0x27, 0x14, 0x5f, 0x41, 0x45, 0xfe, + 0x40, 0x84, 0x2d, 0x6c, 0xac, 0x4f, 0x97, 0x05, 0x2d, 0x0f, 0xc4, 0x0b, 0xa8, 0x8c, 0x5c, 0x12, + 0xc4, 0x6d, 0xc7, 0xeb, 0x8c, 0xb5, 0x1f, 0x87, 0xf6, 0x30, 0xbf, 0x98, 0x1c, 0x80, 0x03, 0x8d, + 0x9c, 0xf3, 0x41, 0x63, 0xa3, 0xe9, 0xc6, 0x4b, 0xa2, 0x3d, 0xdd, 0x81, 0x19, 0xcf, 0x7a, 0xa9, + 0xa0, 0x0d, 0xb8, 0xfd, 0x45, 0xe0, 0x93, 0x1b, 0x24, 0x36, 0xbf, 0x40, 0xcd, 0xf8, 0x33, 0x31, + 0x1e, 0x65, 0x88, 0x51, 0xea, 0x45, 0xe4, 0x38, 0xe7, 0x11, 0x4f, 0xfb, 0xf5, 0xbf, 0x65, 0x32, + 0x14, 0x99, 0x4a, 0x7d, 0x4f, 0x9c, 0xeb, 0x3b, 0x18, 0xf5, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x4c, + 0x41, 0xfe, 0xb6, 0x89, 0x06, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/grpc/test/grpc_testing/test.proto b/vendor/google.golang.org/grpc/test/grpc_testing/test.proto new file mode 100644 index 00000000..b5bfe053 --- /dev/null +++ b/vendor/google.golang.org/grpc/test/grpc_testing/test.proto @@ -0,0 +1,140 @@ +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +syntax = "proto2"; + +package grpc.testing; + +message Empty {} + +// The type of payload that should be returned. +enum PayloadType { + // Compressable text format. + COMPRESSABLE = 0; + + // Uncompressable binary format. + UNCOMPRESSABLE = 1; + + // Randomly chosen from all other formats defined in this enum. + RANDOM = 2; +} + +// A block of data, to simply increase gRPC message size. +message Payload { + // The type of data in body. + optional PayloadType type = 1; + // Primary contents of payload. + optional bytes body = 2; +} + +// Unary request. +message SimpleRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + optional PayloadType response_type = 1; + + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + optional int32 response_size = 2; + + // Optional input payload sent along with the request. + optional Payload payload = 3; + + // Whether SimpleResponse should include username. + optional bool fill_username = 4; + + // Whether SimpleResponse should include OAuth scope. + optional bool fill_oauth_scope = 5; +} + +// Unary response, as configured by the request. +message SimpleResponse { + // Payload to increase message size. + optional Payload payload = 1; + + // The user the request came from, for verifying authentication was + // successful when the client expected it. + optional string username = 2; + + // OAuth scope. + optional string oauth_scope = 3; +} + +// Client-streaming request. +message StreamingInputCallRequest { + // Optional input payload sent along with the request. + optional Payload payload = 1; + + // Not expecting any payload from the response. +} + +// Client-streaming response. +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + optional int32 aggregated_payload_size = 1; +} + +// Configuration for a particular response. +message ResponseParameters { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + optional int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + optional int32 interval_us = 2; +} + +// Server-streaming request. +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + optional PayloadType response_type = 1; + + // Configuration for each expected response message. + repeated ResponseParameters response_parameters = 2; + + // Optional input payload sent along with the request. + optional Payload payload = 3; +} + +// Server-streaming response, as configured by the request and parameters. +message StreamingOutputCallResponse { + // Payload to increase response size. + optional Payload payload = 1; +} + +// A simple service to test the various types of RPCs and experiment with +// performance with various types of payload. +service TestService { + // One empty request followed by one empty response. + rpc EmptyCall(Empty) returns (Empty); + + // One request followed by one response. + // The server returns the client payload as-is. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + rpc StreamingOutputCall(StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + rpc StreamingInputCall(stream StreamingInputCallRequest) + returns (StreamingInputCallResponse); + + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + rpc FullDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + rpc HalfDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); +} diff --git a/vendor/google.golang.org/grpc/test/race_test.go b/vendor/google.golang.org/grpc/test/race_test.go new file mode 100644 index 00000000..b3a7056c --- /dev/null +++ b/vendor/google.golang.org/grpc/test/race_test.go @@ -0,0 +1,39 @@ +// +build race + +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc_test + +func init() { + raceMode = true +} diff --git a/vendor/google.golang.org/grpc/test/servertester_test.go b/vendor/google.golang.org/grpc/test/servertester_test.go new file mode 100644 index 00000000..0225a857 --- /dev/null +++ b/vendor/google.golang.org/grpc/test/servertester_test.go @@ -0,0 +1,289 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package grpc_test + +import ( + "bytes" + "errors" + "io" + "strings" + "testing" + "time" + + "golang.org/x/net/http2" + "golang.org/x/net/http2/hpack" +) + +// This is a subset of http2's serverTester type. +// +// serverTester wraps a io.ReadWriter (acting like the underlying +// network connection) and provides utility methods to read and write +// http2 frames. +// +// NOTE(bradfitz): this could eventually be exported somewhere. Others +// have asked for it too. For now I'm still experimenting with the +// API and don't feel like maintaining a stable testing API. + +type serverTester struct { + cc io.ReadWriteCloser // client conn + t testing.TB + fr *http2.Framer + + // writing headers: + headerBuf bytes.Buffer + hpackEnc *hpack.Encoder + + // reading frames: + frc chan http2.Frame + frErrc chan error + readTimer *time.Timer +} + +func newServerTesterFromConn(t testing.TB, cc io.ReadWriteCloser) *serverTester { + st := &serverTester{ + t: t, + cc: cc, + frc: make(chan http2.Frame, 1), + frErrc: make(chan error, 1), + } + st.hpackEnc = hpack.NewEncoder(&st.headerBuf) + st.fr = http2.NewFramer(cc, cc) + st.fr.ReadMetaHeaders = hpack.NewDecoder(4096 /*initialHeaderTableSize*/, nil) + + return st +} + +func (st *serverTester) readFrame() (http2.Frame, error) { + go func() { + fr, err := st.fr.ReadFrame() + if err != nil { + st.frErrc <- err + } else { + st.frc <- fr + } + }() + t := time.NewTimer(2 * time.Second) + defer t.Stop() + select { + case f := <-st.frc: + return f, nil + case err := <-st.frErrc: + return nil, err + case <-t.C: + return nil, errors.New("timeout waiting for frame") + } +} + +// greet initiates the client's HTTP/2 connection into a state where +// frames may be sent. +func (st *serverTester) greet() { + st.writePreface() + st.writeInitialSettings() + st.wantSettings() + st.writeSettingsAck() + for { + f, err := st.readFrame() + if err != nil { + st.t.Fatal(err) + } + switch f := f.(type) { + case *http2.WindowUpdateFrame: + // grpc's transport/http2_server sends this + // before the settings ack. The Go http2 + // server uses a setting instead. + case *http2.SettingsFrame: + if f.IsAck() { + return + } + st.t.Fatalf("during greet, got non-ACK settings frame") + default: + st.t.Fatalf("during greet, unexpected frame type %T", f) + } + } +} + +func (st *serverTester) writePreface() { + n, err := st.cc.Write([]byte(http2.ClientPreface)) + if err != nil { + st.t.Fatalf("Error writing client preface: %v", err) + } + if n != len(http2.ClientPreface) { + st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(http2.ClientPreface)) + } +} + +func (st *serverTester) writeInitialSettings() { + if err := st.fr.WriteSettings(); err != nil { + st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err) + } +} + +func (st *serverTester) writeSettingsAck() { + if err := st.fr.WriteSettingsAck(); err != nil { + st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err) + } +} + +func (st *serverTester) wantSettings() *http2.SettingsFrame { + f, err := st.readFrame() + if err != nil { + st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err) + } + sf, ok := f.(*http2.SettingsFrame) + if !ok { + st.t.Fatalf("got a %T; want *SettingsFrame", f) + } + return sf +} + +func (st *serverTester) wantSettingsAck() { + f, err := st.readFrame() + if err != nil { + st.t.Fatal(err) + } + sf, ok := f.(*http2.SettingsFrame) + if !ok { + st.t.Fatalf("Wanting a settings ACK, received a %T", f) + } + if !sf.IsAck() { + st.t.Fatal("Settings Frame didn't have ACK set") + } +} + +// wait for any activity from the server +func (st *serverTester) wantAnyFrame() http2.Frame { + f, err := st.fr.ReadFrame() + if err != nil { + st.t.Fatal(err) + } + return f +} + +func (st *serverTester) encodeHeaderField(k, v string) { + err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v}) + if err != nil { + st.t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err) + } +} + +// encodeHeader encodes headers and returns their HPACK bytes. headers +// must contain an even number of key/value pairs. There may be +// multiple pairs for keys (e.g. "cookie"). The :method, :path, and +// :scheme headers default to GET, / and https. +func (st *serverTester) encodeHeader(headers ...string) []byte { + if len(headers)%2 == 1 { + panic("odd number of kv args") + } + + st.headerBuf.Reset() + + if len(headers) == 0 { + // Fast path, mostly for benchmarks, so test code doesn't pollute + // profiles when we're looking to improve server allocations. + st.encodeHeaderField(":method", "GET") + st.encodeHeaderField(":path", "/") + st.encodeHeaderField(":scheme", "https") + return st.headerBuf.Bytes() + } + + if len(headers) == 2 && headers[0] == ":method" { + // Another fast path for benchmarks. + st.encodeHeaderField(":method", headers[1]) + st.encodeHeaderField(":path", "/") + st.encodeHeaderField(":scheme", "https") + return st.headerBuf.Bytes() + } + + pseudoCount := map[string]int{} + keys := []string{":method", ":path", ":scheme"} + vals := map[string][]string{ + ":method": {"GET"}, + ":path": {"/"}, + ":scheme": {"https"}, + } + for len(headers) > 0 { + k, v := headers[0], headers[1] + headers = headers[2:] + if _, ok := vals[k]; !ok { + keys = append(keys, k) + } + if strings.HasPrefix(k, ":") { + pseudoCount[k]++ + if pseudoCount[k] == 1 { + vals[k] = []string{v} + } else { + // Allows testing of invalid headers w/ dup pseudo fields. + vals[k] = append(vals[k], v) + } + } else { + vals[k] = append(vals[k], v) + } + } + for _, k := range keys { + for _, v := range vals[k] { + st.encodeHeaderField(k, v) + } + } + return st.headerBuf.Bytes() +} + +func (st *serverTester) writeHeadersGRPC(streamID uint32, path string) { + st.writeHeaders(http2.HeadersFrameParam{ + StreamID: streamID, + BlockFragment: st.encodeHeader( + ":method", "POST", + ":path", path, + "content-type", "application/grpc", + "te", "trailers", + ), + EndStream: false, + EndHeaders: true, + }) +} + +func (st *serverTester) writeHeaders(p http2.HeadersFrameParam) { + if err := st.fr.WriteHeaders(p); err != nil { + st.t.Fatalf("Error writing HEADERS: %v", err) + } +} + +func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) { + if err := st.fr.WriteData(streamID, endStream, data); err != nil { + st.t.Fatalf("Error writing DATA: %v", err) + } +} + +func (st *serverTester) writeRSTStream(streamID uint32, code http2.ErrCode) { + if err := st.fr.WriteRSTStream(streamID, code); err != nil { + st.t.Fatalf("Error writing RST_STREAM: %v", err) + } +} diff --git a/vendor/google.golang.org/grpc/test/testdata/ca.pem b/vendor/google.golang.org/grpc/test/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/test/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/test/testdata/server1.key b/vendor/google.golang.org/grpc/test/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/test/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/test/testdata/server1.pem b/vendor/google.golang.org/grpc/test/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/test/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/testdata/ca.pem b/vendor/google.golang.org/grpc/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/testdata/server1.key b/vendor/google.golang.org/grpc/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/testdata/server1.pem b/vendor/google.golang.org/grpc/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/trace.go b/vendor/google.golang.org/grpc/trace.go new file mode 100644 index 00000000..f6747e1d --- /dev/null +++ b/vendor/google.golang.org/grpc/trace.go @@ -0,0 +1,119 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package grpc + +import ( + "bytes" + "fmt" + "io" + "net" + "strings" + "time" + + "golang.org/x/net/trace" +) + +// EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package. +// This should only be set before any RPCs are sent or received by this program. +var EnableTracing = true + +// methodFamily returns the trace family for the given method. +// It turns "/pkg.Service/GetFoo" into "pkg.Service". +func methodFamily(m string) string { + m = strings.TrimPrefix(m, "/") // remove leading slash + if i := strings.Index(m, "/"); i >= 0 { + m = m[:i] // remove everything from second slash + } + if i := strings.LastIndex(m, "."); i >= 0 { + m = m[i+1:] // cut down to last dotted component + } + return m +} + +// traceInfo contains tracing information for an RPC. +type traceInfo struct { + tr trace.Trace + firstLine firstLine +} + +// firstLine is the first line of an RPC trace. +type firstLine struct { + client bool // whether this is a client (outgoing) RPC + remoteAddr net.Addr + deadline time.Duration // may be zero +} + +func (f *firstLine) String() string { + var line bytes.Buffer + io.WriteString(&line, "RPC: ") + if f.client { + io.WriteString(&line, "to") + } else { + io.WriteString(&line, "from") + } + fmt.Fprintf(&line, " %v deadline:", f.remoteAddr) + if f.deadline != 0 { + fmt.Fprint(&line, f.deadline) + } else { + io.WriteString(&line, "none") + } + return line.String() +} + +// payload represents an RPC request or response payload. +type payload struct { + sent bool // whether this is an outgoing payload + msg interface{} // e.g. a proto.Message + // TODO(dsymonds): add stringifying info to codec, and limit how much we hold here? +} + +func (p payload) String() string { + if p.sent { + return fmt.Sprintf("sent: %v", p.msg) + } + return fmt.Sprintf("recv: %v", p.msg) +} + +type fmtStringer struct { + format string + a []interface{} +} + +func (f *fmtStringer) String() string { + return fmt.Sprintf(f.format, f.a...) +} + +type stringer string + +func (s stringer) String() string { return string(s) } diff --git a/vendor/google.golang.org/grpc/transport/control.go b/vendor/google.golang.org/grpc/transport/control.go new file mode 100644 index 00000000..7e9bdf33 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/control.go @@ -0,0 +1,210 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "fmt" + "sync" + + "golang.org/x/net/http2" +) + +const ( + // The default value of flow control window size in HTTP2 spec. + defaultWindowSize = 65535 + // The initial window size for flow control. + initialWindowSize = defaultWindowSize // for an RPC + initialConnWindowSize = defaultWindowSize * 16 // for a connection +) + +// The following defines various control items which could flow through +// the control buffer of transport. They represent different aspects of +// control tasks, e.g., flow control, settings, streaming resetting, etc. +type windowUpdate struct { + streamID uint32 + increment uint32 +} + +func (*windowUpdate) item() {} + +type settings struct { + ack bool + ss []http2.Setting +} + +func (*settings) item() {} + +type resetStream struct { + streamID uint32 + code http2.ErrCode +} + +func (*resetStream) item() {} + +type flushIO struct { +} + +func (*flushIO) item() {} + +type ping struct { + ack bool + data [8]byte +} + +func (*ping) item() {} + +// quotaPool is a pool which accumulates the quota and sends it to acquire() +// when it is available. +type quotaPool struct { + c chan int + + mu sync.Mutex + quota int +} + +// newQuotaPool creates a quotaPool which has quota q available to consume. +func newQuotaPool(q int) *quotaPool { + qb := "aPool{ + c: make(chan int, 1), + } + if q > 0 { + qb.c <- q + } else { + qb.quota = q + } + return qb +} + +// add adds n to the available quota and tries to send it on acquire. +func (qb *quotaPool) add(n int) { + qb.mu.Lock() + defer qb.mu.Unlock() + qb.quota += n + if qb.quota <= 0 { + return + } + select { + case qb.c <- qb.quota: + qb.quota = 0 + default: + } +} + +// cancel cancels the pending quota sent on acquire, if any. +func (qb *quotaPool) cancel() { + qb.mu.Lock() + defer qb.mu.Unlock() + select { + case n := <-qb.c: + qb.quota += n + default: + } +} + +// reset cancels the pending quota sent on acquired, incremented by v and sends +// it back on acquire. +func (qb *quotaPool) reset(v int) { + qb.mu.Lock() + defer qb.mu.Unlock() + select { + case n := <-qb.c: + qb.quota += n + default: + } + qb.quota += v + if qb.quota <= 0 { + return + } + select { + case qb.c <- qb.quota: + qb.quota = 0 + default: + } +} + +// acquire returns the channel on which available quota amounts are sent. +func (qb *quotaPool) acquire() <-chan int { + return qb.c +} + +// inFlow deals with inbound flow control +type inFlow struct { + // The inbound flow control limit for pending data. + limit uint32 + + mu sync.Mutex + // pendingData is the overall data which have been received but not been + // consumed by applications. + pendingData uint32 + // The amount of data the application has consumed but grpc has not sent + // window update for them. Used to reduce window update frequency. + pendingUpdate uint32 +} + +// onData is invoked when some data frame is received. It updates pendingData. +func (f *inFlow) onData(n uint32) error { + f.mu.Lock() + defer f.mu.Unlock() + f.pendingData += n + if f.pendingData+f.pendingUpdate > f.limit { + return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", f.pendingData+f.pendingUpdate, f.limit) + } + return nil +} + +// onRead is invoked when the application reads the data. It returns the window size +// to be sent to the peer. +func (f *inFlow) onRead(n uint32) uint32 { + f.mu.Lock() + defer f.mu.Unlock() + if f.pendingData == 0 { + return 0 + } + f.pendingData -= n + f.pendingUpdate += n + if f.pendingUpdate >= f.limit/4 { + wu := f.pendingUpdate + f.pendingUpdate = 0 + return wu + } + return 0 +} + +func (f *inFlow) resetPendingData() uint32 { + f.mu.Lock() + defer f.mu.Unlock() + n := f.pendingData + f.pendingData = 0 + return n +} diff --git a/vendor/google.golang.org/grpc/transport/handler_server.go b/vendor/google.golang.org/grpc/transport/handler_server.go new file mode 100644 index 00000000..4b0d5252 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/handler_server.go @@ -0,0 +1,393 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// This file is the implementation of a gRPC server using HTTP/2 which +// uses the standard Go http2 Server implementation (via the +// http.Handler interface), rather than speaking low-level HTTP/2 +// frames itself. It is the implementation of *grpc.Server.ServeHTTP. + +package transport + +import ( + "errors" + "fmt" + "io" + "net" + "net/http" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/http2" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" +) + +// NewServerHandlerTransport returns a ServerTransport handling gRPC +// from inside an http.Handler. It requires that the http Server +// supports HTTP/2. +func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTransport, error) { + if r.ProtoMajor != 2 { + return nil, errors.New("gRPC requires HTTP/2") + } + if r.Method != "POST" { + return nil, errors.New("invalid gRPC request method") + } + if !validContentType(r.Header.Get("Content-Type")) { + return nil, errors.New("invalid gRPC request content-type") + } + if _, ok := w.(http.Flusher); !ok { + return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher") + } + if _, ok := w.(http.CloseNotifier); !ok { + return nil, errors.New("gRPC requires a ResponseWriter supporting http.CloseNotifier") + } + + st := &serverHandlerTransport{ + rw: w, + req: r, + closedCh: make(chan struct{}), + writes: make(chan func()), + } + + if v := r.Header.Get("grpc-timeout"); v != "" { + to, err := timeoutDecode(v) + if err != nil { + return nil, StreamErrorf(codes.Internal, "malformed time-out: %v", err) + } + st.timeoutSet = true + st.timeout = to + } + + var metakv []string + if r.Host != "" { + metakv = append(metakv, ":authority", r.Host) + } + for k, vv := range r.Header { + k = strings.ToLower(k) + if isReservedHeader(k) && !isWhitelistedPseudoHeader(k) { + continue + } + for _, v := range vv { + if k == "user-agent" { + // user-agent is special. Copying logic of http_util.go. + if i := strings.LastIndex(v, " "); i == -1 { + // There is no application user agent string being set + continue + } else { + v = v[:i] + } + } + metakv = append(metakv, k, v) + } + } + st.headerMD = metadata.Pairs(metakv...) + + return st, nil +} + +// serverHandlerTransport is an implementation of ServerTransport +// which replies to exactly one gRPC request (exactly one HTTP request), +// using the net/http.Handler interface. This http.Handler is guaranteed +// at this point to be speaking over HTTP/2, so it's able to speak valid +// gRPC. +type serverHandlerTransport struct { + rw http.ResponseWriter + req *http.Request + timeoutSet bool + timeout time.Duration + didCommonHeaders bool + + headerMD metadata.MD + + closeOnce sync.Once + closedCh chan struct{} // closed on Close + + // writes is a channel of code to run serialized in the + // ServeHTTP (HandleStreams) goroutine. The channel is closed + // when WriteStatus is called. + writes chan func() +} + +func (ht *serverHandlerTransport) Close() error { + ht.closeOnce.Do(ht.closeCloseChanOnce) + return nil +} + +func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) } + +func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) } + +// strAddr is a net.Addr backed by either a TCP "ip:port" string, or +// the empty string if unknown. +type strAddr string + +func (a strAddr) Network() string { + if a != "" { + // Per the documentation on net/http.Request.RemoteAddr, if this is + // set, it's set to the IP:port of the peer (hence, TCP): + // https://golang.org/pkg/net/http/#Request + // + // If we want to support Unix sockets later, we can + // add our own grpc-specific convention within the + // grpc codebase to set RemoteAddr to a different + // format, or probably better: we can attach it to the + // context and use that from serverHandlerTransport.RemoteAddr. + return "tcp" + } + return "" +} + +func (a strAddr) String() string { return string(a) } + +// do runs fn in the ServeHTTP goroutine. +func (ht *serverHandlerTransport) do(fn func()) error { + select { + case ht.writes <- fn: + return nil + case <-ht.closedCh: + return ErrConnClosing + } +} + +func (ht *serverHandlerTransport) WriteStatus(s *Stream, statusCode codes.Code, statusDesc string) error { + err := ht.do(func() { + ht.writeCommonHeaders(s) + + // And flush, in case no header or body has been sent yet. + // This forces a separation of headers and trailers if this is the + // first call (for example, in end2end tests's TestNoService). + ht.rw.(http.Flusher).Flush() + + h := ht.rw.Header() + h.Set("Grpc-Status", fmt.Sprintf("%d", statusCode)) + if statusDesc != "" { + h.Set("Grpc-Message", statusDesc) + } + if md := s.Trailer(); len(md) > 0 { + for k, vv := range md { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } + for _, v := range vv { + // http2 ResponseWriter mechanism to + // send undeclared Trailers after the + // headers have possibly been written. + h.Add(http2.TrailerPrefix+k, v) + } + } + } + }) + close(ht.writes) + return err +} + +// writeCommonHeaders sets common headers on the first write +// call (Write, WriteHeader, or WriteStatus). +func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) { + if ht.didCommonHeaders { + return + } + ht.didCommonHeaders = true + + h := ht.rw.Header() + h["Date"] = nil // suppress Date to make tests happy; TODO: restore + h.Set("Content-Type", "application/grpc") + + // Predeclare trailers we'll set later in WriteStatus (after the body). + // This is a SHOULD in the HTTP RFC, and the way you add (known) + // Trailers per the net/http.ResponseWriter contract. + // See https://golang.org/pkg/net/http/#ResponseWriter + // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers + h.Add("Trailer", "Grpc-Status") + h.Add("Trailer", "Grpc-Message") + + if s.sendCompress != "" { + h.Set("Grpc-Encoding", s.sendCompress) + } +} + +func (ht *serverHandlerTransport) Write(s *Stream, data []byte, opts *Options) error { + return ht.do(func() { + ht.writeCommonHeaders(s) + ht.rw.Write(data) + if !opts.Delay { + ht.rw.(http.Flusher).Flush() + } + }) +} + +func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error { + return ht.do(func() { + ht.writeCommonHeaders(s) + h := ht.rw.Header() + for k, vv := range md { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } + for _, v := range vv { + h.Add(k, v) + } + } + ht.rw.WriteHeader(200) + ht.rw.(http.Flusher).Flush() + }) +} + +func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) { + // With this transport type there will be exactly 1 stream: this HTTP request. + + var ctx context.Context + var cancel context.CancelFunc + if ht.timeoutSet { + ctx, cancel = context.WithTimeout(context.Background(), ht.timeout) + } else { + ctx, cancel = context.WithCancel(context.Background()) + } + + // requestOver is closed when either the request's context is done + // or the status has been written via WriteStatus. + requestOver := make(chan struct{}) + + // clientGone receives a single value if peer is gone, either + // because the underlying connection is dead or because the + // peer sends an http2 RST_STREAM. + clientGone := ht.rw.(http.CloseNotifier).CloseNotify() + go func() { + select { + case <-requestOver: + return + case <-ht.closedCh: + case <-clientGone: + } + cancel() + }() + + req := ht.req + + s := &Stream{ + id: 0, // irrelevant + windowHandler: func(int) {}, // nothing + cancel: cancel, + buf: newRecvBuffer(), + st: ht, + method: req.URL.Path, + recvCompress: req.Header.Get("grpc-encoding"), + } + pr := &peer.Peer{ + Addr: ht.RemoteAddr(), + } + if req.TLS != nil { + pr.AuthInfo = credentials.TLSInfo{State: *req.TLS} + } + ctx = metadata.NewContext(ctx, ht.headerMD) + ctx = peer.NewContext(ctx, pr) + s.ctx = newContextWithStream(ctx, s) + s.dec = &recvBufferReader{ctx: s.ctx, recv: s.buf} + + // readerDone is closed when the Body.Read-ing goroutine exits. + readerDone := make(chan struct{}) + go func() { + defer close(readerDone) + + // TODO: minimize garbage, optimize recvBuffer code/ownership + const readSize = 8196 + for buf := make([]byte, readSize); ; { + n, err := req.Body.Read(buf) + if n > 0 { + s.buf.put(&recvMsg{data: buf[:n:n]}) + buf = buf[n:] + } + if err != nil { + s.buf.put(&recvMsg{err: mapRecvMsgError(err)}) + return + } + if len(buf) == 0 { + buf = make([]byte, readSize) + } + } + }() + + // startStream is provided by the *grpc.Server's serveStreams. + // It starts a goroutine serving s and exits immediately. + // The goroutine that is started is the one that then calls + // into ht, calling WriteHeader, Write, WriteStatus, Close, etc. + startStream(s) + + ht.runStream() + close(requestOver) + + // Wait for reading goroutine to finish. + req.Body.Close() + <-readerDone +} + +func (ht *serverHandlerTransport) runStream() { + for { + select { + case fn, ok := <-ht.writes: + if !ok { + return + } + fn() + case <-ht.closedCh: + return + } + } +} + +// mapRecvMsgError returns the non-nil err into the appropriate +// error value as expected by callers of *grpc.parser.recvMsg. +// In particular, in can only be: +// * io.EOF +// * io.ErrUnexpectedEOF +// * of type transport.ConnectionError +// * of type transport.StreamError +func mapRecvMsgError(err error) error { + if err == io.EOF || err == io.ErrUnexpectedEOF { + return err + } + if se, ok := err.(http2.StreamError); ok { + if code, ok := http2ErrConvTab[se.Code]; ok { + return StreamError{ + Code: code, + Desc: se.Error(), + } + } + } + return ConnectionError{Desc: err.Error()} +} diff --git a/vendor/google.golang.org/grpc/transport/handler_server_test.go b/vendor/google.golang.org/grpc/transport/handler_server_test.go new file mode 100644 index 00000000..1fee72ff --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/handler_server_test.go @@ -0,0 +1,389 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "net/url" + "reflect" + "testing" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" +) + +func TestHandlerTransport_NewServerHandlerTransport(t *testing.T) { + type testCase struct { + name string + req *http.Request + wantErr string + modrw func(http.ResponseWriter) http.ResponseWriter + check func(*serverHandlerTransport, *testCase) error + } + tests := []testCase{ + { + name: "http/1.1", + req: &http.Request{ + ProtoMajor: 1, + ProtoMinor: 1, + }, + wantErr: "gRPC requires HTTP/2", + }, + { + name: "bad method", + req: &http.Request{ + ProtoMajor: 2, + Method: "GET", + Header: http.Header{}, + RequestURI: "/", + }, + wantErr: "invalid gRPC request method", + }, + { + name: "bad content type", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/foo"}, + }, + RequestURI: "/service/foo.bar", + }, + wantErr: "invalid gRPC request content-type", + }, + { + name: "not flusher", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/grpc"}, + }, + RequestURI: "/service/foo.bar", + }, + modrw: func(w http.ResponseWriter) http.ResponseWriter { + // Return w without its Flush method + type onlyCloseNotifier interface { + http.ResponseWriter + http.CloseNotifier + } + return struct{ onlyCloseNotifier }{w.(onlyCloseNotifier)} + }, + wantErr: "gRPC requires a ResponseWriter supporting http.Flusher", + }, + { + name: "not closenotifier", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/grpc"}, + }, + RequestURI: "/service/foo.bar", + }, + modrw: func(w http.ResponseWriter) http.ResponseWriter { + // Return w without its CloseNotify method + type onlyFlusher interface { + http.ResponseWriter + http.Flusher + } + return struct{ onlyFlusher }{w.(onlyFlusher)} + }, + wantErr: "gRPC requires a ResponseWriter supporting http.CloseNotifier", + }, + { + name: "valid", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/grpc"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + }, + check: func(t *serverHandlerTransport, tt *testCase) error { + if t.req != tt.req { + return fmt.Errorf("t.req = %p; want %p", t.req, tt.req) + } + if t.rw == nil { + return errors.New("t.rw = nil; want non-nil") + } + return nil + }, + }, + { + name: "with timeout", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": []string{"application/grpc"}, + "Grpc-Timeout": {"200m"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + }, + check: func(t *serverHandlerTransport, tt *testCase) error { + if !t.timeoutSet { + return errors.New("timeout not set") + } + if want := 200 * time.Millisecond; t.timeout != want { + return fmt.Errorf("timeout = %v; want %v", t.timeout, want) + } + return nil + }, + }, + { + name: "with bad timeout", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": []string{"application/grpc"}, + "Grpc-Timeout": {"tomorrow"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + }, + wantErr: `stream error: code = 13 desc = "malformed time-out: transport: timeout unit is not recognized: \"tomorrow\""`, + }, + { + name: "with metadata", + req: &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": []string{"application/grpc"}, + "meta-foo": {"foo-val"}, + "meta-bar": {"bar-val1", "bar-val2"}, + "user-agent": {"x/y a/b"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + }, + check: func(ht *serverHandlerTransport, tt *testCase) error { + want := metadata.MD{ + "meta-bar": {"bar-val1", "bar-val2"}, + "user-agent": {"x/y"}, + "meta-foo": {"foo-val"}, + } + if !reflect.DeepEqual(ht.headerMD, want) { + return fmt.Errorf("metdata = %#v; want %#v", ht.headerMD, want) + } + return nil + }, + }, + } + + for _, tt := range tests { + rw := newTestHandlerResponseWriter() + if tt.modrw != nil { + rw = tt.modrw(rw) + } + got, gotErr := NewServerHandlerTransport(rw, tt.req) + if (gotErr != nil) != (tt.wantErr != "") || (gotErr != nil && gotErr.Error() != tt.wantErr) { + t.Errorf("%s: error = %v; want %q", tt.name, gotErr, tt.wantErr) + continue + } + if gotErr != nil { + continue + } + if tt.check != nil { + if err := tt.check(got.(*serverHandlerTransport), &tt); err != nil { + t.Errorf("%s: %v", tt.name, err) + } + } + } +} + +type testHandlerResponseWriter struct { + *httptest.ResponseRecorder + closeNotify chan bool +} + +func (w testHandlerResponseWriter) CloseNotify() <-chan bool { return w.closeNotify } +func (w testHandlerResponseWriter) Flush() {} + +func newTestHandlerResponseWriter() http.ResponseWriter { + return testHandlerResponseWriter{ + ResponseRecorder: httptest.NewRecorder(), + closeNotify: make(chan bool, 1), + } +} + +type handleStreamTest struct { + t *testing.T + bodyw *io.PipeWriter + req *http.Request + rw testHandlerResponseWriter + ht *serverHandlerTransport +} + +func newHandleStreamTest(t *testing.T) *handleStreamTest { + bodyr, bodyw := io.Pipe() + req := &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/grpc"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + Body: bodyr, + } + rw := newTestHandlerResponseWriter().(testHandlerResponseWriter) + ht, err := NewServerHandlerTransport(rw, req) + if err != nil { + t.Fatal(err) + } + return &handleStreamTest{ + t: t, + bodyw: bodyw, + ht: ht.(*serverHandlerTransport), + rw: rw, + } +} + +func TestHandlerTransport_HandleStreams(t *testing.T) { + st := newHandleStreamTest(t) + handleStream := func(s *Stream) { + if want := "/service/foo.bar"; s.method != want { + t.Errorf("stream method = %q; want %q", s.method, want) + } + st.bodyw.Close() // no body + st.ht.WriteStatus(s, codes.OK, "") + } + st.ht.HandleStreams(func(s *Stream) { go handleStream(s) }) + wantHeader := http.Header{ + "Date": nil, + "Content-Type": {"application/grpc"}, + "Trailer": {"Grpc-Status", "Grpc-Message"}, + "Grpc-Status": {"0"}, + } + if !reflect.DeepEqual(st.rw.HeaderMap, wantHeader) { + t.Errorf("Header+Trailer Map: %#v; want %#v", st.rw.HeaderMap, wantHeader) + } +} + +// Tests that codes.Unimplemented will close the body, per comment in handler_server.go. +func TestHandlerTransport_HandleStreams_Unimplemented(t *testing.T) { + handleStreamCloseBodyTest(t, codes.Unimplemented, "thingy is unimplemented") +} + +// Tests that codes.InvalidArgument will close the body, per comment in handler_server.go. +func TestHandlerTransport_HandleStreams_InvalidArgument(t *testing.T) { + handleStreamCloseBodyTest(t, codes.InvalidArgument, "bad arg") +} + +func handleStreamCloseBodyTest(t *testing.T, statusCode codes.Code, msg string) { + st := newHandleStreamTest(t) + handleStream := func(s *Stream) { + st.ht.WriteStatus(s, statusCode, msg) + } + st.ht.HandleStreams(func(s *Stream) { go handleStream(s) }) + wantHeader := http.Header{ + "Date": nil, + "Content-Type": {"application/grpc"}, + "Trailer": {"Grpc-Status", "Grpc-Message"}, + "Grpc-Status": {fmt.Sprint(uint32(statusCode))}, + "Grpc-Message": {msg}, + } + if !reflect.DeepEqual(st.rw.HeaderMap, wantHeader) { + t.Errorf("Header+Trailer mismatch.\n got: %#v\nwant: %#v", st.rw.HeaderMap, wantHeader) + } +} + +func TestHandlerTransport_HandleStreams_Timeout(t *testing.T) { + bodyr, bodyw := io.Pipe() + req := &http.Request{ + ProtoMajor: 2, + Method: "POST", + Header: http.Header{ + "Content-Type": {"application/grpc"}, + "Grpc-Timeout": {"200m"}, + }, + URL: &url.URL{ + Path: "/service/foo.bar", + }, + RequestURI: "/service/foo.bar", + Body: bodyr, + } + rw := newTestHandlerResponseWriter().(testHandlerResponseWriter) + ht, err := NewServerHandlerTransport(rw, req) + if err != nil { + t.Fatal(err) + } + runStream := func(s *Stream) { + defer bodyw.Close() + select { + case <-s.ctx.Done(): + case <-time.After(5 * time.Second): + t.Errorf("timeout waiting for ctx.Done") + return + } + err := s.ctx.Err() + if err != context.DeadlineExceeded { + t.Errorf("ctx.Err = %v; want %v", err, context.DeadlineExceeded) + return + } + ht.WriteStatus(s, codes.DeadlineExceeded, "too slow") + } + ht.HandleStreams(func(s *Stream) { go runStream(s) }) + wantHeader := http.Header{ + "Date": nil, + "Content-Type": {"application/grpc"}, + "Trailer": {"Grpc-Status", "Grpc-Message"}, + "Grpc-Status": {"4"}, + "Grpc-Message": {"too slow"}, + } + if !reflect.DeepEqual(rw.HeaderMap, wantHeader) { + t.Errorf("Header+Trailer Map mismatch.\n got: %#v\nwant: %#v", rw.HeaderMap, wantHeader) + } +} diff --git a/vendor/google.golang.org/grpc/transport/http2_client.go b/vendor/google.golang.org/grpc/transport/http2_client.go new file mode 100644 index 00000000..f66435fd --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/http2_client.go @@ -0,0 +1,949 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "bytes" + "io" + "math" + "net" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/http2" + "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" +) + +// http2Client implements the ClientTransport interface with HTTP2. +type http2Client struct { + target string // server name/addr + userAgent string + conn net.Conn // underlying communication channel + authInfo credentials.AuthInfo // auth info about the connection + nextID uint32 // the next stream ID to be used + + // writableChan synchronizes write access to the transport. + // A writer acquires the write lock by sending a value on writableChan + // and releases it by receiving from writableChan. + writableChan chan int + // shutdownChan is closed when Close is called. + // Blocking operations should select on shutdownChan to avoid + // blocking forever after Close. + // TODO(zhaoq): Maybe have a channel context? + shutdownChan chan struct{} + // errorChan is closed to notify the I/O error to the caller. + errorChan chan struct{} + + framer *framer + hBuf *bytes.Buffer // the buffer for HPACK encoding + hEnc *hpack.Encoder // HPACK encoder + + // controlBuf delivers all the control related tasks (e.g., window + // updates, reset streams, and various settings) to the controller. + controlBuf *recvBuffer + fc *inFlow + // sendQuotaPool provides flow control to outbound message. + sendQuotaPool *quotaPool + // streamsQuota limits the max number of concurrent streams. + streamsQuota *quotaPool + + // The scheme used: https if TLS is on, http otherwise. + scheme string + + creds []credentials.PerRPCCredentials + + mu sync.Mutex // guard the following variables + state transportState // the state of underlying connection + activeStreams map[uint32]*Stream + // The max number of concurrent streams + maxStreams int + // the per-stream outbound flow control window size set by the peer. + streamSendQuota uint32 +} + +// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 +// and starts to receive messages on it. Non-nil error returns if construction +// fails. +func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err error) { + if opts.Dialer == nil { + // Set the default Dialer. + opts.Dialer = func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("tcp", addr, timeout) + } + } + scheme := "http" + startT := time.Now() + timeout := opts.Timeout + conn, connErr := opts.Dialer(addr, timeout) + if connErr != nil { + return nil, ConnectionErrorf("transport: %v", connErr) + } + var authInfo credentials.AuthInfo + if opts.TransportCredentials != nil { + scheme = "https" + if timeout > 0 { + timeout -= time.Since(startT) + } + conn, authInfo, connErr = opts.TransportCredentials.ClientHandshake(addr, conn, timeout) + } + if connErr != nil { + return nil, ConnectionErrorf("transport: %v", connErr) + } + defer func() { + if err != nil { + conn.Close() + } + }() + ua := primaryUA + if opts.UserAgent != "" { + ua = opts.UserAgent + " " + ua + } + var buf bytes.Buffer + t := &http2Client{ + target: addr, + userAgent: ua, + conn: conn, + authInfo: authInfo, + // The client initiated stream id is odd starting from 1. + nextID: 1, + writableChan: make(chan int, 1), + shutdownChan: make(chan struct{}), + errorChan: make(chan struct{}), + framer: newFramer(conn), + hBuf: &buf, + hEnc: hpack.NewEncoder(&buf), + controlBuf: newRecvBuffer(), + fc: &inFlow{limit: initialConnWindowSize}, + sendQuotaPool: newQuotaPool(defaultWindowSize), + scheme: scheme, + state: reachable, + activeStreams: make(map[uint32]*Stream), + creds: opts.PerRPCCredentials, + maxStreams: math.MaxInt32, + streamSendQuota: defaultWindowSize, + } + // Start the reader goroutine for incoming message. Each transport has + // a dedicated goroutine which reads HTTP2 frame from network. Then it + // dispatches the frame to the corresponding stream entity. + go t.reader() + // Send connection preface to server. + n, err := t.conn.Write(clientPreface) + if err != nil { + t.Close() + return nil, ConnectionErrorf("transport: %v", err) + } + if n != len(clientPreface) { + t.Close() + return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) + } + if initialWindowSize != defaultWindowSize { + err = t.framer.writeSettings(true, http2.Setting{ + ID: http2.SettingInitialWindowSize, + Val: uint32(initialWindowSize), + }) + } else { + err = t.framer.writeSettings(true) + } + if err != nil { + t.Close() + return nil, ConnectionErrorf("transport: %v", err) + } + // Adjust the connection flow control window if needed. + if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { + if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil { + t.Close() + return nil, ConnectionErrorf("transport: %v", err) + } + } + go t.controller() + t.writableChan <- 0 + return t, nil +} + +func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { + // TODO(zhaoq): Handle uint32 overflow of Stream.id. + s := &Stream{ + id: t.nextID, + method: callHdr.Method, + sendCompress: callHdr.SendCompress, + buf: newRecvBuffer(), + fc: &inFlow{limit: initialWindowSize}, + sendQuotaPool: newQuotaPool(int(t.streamSendQuota)), + headerChan: make(chan struct{}), + } + t.nextID += 2 + s.windowHandler = func(n int) { + t.updateWindow(s, uint32(n)) + } + // Make a stream be able to cancel the pending operations by itself. + s.ctx, s.cancel = context.WithCancel(ctx) + s.dec = &recvBufferReader{ + ctx: s.ctx, + recv: s.buf, + } + return s +} + +// NewStream creates a stream and register it into the transport as "active" +// streams. +func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Stream, err error) { + // Record the timeout value on the context. + var timeout time.Duration + if dl, ok := ctx.Deadline(); ok { + timeout = dl.Sub(time.Now()) + } + select { + case <-ctx.Done(): + return nil, ContextErr(ctx.Err()) + default: + } + pr := &peer.Peer{ + Addr: t.conn.RemoteAddr(), + } + // Attach Auth info if there is any. + if t.authInfo != nil { + pr.AuthInfo = t.authInfo + } + ctx = peer.NewContext(ctx, pr) + authData := make(map[string]string) + for _, c := range t.creds { + // Construct URI required to get auth request metadata. + var port string + if pos := strings.LastIndex(t.target, ":"); pos != -1 { + // Omit port if it is the default one. + if t.target[pos+1:] != "443" { + port = ":" + t.target[pos+1:] + } + } + pos := strings.LastIndex(callHdr.Method, "/") + if pos == -1 { + return nil, StreamErrorf(codes.InvalidArgument, "transport: malformed method name: %q", callHdr.Method) + } + audience := "https://" + callHdr.Host + port + callHdr.Method[:pos] + data, err := c.GetRequestMetadata(ctx, audience) + if err != nil { + return nil, StreamErrorf(codes.InvalidArgument, "transport: %v", err) + } + for k, v := range data { + authData[k] = v + } + } + t.mu.Lock() + if t.activeStreams == nil { + t.mu.Unlock() + return nil, ErrConnClosing + } + if t.state != reachable { + t.mu.Unlock() + return nil, ErrConnClosing + } + checkStreamsQuota := t.streamsQuota != nil + t.mu.Unlock() + if checkStreamsQuota { + sq, err := wait(ctx, t.shutdownChan, t.streamsQuota.acquire()) + if err != nil { + return nil, err + } + // Returns the quota balance back. + if sq > 1 { + t.streamsQuota.add(sq - 1) + } + } + if _, err := wait(ctx, t.shutdownChan, t.writableChan); err != nil { + // Return the quota back now because there is no stream returned to the caller. + if _, ok := err.(StreamError); ok && checkStreamsQuota { + t.streamsQuota.add(1) + } + return nil, err + } + t.mu.Lock() + if t.state != reachable { + t.mu.Unlock() + return nil, ErrConnClosing + } + s := t.newStream(ctx, callHdr) + t.activeStreams[s.id] = s + + // This stream is not counted when applySetings(...) initialize t.streamsQuota. + // Reset t.streamsQuota to the right value. + var reset bool + if !checkStreamsQuota && t.streamsQuota != nil { + reset = true + } + t.mu.Unlock() + if reset { + t.streamsQuota.reset(-1) + } + + // HPACK encodes various headers. Note that once WriteField(...) is + // called, the corresponding headers/continuation frame has to be sent + // because hpack.Encoder is stateful. + t.hBuf.Reset() + t.hEnc.WriteField(hpack.HeaderField{Name: ":method", Value: "POST"}) + t.hEnc.WriteField(hpack.HeaderField{Name: ":scheme", Value: t.scheme}) + t.hEnc.WriteField(hpack.HeaderField{Name: ":path", Value: callHdr.Method}) + t.hEnc.WriteField(hpack.HeaderField{Name: ":authority", Value: callHdr.Host}) + t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}) + t.hEnc.WriteField(hpack.HeaderField{Name: "user-agent", Value: t.userAgent}) + t.hEnc.WriteField(hpack.HeaderField{Name: "te", Value: "trailers"}) + + if callHdr.SendCompress != "" { + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) + } + if timeout > 0 { + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: timeoutEncode(timeout)}) + } + for k, v := range authData { + // Capital header names are illegal in HTTP/2. + k = strings.ToLower(k) + t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: v}) + } + var ( + hasMD bool + endHeaders bool + ) + if md, ok := metadata.FromContext(ctx); ok { + hasMD = true + for k, v := range md { + // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set. + if isReservedHeader(k) { + continue + } + for _, entry := range v { + t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) + } + } + } + first := true + // Sends the headers in a single batch even when they span multiple frames. + for !endHeaders { + size := t.hBuf.Len() + if size > http2MaxFrameLen { + size = http2MaxFrameLen + } else { + endHeaders = true + } + var flush bool + if endHeaders && (hasMD || callHdr.Flush) { + flush = true + } + if first { + // Sends a HeadersFrame to server to start a new stream. + p := http2.HeadersFrameParam{ + StreamID: s.id, + BlockFragment: t.hBuf.Next(size), + EndStream: false, + EndHeaders: endHeaders, + } + // Do a force flush for the buffered frames iff it is the last headers frame + // and there is header metadata to be sent. Otherwise, there is flushing until + // the corresponding data frame is written. + err = t.framer.writeHeaders(flush, p) + first = false + } else { + // Sends Continuation frames for the leftover headers. + err = t.framer.writeContinuation(flush, s.id, endHeaders, t.hBuf.Next(size)) + } + if err != nil { + t.notifyError(err) + return nil, ConnectionErrorf("transport: %v", err) + } + } + t.writableChan <- 0 + return s, nil +} + +// CloseStream clears the footprint of a stream when the stream is not needed any more. +// This must not be executed in reader's goroutine. +func (t *http2Client) CloseStream(s *Stream, err error) { + var updateStreams bool + t.mu.Lock() + if t.activeStreams == nil { + t.mu.Unlock() + return + } + if t.streamsQuota != nil { + updateStreams = true + } + if t.state == draining && len(t.activeStreams) == 1 { + // The transport is draining and s is the last live stream on t. + t.mu.Unlock() + t.Close() + return + } + delete(t.activeStreams, s.id) + t.mu.Unlock() + if updateStreams { + t.streamsQuota.add(1) + } + // In case stream sending and receiving are invoked in separate + // goroutines (e.g., bi-directional streaming), the caller needs + // to call cancel on the stream to interrupt the blocking on + // other goroutines. + s.cancel() + s.mu.Lock() + if q := s.fc.resetPendingData(); q > 0 { + if n := t.fc.onRead(q); n > 0 { + t.controlBuf.put(&windowUpdate{0, n}) + } + } + if s.state == streamDone { + s.mu.Unlock() + return + } + if !s.headerDone { + close(s.headerChan) + s.headerDone = true + } + s.state = streamDone + s.mu.Unlock() + if _, ok := err.(StreamError); ok { + t.controlBuf.put(&resetStream{s.id, http2.ErrCodeCancel}) + } +} + +// Close kicks off the shutdown process of the transport. This should be called +// only once on a transport. Once it is called, the transport should not be +// accessed any more. +func (t *http2Client) Close() (err error) { + t.mu.Lock() + if t.state == reachable { + close(t.errorChan) + } + if t.state == closing { + t.mu.Unlock() + return + } + t.state = closing + t.mu.Unlock() + close(t.shutdownChan) + err = t.conn.Close() + t.mu.Lock() + streams := t.activeStreams + t.activeStreams = nil + t.mu.Unlock() + // Notify all active streams. + for _, s := range streams { + s.mu.Lock() + if !s.headerDone { + close(s.headerChan) + s.headerDone = true + } + s.mu.Unlock() + s.write(recvMsg{err: ErrConnClosing}) + } + return +} + +func (t *http2Client) GracefulClose() error { + t.mu.Lock() + if t.state == closing { + t.mu.Unlock() + return nil + } + if t.state == draining { + t.mu.Unlock() + return nil + } + t.state = draining + active := len(t.activeStreams) + t.mu.Unlock() + if active == 0 { + return t.Close() + } + return nil +} + +// Write formats the data into HTTP2 data frame(s) and sends it out. The caller +// should proceed only if Write returns nil. +// TODO(zhaoq): opts.Delay is ignored in this implementation. Support it later +// if it improves the performance. +func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { + r := bytes.NewBuffer(data) + for { + var p []byte + if r.Len() > 0 { + size := http2MaxFrameLen + s.sendQuotaPool.add(0) + // Wait until the stream has some quota to send the data. + sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) + if err != nil { + return err + } + t.sendQuotaPool.add(0) + // Wait until the transport has some quota to send the data. + tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) + if err != nil { + if _, ok := err.(StreamError); ok { + t.sendQuotaPool.cancel() + } + return err + } + if sq < size { + size = sq + } + if tq < size { + size = tq + } + p = r.Next(size) + ps := len(p) + if ps < sq { + // Overbooked stream quota. Return it back. + s.sendQuotaPool.add(sq - ps) + } + if ps < tq { + // Overbooked transport quota. Return it back. + t.sendQuotaPool.add(tq - ps) + } + } + var ( + endStream bool + forceFlush bool + ) + if opts.Last && r.Len() == 0 { + endStream = true + } + // Indicate there is a writer who is about to write a data frame. + t.framer.adjustNumWriters(1) + // Got some quota. Try to acquire writing privilege on the transport. + if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, ok := err.(StreamError); ok { + // Return the connection quota back. + t.sendQuotaPool.add(len(p)) + } + if t.framer.adjustNumWriters(-1) == 0 { + // This writer is the last one in this batch and has the + // responsibility to flush the buffered frames. It queues + // a flush request to controlBuf instead of flushing directly + // in order to avoid the race with other writing or flushing. + t.controlBuf.put(&flushIO{}) + } + return err + } + select { + case <-s.ctx.Done(): + t.sendQuotaPool.add(len(p)) + if t.framer.adjustNumWriters(-1) == 0 { + t.controlBuf.put(&flushIO{}) + } + t.writableChan <- 0 + return ContextErr(s.ctx.Err()) + default: + } + if r.Len() == 0 && t.framer.adjustNumWriters(0) == 1 { + // Do a force flush iff this is last frame for the entire gRPC message + // and the caller is the only writer at this moment. + forceFlush = true + } + // If WriteData fails, all the pending streams will be handled + // by http2Client.Close(). No explicit CloseStream() needs to be + // invoked. + if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil { + t.notifyError(err) + return ConnectionErrorf("transport: %v", err) + } + if t.framer.adjustNumWriters(-1) == 0 { + t.framer.flushWrite() + } + t.writableChan <- 0 + if r.Len() == 0 { + break + } + } + if !opts.Last { + return nil + } + s.mu.Lock() + if s.state != streamDone { + if s.state == streamReadDone { + s.state = streamDone + } else { + s.state = streamWriteDone + } + } + s.mu.Unlock() + return nil +} + +func (t *http2Client) getStream(f http2.Frame) (*Stream, bool) { + t.mu.Lock() + defer t.mu.Unlock() + s, ok := t.activeStreams[f.Header().StreamID] + return s, ok +} + +// updateWindow adjusts the inbound quota for the stream and the transport. +// Window updates will deliver to the controller for sending when +// the cumulative quota exceeds the corresponding threshold. +func (t *http2Client) updateWindow(s *Stream, n uint32) { + s.mu.Lock() + defer s.mu.Unlock() + if s.state == streamDone { + return + } + if w := t.fc.onRead(n); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + if w := s.fc.onRead(n); w > 0 { + t.controlBuf.put(&windowUpdate{s.id, w}) + } +} + +func (t *http2Client) handleData(f *http2.DataFrame) { + size := len(f.Data()) + if err := t.fc.onData(uint32(size)); err != nil { + t.notifyError(ConnectionErrorf("%v", err)) + return + } + // Select the right stream to dispatch. + s, ok := t.getStream(f) + if !ok { + if w := t.fc.onRead(uint32(size)); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + return + } + if size > 0 { + s.mu.Lock() + if s.state == streamDone { + s.mu.Unlock() + // The stream has been closed. Release the corresponding quota. + if w := t.fc.onRead(uint32(size)); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + return + } + if err := s.fc.onData(uint32(size)); err != nil { + s.state = streamDone + s.statusCode = codes.Internal + s.statusDesc = err.Error() + s.mu.Unlock() + s.write(recvMsg{err: io.EOF}) + t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl}) + return + } + s.mu.Unlock() + // TODO(bradfitz, zhaoq): A copy is required here because there is no + // guarantee f.Data() is consumed before the arrival of next frame. + // Can this copy be eliminated? + data := make([]byte, size) + copy(data, f.Data()) + s.write(recvMsg{data: data}) + } + // The server has closed the stream without sending trailers. Record that + // the read direction is closed, and set the status appropriately. + if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) { + s.mu.Lock() + if s.state == streamWriteDone { + s.state = streamDone + } else { + s.state = streamReadDone + } + s.statusCode = codes.Internal + s.statusDesc = "server closed the stream without sending trailers" + s.mu.Unlock() + s.write(recvMsg{err: io.EOF}) + } +} + +func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { + s, ok := t.getStream(f) + if !ok { + return + } + s.mu.Lock() + if s.state == streamDone { + s.mu.Unlock() + return + } + s.state = streamDone + if !s.headerDone { + close(s.headerChan) + s.headerDone = true + } + s.statusCode, ok = http2ErrConvTab[http2.ErrCode(f.ErrCode)] + if !ok { + grpclog.Println("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error ", f.ErrCode) + s.statusCode = codes.Unknown + } + s.mu.Unlock() + s.write(recvMsg{err: io.EOF}) +} + +func (t *http2Client) handleSettings(f *http2.SettingsFrame) { + if f.IsAck() { + return + } + var ss []http2.Setting + f.ForeachSetting(func(s http2.Setting) error { + ss = append(ss, s) + return nil + }) + // The settings will be applied once the ack is sent. + t.controlBuf.put(&settings{ack: true, ss: ss}) +} + +func (t *http2Client) handlePing(f *http2.PingFrame) { + pingAck := &ping{ack: true} + copy(pingAck.data[:], f.Data[:]) + t.controlBuf.put(pingAck) +} + +func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { + // TODO(zhaoq): GoAwayFrame handler to be implemented +} + +func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) { + id := f.Header().StreamID + incr := f.Increment + if id == 0 { + t.sendQuotaPool.add(int(incr)) + return + } + if s, ok := t.getStream(f); ok { + s.sendQuotaPool.add(int(incr)) + } +} + +// operateHeaders takes action on the decoded headers. +func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { + s, ok := t.getStream(frame) + if !ok { + return + } + var state decodeState + for _, hf := range frame.Fields { + state.processHeaderField(hf) + } + if state.err != nil { + s.write(recvMsg{err: state.err}) + // Something wrong. Stops reading even when there is remaining. + return + } + + endStream := frame.StreamEnded() + + s.mu.Lock() + if !endStream { + s.recvCompress = state.encoding + } + if !s.headerDone { + if !endStream && len(state.mdata) > 0 { + s.header = state.mdata + } + close(s.headerChan) + s.headerDone = true + } + if !endStream || s.state == streamDone { + s.mu.Unlock() + return + } + + if len(state.mdata) > 0 { + s.trailer = state.mdata + } + s.state = streamDone + s.statusCode = state.statusCode + s.statusDesc = state.statusDesc + s.mu.Unlock() + + s.write(recvMsg{err: io.EOF}) +} + +func handleMalformedHTTP2(s *Stream, err error) { + s.mu.Lock() + if !s.headerDone { + close(s.headerChan) + s.headerDone = true + } + s.mu.Unlock() + s.write(recvMsg{err: err}) +} + +// reader runs as a separate goroutine in charge of reading data from network +// connection. +// +// TODO(zhaoq): currently one reader per transport. Investigate whether this is +// optimal. +// TODO(zhaoq): Check the validity of the incoming frame sequence. +func (t *http2Client) reader() { + // Check the validity of server preface. + frame, err := t.framer.readFrame() + if err != nil { + t.notifyError(err) + return + } + sf, ok := frame.(*http2.SettingsFrame) + if !ok { + t.notifyError(err) + return + } + t.handleSettings(sf) + + // loop to keep reading incoming messages on this transport. + for { + frame, err := t.framer.readFrame() + if err != nil { + // Abort an active stream if the http2.Framer returns a + // http2.StreamError. This can happen only if the server's response + // is malformed http2. + if se, ok := err.(http2.StreamError); ok { + t.mu.Lock() + s := t.activeStreams[se.StreamID] + t.mu.Unlock() + if s != nil { + // use error detail to provide better err message + handleMalformedHTTP2(s, StreamErrorf(http2ErrConvTab[se.Code], "%v", t.framer.errorDetail())) + } + continue + } else { + // Transport error. + t.notifyError(err) + return + } + } + switch frame := frame.(type) { + case *http2.MetaHeadersFrame: + t.operateHeaders(frame) + case *http2.DataFrame: + t.handleData(frame) + case *http2.RSTStreamFrame: + t.handleRSTStream(frame) + case *http2.SettingsFrame: + t.handleSettings(frame) + case *http2.PingFrame: + t.handlePing(frame) + case *http2.GoAwayFrame: + t.handleGoAway(frame) + case *http2.WindowUpdateFrame: + t.handleWindowUpdate(frame) + default: + grpclog.Printf("transport: http2Client.reader got unhandled frame type %v.", frame) + } + } +} + +func (t *http2Client) applySettings(ss []http2.Setting) { + for _, s := range ss { + switch s.ID { + case http2.SettingMaxConcurrentStreams: + // TODO(zhaoq): This is a hack to avoid significant refactoring of the + // code to deal with the unrealistic int32 overflow. Probably will try + // to find a better way to handle this later. + if s.Val > math.MaxInt32 { + s.Val = math.MaxInt32 + } + t.mu.Lock() + reset := t.streamsQuota != nil + if !reset { + t.streamsQuota = newQuotaPool(int(s.Val) - len(t.activeStreams)) + } + ms := t.maxStreams + t.maxStreams = int(s.Val) + t.mu.Unlock() + if reset { + t.streamsQuota.reset(int(s.Val) - ms) + } + case http2.SettingInitialWindowSize: + t.mu.Lock() + for _, stream := range t.activeStreams { + // Adjust the sending quota for each stream. + stream.sendQuotaPool.reset(int(s.Val - t.streamSendQuota)) + } + t.streamSendQuota = s.Val + t.mu.Unlock() + } + } +} + +// controller running in a separate goroutine takes charge of sending control +// frames (e.g., window update, reset stream, setting, etc.) to the server. +func (t *http2Client) controller() { + for { + select { + case i := <-t.controlBuf.get(): + t.controlBuf.load() + select { + case <-t.writableChan: + switch i := i.(type) { + case *windowUpdate: + t.framer.writeWindowUpdate(true, i.streamID, i.increment) + case *settings: + if i.ack { + t.framer.writeSettingsAck(true) + t.applySettings(i.ss) + } else { + t.framer.writeSettings(true, i.ss...) + } + case *resetStream: + t.framer.writeRSTStream(true, i.streamID, i.code) + case *flushIO: + t.framer.flushWrite() + case *ping: + t.framer.writePing(true, i.ack, i.data) + default: + grpclog.Printf("transport: http2Client.controller got unexpected item type %v\n", i) + } + t.writableChan <- 0 + continue + case <-t.shutdownChan: + return + } + case <-t.shutdownChan: + return + } + } +} + +func (t *http2Client) Error() <-chan struct{} { + return t.errorChan +} + +func (t *http2Client) notifyError(err error) { + t.mu.Lock() + defer t.mu.Unlock() + // make sure t.errorChan is closed only once. + if t.state == reachable { + t.state = unreachable + close(t.errorChan) + grpclog.Printf("transport: http2Client.notifyError got notified that the client transport was broken %v.", err) + } +} diff --git a/vendor/google.golang.org/grpc/transport/http2_server.go b/vendor/google.golang.org/grpc/transport/http2_server.go new file mode 100644 index 00000000..cee15429 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/http2_server.go @@ -0,0 +1,748 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "bytes" + "errors" + "io" + "math" + "net" + "strconv" + "sync" + + "golang.org/x/net/context" + "golang.org/x/net/http2" + "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" +) + +// ErrIllegalHeaderWrite indicates that setting header is illegal because of +// the stream's state. +var ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called") + +// http2Server implements the ServerTransport interface with HTTP2. +type http2Server struct { + conn net.Conn + maxStreamID uint32 // max stream ID ever seen + authInfo credentials.AuthInfo // auth info about the connection + // writableChan synchronizes write access to the transport. + // A writer acquires the write lock by receiving a value on writableChan + // and releases it by sending on writableChan. + writableChan chan int + // shutdownChan is closed when Close is called. + // Blocking operations should select on shutdownChan to avoid + // blocking forever after Close. + shutdownChan chan struct{} + framer *framer + hBuf *bytes.Buffer // the buffer for HPACK encoding + hEnc *hpack.Encoder // HPACK encoder + + // The max number of concurrent streams. + maxStreams uint32 + // controlBuf delivers all the control related tasks (e.g., window + // updates, reset streams, and various settings) to the controller. + controlBuf *recvBuffer + fc *inFlow + // sendQuotaPool provides flow control to outbound message. + sendQuotaPool *quotaPool + + mu sync.Mutex // guard the following + state transportState + activeStreams map[uint32]*Stream + // the per-stream outbound flow control window size set by the peer. + streamSendQuota uint32 +} + +// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is +// returned if something goes wrong. +func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthInfo) (_ ServerTransport, err error) { + framer := newFramer(conn) + // Send initial settings as connection preface to client. + var settings []http2.Setting + // TODO(zhaoq): Have a better way to signal "no limit" because 0 is + // permitted in the HTTP2 spec. + if maxStreams == 0 { + maxStreams = math.MaxUint32 + } else { + settings = append(settings, http2.Setting{ + ID: http2.SettingMaxConcurrentStreams, + Val: maxStreams, + }) + } + if initialWindowSize != defaultWindowSize { + settings = append(settings, http2.Setting{ + ID: http2.SettingInitialWindowSize, + Val: uint32(initialWindowSize)}) + } + if err := framer.writeSettings(true, settings...); err != nil { + return nil, ConnectionErrorf("transport: %v", err) + } + // Adjust the connection flow control window if needed. + if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { + if err := framer.writeWindowUpdate(true, 0, delta); err != nil { + return nil, ConnectionErrorf("transport: %v", err) + } + } + var buf bytes.Buffer + t := &http2Server{ + conn: conn, + authInfo: authInfo, + framer: framer, + hBuf: &buf, + hEnc: hpack.NewEncoder(&buf), + maxStreams: maxStreams, + controlBuf: newRecvBuffer(), + fc: &inFlow{limit: initialConnWindowSize}, + sendQuotaPool: newQuotaPool(defaultWindowSize), + state: reachable, + writableChan: make(chan int, 1), + shutdownChan: make(chan struct{}), + activeStreams: make(map[uint32]*Stream), + streamSendQuota: defaultWindowSize, + } + go t.controller() + t.writableChan <- 0 + return t, nil +} + +// operateHeader takes action on the decoded headers. +func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) { + buf := newRecvBuffer() + s := &Stream{ + id: frame.Header().StreamID, + st: t, + buf: buf, + fc: &inFlow{limit: initialWindowSize}, + } + + var state decodeState + for _, hf := range frame.Fields { + state.processHeaderField(hf) + } + if err := state.err; err != nil { + if se, ok := err.(StreamError); ok { + t.controlBuf.put(&resetStream{s.id, statusCodeConvTab[se.Code]}) + } + return + } + + if frame.StreamEnded() { + // s is just created by the caller. No lock needed. + s.state = streamReadDone + } + s.recvCompress = state.encoding + if state.timeoutSet { + s.ctx, s.cancel = context.WithTimeout(context.TODO(), state.timeout) + } else { + s.ctx, s.cancel = context.WithCancel(context.TODO()) + } + pr := &peer.Peer{ + Addr: t.conn.RemoteAddr(), + } + // Attach Auth info if there is any. + if t.authInfo != nil { + pr.AuthInfo = t.authInfo + } + s.ctx = peer.NewContext(s.ctx, pr) + // Cache the current stream to the context so that the server application + // can find out. Required when the server wants to send some metadata + // back to the client (unary call only). + s.ctx = newContextWithStream(s.ctx, s) + // Attach the received metadata to the context. + if len(state.mdata) > 0 { + s.ctx = metadata.NewContext(s.ctx, state.mdata) + } + + s.dec = &recvBufferReader{ + ctx: s.ctx, + recv: s.buf, + } + s.recvCompress = state.encoding + s.method = state.method + t.mu.Lock() + if t.state != reachable { + t.mu.Unlock() + return + } + if uint32(len(t.activeStreams)) >= t.maxStreams { + t.mu.Unlock() + t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) + return + } + s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) + t.activeStreams[s.id] = s + t.mu.Unlock() + s.windowHandler = func(n int) { + t.updateWindow(s, uint32(n)) + } + handle(s) +} + +// HandleStreams receives incoming streams using the given handler. This is +// typically run in a separate goroutine. +func (t *http2Server) HandleStreams(handle func(*Stream)) { + // Check the validity of client preface. + preface := make([]byte, len(clientPreface)) + if _, err := io.ReadFull(t.conn, preface); err != nil { + grpclog.Printf("transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) + t.Close() + return + } + if !bytes.Equal(preface, clientPreface) { + grpclog.Printf("transport: http2Server.HandleStreams received bogus greeting from client: %q", preface) + t.Close() + return + } + + frame, err := t.framer.readFrame() + if err != nil { + grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) + t.Close() + return + } + sf, ok := frame.(*http2.SettingsFrame) + if !ok { + grpclog.Printf("transport: http2Server.HandleStreams saw invalid preface type %T from client", frame) + t.Close() + return + } + t.handleSettings(sf) + + for { + frame, err := t.framer.readFrame() + if err != nil { + if se, ok := err.(http2.StreamError); ok { + t.mu.Lock() + s := t.activeStreams[se.StreamID] + t.mu.Unlock() + if s != nil { + t.closeStream(s) + } + t.controlBuf.put(&resetStream{se.StreamID, se.Code}) + continue + } + t.Close() + return + } + switch frame := frame.(type) { + case *http2.MetaHeadersFrame: + id := frame.Header().StreamID + if id%2 != 1 || id <= t.maxStreamID { + // illegal gRPC stream id. + grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", id) + t.Close() + break + } + t.maxStreamID = id + t.operateHeaders(frame, handle) + case *http2.DataFrame: + t.handleData(frame) + case *http2.RSTStreamFrame: + t.handleRSTStream(frame) + case *http2.SettingsFrame: + t.handleSettings(frame) + case *http2.PingFrame: + t.handlePing(frame) + case *http2.WindowUpdateFrame: + t.handleWindowUpdate(frame) + case *http2.GoAwayFrame: + break + default: + grpclog.Printf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame) + } + } +} + +func (t *http2Server) getStream(f http2.Frame) (*Stream, bool) { + t.mu.Lock() + defer t.mu.Unlock() + if t.activeStreams == nil { + // The transport is closing. + return nil, false + } + s, ok := t.activeStreams[f.Header().StreamID] + if !ok { + // The stream is already done. + return nil, false + } + return s, true +} + +// updateWindow adjusts the inbound quota for the stream and the transport. +// Window updates will deliver to the controller for sending when +// the cumulative quota exceeds the corresponding threshold. +func (t *http2Server) updateWindow(s *Stream, n uint32) { + s.mu.Lock() + defer s.mu.Unlock() + if s.state == streamDone { + return + } + if w := t.fc.onRead(n); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + if w := s.fc.onRead(n); w > 0 { + t.controlBuf.put(&windowUpdate{s.id, w}) + } +} + +func (t *http2Server) handleData(f *http2.DataFrame) { + size := len(f.Data()) + if err := t.fc.onData(uint32(size)); err != nil { + grpclog.Printf("transport: http2Server %v", err) + t.Close() + return + } + // Select the right stream to dispatch. + s, ok := t.getStream(f) + if !ok { + if w := t.fc.onRead(uint32(size)); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + return + } + if size > 0 { + s.mu.Lock() + if s.state == streamDone { + s.mu.Unlock() + // The stream has been closed. Release the corresponding quota. + if w := t.fc.onRead(uint32(size)); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + return + } + if err := s.fc.onData(uint32(size)); err != nil { + s.mu.Unlock() + t.closeStream(s) + t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl}) + return + } + s.mu.Unlock() + // TODO(bradfitz, zhaoq): A copy is required here because there is no + // guarantee f.Data() is consumed before the arrival of next frame. + // Can this copy be eliminated? + data := make([]byte, size) + copy(data, f.Data()) + s.write(recvMsg{data: data}) + } + if f.Header().Flags.Has(http2.FlagDataEndStream) { + // Received the end of stream from the client. + s.mu.Lock() + if s.state != streamDone { + if s.state == streamWriteDone { + s.state = streamDone + } else { + s.state = streamReadDone + } + } + s.mu.Unlock() + s.write(recvMsg{err: io.EOF}) + } +} + +func (t *http2Server) handleRSTStream(f *http2.RSTStreamFrame) { + s, ok := t.getStream(f) + if !ok { + return + } + t.closeStream(s) +} + +func (t *http2Server) handleSettings(f *http2.SettingsFrame) { + if f.IsAck() { + return + } + var ss []http2.Setting + f.ForeachSetting(func(s http2.Setting) error { + ss = append(ss, s) + return nil + }) + // The settings will be applied once the ack is sent. + t.controlBuf.put(&settings{ack: true, ss: ss}) +} + +func (t *http2Server) handlePing(f *http2.PingFrame) { + pingAck := &ping{ack: true} + copy(pingAck.data[:], f.Data[:]) + t.controlBuf.put(pingAck) +} + +func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) { + id := f.Header().StreamID + incr := f.Increment + if id == 0 { + t.sendQuotaPool.add(int(incr)) + return + } + if s, ok := t.getStream(f); ok { + s.sendQuotaPool.add(int(incr)) + } +} + +func (t *http2Server) writeHeaders(s *Stream, b *bytes.Buffer, endStream bool) error { + first := true + endHeaders := false + var err error + // Sends the headers in a single batch. + for !endHeaders { + size := t.hBuf.Len() + if size > http2MaxFrameLen { + size = http2MaxFrameLen + } else { + endHeaders = true + } + if first { + p := http2.HeadersFrameParam{ + StreamID: s.id, + BlockFragment: b.Next(size), + EndStream: endStream, + EndHeaders: endHeaders, + } + err = t.framer.writeHeaders(endHeaders, p) + first = false + } else { + err = t.framer.writeContinuation(endHeaders, s.id, endHeaders, b.Next(size)) + } + if err != nil { + t.Close() + return ConnectionErrorf("transport: %v", err) + } + } + return nil +} + +// WriteHeader sends the header metedata md back to the client. +func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { + s.mu.Lock() + if s.headerOk || s.state == streamDone { + s.mu.Unlock() + return ErrIllegalHeaderWrite + } + s.headerOk = true + s.mu.Unlock() + if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + return err + } + t.hBuf.Reset() + t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}) + if s.sendCompress != "" { + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) + } + for k, v := range md { + if isReservedHeader(k) { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + continue + } + for _, entry := range v { + t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) + } + } + if err := t.writeHeaders(s, t.hBuf, false); err != nil { + return err + } + t.writableChan <- 0 + return nil +} + +// WriteStatus sends stream status to the client and terminates the stream. +// There is no further I/O operations being able to perform on this stream. +// TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early +// OK is adopted. +func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc string) error { + var headersSent bool + s.mu.Lock() + if s.state == streamDone { + s.mu.Unlock() + return nil + } + if s.headerOk { + headersSent = true + } + s.mu.Unlock() + if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + return err + } + t.hBuf.Reset() + if !headersSent { + t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}) + } + t.hEnc.WriteField( + hpack.HeaderField{ + Name: "grpc-status", + Value: strconv.Itoa(int(statusCode)), + }) + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: statusDesc}) + // Attach the trailer metadata. + for k, v := range s.trailer { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } + for _, entry := range v { + t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) + } + } + if err := t.writeHeaders(s, t.hBuf, true); err != nil { + t.Close() + return err + } + t.closeStream(s) + t.writableChan <- 0 + return nil +} + +// Write converts the data into HTTP2 data frame and sends it out. Non-nil error +// is returns if it fails (e.g., framing error, transport error). +func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { + // TODO(zhaoq): Support multi-writers for a single stream. + var writeHeaderFrame bool + s.mu.Lock() + if s.state == streamDone { + s.mu.Unlock() + return StreamErrorf(codes.Unknown, "the stream has been done") + } + if !s.headerOk { + writeHeaderFrame = true + s.headerOk = true + } + s.mu.Unlock() + if writeHeaderFrame { + if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + return err + } + t.hBuf.Reset() + t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}) + if s.sendCompress != "" { + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) + } + p := http2.HeadersFrameParam{ + StreamID: s.id, + BlockFragment: t.hBuf.Bytes(), + EndHeaders: true, + } + if err := t.framer.writeHeaders(false, p); err != nil { + t.Close() + return ConnectionErrorf("transport: %v", err) + } + t.writableChan <- 0 + } + r := bytes.NewBuffer(data) + for { + if r.Len() == 0 { + return nil + } + size := http2MaxFrameLen + s.sendQuotaPool.add(0) + // Wait until the stream has some quota to send the data. + sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) + if err != nil { + return err + } + t.sendQuotaPool.add(0) + // Wait until the transport has some quota to send the data. + tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) + if err != nil { + if _, ok := err.(StreamError); ok { + t.sendQuotaPool.cancel() + } + return err + } + if sq < size { + size = sq + } + if tq < size { + size = tq + } + p := r.Next(size) + ps := len(p) + if ps < sq { + // Overbooked stream quota. Return it back. + s.sendQuotaPool.add(sq - ps) + } + if ps < tq { + // Overbooked transport quota. Return it back. + t.sendQuotaPool.add(tq - ps) + } + t.framer.adjustNumWriters(1) + // Got some quota. Try to acquire writing privilege on the + // transport. + if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, ok := err.(StreamError); ok { + // Return the connection quota back. + t.sendQuotaPool.add(ps) + } + if t.framer.adjustNumWriters(-1) == 0 { + // This writer is the last one in this batch and has the + // responsibility to flush the buffered frames. It queues + // a flush request to controlBuf instead of flushing directly + // in order to avoid the race with other writing or flushing. + t.controlBuf.put(&flushIO{}) + } + return err + } + select { + case <-s.ctx.Done(): + t.sendQuotaPool.add(ps) + if t.framer.adjustNumWriters(-1) == 0 { + t.controlBuf.put(&flushIO{}) + } + t.writableChan <- 0 + return ContextErr(s.ctx.Err()) + default: + } + var forceFlush bool + if r.Len() == 0 && t.framer.adjustNumWriters(0) == 1 && !opts.Last { + forceFlush = true + } + if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil { + t.Close() + return ConnectionErrorf("transport: %v", err) + } + if t.framer.adjustNumWriters(-1) == 0 { + t.framer.flushWrite() + } + t.writableChan <- 0 + } + +} + +func (t *http2Server) applySettings(ss []http2.Setting) { + for _, s := range ss { + if s.ID == http2.SettingInitialWindowSize { + t.mu.Lock() + defer t.mu.Unlock() + for _, stream := range t.activeStreams { + stream.sendQuotaPool.reset(int(s.Val - t.streamSendQuota)) + } + t.streamSendQuota = s.Val + } + + } +} + +// controller running in a separate goroutine takes charge of sending control +// frames (e.g., window update, reset stream, setting, etc.) to the server. +func (t *http2Server) controller() { + for { + select { + case i := <-t.controlBuf.get(): + t.controlBuf.load() + select { + case <-t.writableChan: + switch i := i.(type) { + case *windowUpdate: + t.framer.writeWindowUpdate(true, i.streamID, i.increment) + case *settings: + if i.ack { + t.framer.writeSettingsAck(true) + t.applySettings(i.ss) + } else { + t.framer.writeSettings(true, i.ss...) + } + case *resetStream: + t.framer.writeRSTStream(true, i.streamID, i.code) + case *flushIO: + t.framer.flushWrite() + case *ping: + t.framer.writePing(true, i.ack, i.data) + default: + grpclog.Printf("transport: http2Server.controller got unexpected item type %v\n", i) + } + t.writableChan <- 0 + continue + case <-t.shutdownChan: + return + } + case <-t.shutdownChan: + return + } + } +} + +// Close starts shutting down the http2Server transport. +// TODO(zhaoq): Now the destruction is not blocked on any pending streams. This +// could cause some resource issue. Revisit this later. +func (t *http2Server) Close() (err error) { + t.mu.Lock() + if t.state == closing { + t.mu.Unlock() + return errors.New("transport: Close() was already called") + } + t.state = closing + streams := t.activeStreams + t.activeStreams = nil + t.mu.Unlock() + close(t.shutdownChan) + err = t.conn.Close() + // Cancel all active streams. + for _, s := range streams { + s.cancel() + } + return +} + +// closeStream clears the footprint of a stream when the stream is not needed +// any more. +func (t *http2Server) closeStream(s *Stream) { + t.mu.Lock() + delete(t.activeStreams, s.id) + t.mu.Unlock() + // In case stream sending and receiving are invoked in separate + // goroutines (e.g., bi-directional streaming), cancel needs to be + // called to interrupt the potential blocking on other goroutines. + s.cancel() + s.mu.Lock() + if q := s.fc.resetPendingData(); q > 0 { + if w := t.fc.onRead(q); w > 0 { + t.controlBuf.put(&windowUpdate{0, w}) + } + } + if s.state == streamDone { + s.mu.Unlock() + return + } + s.state = streamDone + s.mu.Unlock() +} + +func (t *http2Server) RemoteAddr() net.Addr { + return t.conn.RemoteAddr() +} diff --git a/vendor/google.golang.org/grpc/transport/http_util.go b/vendor/google.golang.org/grpc/transport/http_util.go new file mode 100644 index 00000000..f2e23dce --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/http_util.go @@ -0,0 +1,435 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "bufio" + "fmt" + "io" + "net" + "strconv" + "strings" + "sync/atomic" + "time" + + "golang.org/x/net/http2" + "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" +) + +const ( + // The primary user agent + primaryUA = "grpc-go/0.11" + // http2MaxFrameLen specifies the max length of a HTTP2 frame. + http2MaxFrameLen = 16384 // 16KB frame + // http://http2.github.io/http2-spec/#SettingValues + http2InitHeaderTableSize = 4096 + // http2IOBufSize specifies the buffer size for sending frames. + http2IOBufSize = 32 * 1024 +) + +var ( + clientPreface = []byte(http2.ClientPreface) + http2ErrConvTab = map[http2.ErrCode]codes.Code{ + http2.ErrCodeNo: codes.Internal, + http2.ErrCodeProtocol: codes.Internal, + http2.ErrCodeInternal: codes.Internal, + http2.ErrCodeFlowControl: codes.ResourceExhausted, + http2.ErrCodeSettingsTimeout: codes.Internal, + http2.ErrCodeStreamClosed: codes.Internal, + http2.ErrCodeFrameSize: codes.Internal, + http2.ErrCodeRefusedStream: codes.Unavailable, + http2.ErrCodeCancel: codes.Canceled, + http2.ErrCodeCompression: codes.Internal, + http2.ErrCodeConnect: codes.Internal, + http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted, + http2.ErrCodeInadequateSecurity: codes.PermissionDenied, + http2.ErrCodeHTTP11Required: codes.FailedPrecondition, + } + statusCodeConvTab = map[codes.Code]http2.ErrCode{ + codes.Internal: http2.ErrCodeInternal, + codes.Canceled: http2.ErrCodeCancel, + codes.Unavailable: http2.ErrCodeRefusedStream, + codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm, + codes.PermissionDenied: http2.ErrCodeInadequateSecurity, + } +) + +// Records the states during HPACK decoding. Must be reset once the +// decoding of the entire headers are finished. +type decodeState struct { + err error // first error encountered decoding + + encoding string + // statusCode caches the stream status received from the trailer + // the server sent. Client side only. + statusCode codes.Code + statusDesc string + // Server side only fields. + timeoutSet bool + timeout time.Duration + method string + // key-value metadata map from the peer. + mdata map[string][]string +} + +// isReservedHeader checks whether hdr belongs to HTTP2 headers +// reserved by gRPC protocol. Any other headers are classified as the +// user-specified metadata. +func isReservedHeader(hdr string) bool { + if hdr != "" && hdr[0] == ':' { + return true + } + switch hdr { + case "content-type", + "grpc-message-type", + "grpc-encoding", + "grpc-message", + "grpc-status", + "grpc-timeout", + "te": + return true + default: + return false + } +} + +// isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders +// that should be propagated into metadata visible to users. +func isWhitelistedPseudoHeader(hdr string) bool { + switch hdr { + case ":authority": + return true + default: + return false + } +} + +func (d *decodeState) setErr(err error) { + if d.err == nil { + d.err = err + } +} + +func validContentType(t string) bool { + e := "application/grpc" + if !strings.HasPrefix(t, e) { + return false + } + // Support variations on the content-type + // (e.g. "application/grpc+blah", "application/grpc;blah"). + if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' { + return false + } + return true +} + +func (d *decodeState) processHeaderField(f hpack.HeaderField) { + switch f.Name { + case "content-type": + if !validContentType(f.Value) { + d.setErr(StreamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value)) + return + } + case "grpc-encoding": + d.encoding = f.Value + case "grpc-status": + code, err := strconv.Atoi(f.Value) + if err != nil { + d.setErr(StreamErrorf(codes.Internal, "transport: malformed grpc-status: %v", err)) + return + } + d.statusCode = codes.Code(code) + case "grpc-message": + d.statusDesc = f.Value + case "grpc-timeout": + d.timeoutSet = true + var err error + d.timeout, err = timeoutDecode(f.Value) + if err != nil { + d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err)) + return + } + case ":path": + d.method = f.Value + default: + if !isReservedHeader(f.Name) || isWhitelistedPseudoHeader(f.Name) { + if f.Name == "user-agent" { + i := strings.LastIndex(f.Value, " ") + if i == -1 { + // There is no application user agent string being set. + return + } + // Extract the application user agent string. + f.Value = f.Value[:i] + } + if d.mdata == nil { + d.mdata = make(map[string][]string) + } + k, v, err := metadata.DecodeKeyValue(f.Name, f.Value) + if err != nil { + grpclog.Printf("Failed to decode (%q, %q): %v", f.Name, f.Value, err) + return + } + d.mdata[k] = append(d.mdata[k], v) + } + } +} + +type timeoutUnit uint8 + +const ( + hour timeoutUnit = 'H' + minute timeoutUnit = 'M' + second timeoutUnit = 'S' + millisecond timeoutUnit = 'm' + microsecond timeoutUnit = 'u' + nanosecond timeoutUnit = 'n' +) + +func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) { + switch u { + case hour: + return time.Hour, true + case minute: + return time.Minute, true + case second: + return time.Second, true + case millisecond: + return time.Millisecond, true + case microsecond: + return time.Microsecond, true + case nanosecond: + return time.Nanosecond, true + default: + } + return +} + +const maxTimeoutValue int64 = 100000000 - 1 + +// div does integer division and round-up the result. Note that this is +// equivalent to (d+r-1)/r but has less chance to overflow. +func div(d, r time.Duration) int64 { + if m := d % r; m > 0 { + return int64(d/r + 1) + } + return int64(d / r) +} + +// TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it. +func timeoutEncode(t time.Duration) string { + if d := div(t, time.Nanosecond); d <= maxTimeoutValue { + return strconv.FormatInt(d, 10) + "n" + } + if d := div(t, time.Microsecond); d <= maxTimeoutValue { + return strconv.FormatInt(d, 10) + "u" + } + if d := div(t, time.Millisecond); d <= maxTimeoutValue { + return strconv.FormatInt(d, 10) + "m" + } + if d := div(t, time.Second); d <= maxTimeoutValue { + return strconv.FormatInt(d, 10) + "S" + } + if d := div(t, time.Minute); d <= maxTimeoutValue { + return strconv.FormatInt(d, 10) + "M" + } + // Note that maxTimeoutValue * time.Hour > MaxInt64. + return strconv.FormatInt(div(t, time.Hour), 10) + "H" +} + +func timeoutDecode(s string) (time.Duration, error) { + size := len(s) + if size < 2 { + return 0, fmt.Errorf("transport: timeout string is too short: %q", s) + } + unit := timeoutUnit(s[size-1]) + d, ok := timeoutUnitToDuration(unit) + if !ok { + return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s) + } + t, err := strconv.ParseInt(s[:size-1], 10, 64) + if err != nil { + return 0, err + } + return d * time.Duration(t), nil +} + +type framer struct { + numWriters int32 + reader io.Reader + writer *bufio.Writer + fr *http2.Framer +} + +func newFramer(conn net.Conn) *framer { + f := &framer{ + reader: bufio.NewReaderSize(conn, http2IOBufSize), + writer: bufio.NewWriterSize(conn, http2IOBufSize), + } + f.fr = http2.NewFramer(f.writer, f.reader) + f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil) + return f +} + +func (f *framer) adjustNumWriters(i int32) int32 { + return atomic.AddInt32(&f.numWriters, i) +} + +// The following writeXXX functions can only be called when the caller gets +// unblocked from writableChan channel (i.e., owns the privilege to write). + +func (f *framer) writeContinuation(forceFlush bool, streamID uint32, endHeaders bool, headerBlockFragment []byte) error { + if err := f.fr.WriteContinuation(streamID, endHeaders, headerBlockFragment); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeData(forceFlush bool, streamID uint32, endStream bool, data []byte) error { + if err := f.fr.WriteData(streamID, endStream, data); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeGoAway(forceFlush bool, maxStreamID uint32, code http2.ErrCode, debugData []byte) error { + if err := f.fr.WriteGoAway(maxStreamID, code, debugData); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeHeaders(forceFlush bool, p http2.HeadersFrameParam) error { + if err := f.fr.WriteHeaders(p); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writePing(forceFlush, ack bool, data [8]byte) error { + if err := f.fr.WritePing(ack, data); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writePriority(forceFlush bool, streamID uint32, p http2.PriorityParam) error { + if err := f.fr.WritePriority(streamID, p); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writePushPromise(forceFlush bool, p http2.PushPromiseParam) error { + if err := f.fr.WritePushPromise(p); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeRSTStream(forceFlush bool, streamID uint32, code http2.ErrCode) error { + if err := f.fr.WriteRSTStream(streamID, code); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeSettings(forceFlush bool, settings ...http2.Setting) error { + if err := f.fr.WriteSettings(settings...); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeSettingsAck(forceFlush bool) error { + if err := f.fr.WriteSettingsAck(); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) writeWindowUpdate(forceFlush bool, streamID, incr uint32) error { + if err := f.fr.WriteWindowUpdate(streamID, incr); err != nil { + return err + } + if forceFlush { + return f.writer.Flush() + } + return nil +} + +func (f *framer) flushWrite() error { + return f.writer.Flush() +} + +func (f *framer) readFrame() (http2.Frame, error) { + return f.fr.ReadFrame() +} + +func (f *framer) errorDetail() error { + return f.fr.ErrorDetail() +} diff --git a/vendor/google.golang.org/grpc/transport/http_util_test.go b/vendor/google.golang.org/grpc/transport/http_util_test.go new file mode 100644 index 00000000..279acbc5 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/http_util_test.go @@ -0,0 +1,109 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "fmt" + "testing" + "time" +) + +func TestTimeoutEncode(t *testing.T) { + for _, test := range []struct { + in string + out string + }{ + {"12345678ns", "12345678n"}, + {"123456789ns", "123457u"}, + {"12345678us", "12345678u"}, + {"123456789us", "123457m"}, + {"12345678ms", "12345678m"}, + {"123456789ms", "123457S"}, + {"12345678s", "12345678S"}, + {"123456789s", "2057614M"}, + {"12345678m", "12345678M"}, + {"123456789m", "2057614H"}, + } { + d, err := time.ParseDuration(test.in) + if err != nil { + t.Fatalf("failed to parse duration string %s: %v", test.in, err) + } + out := timeoutEncode(d) + if out != test.out { + t.Fatalf("timeoutEncode(%s) = %s, want %s", test.in, out, test.out) + } + } +} + +func TestTimeoutDecode(t *testing.T) { + for _, test := range []struct { + // input + s string + // output + d time.Duration + err error + }{ + {"1234S", time.Second * 1234, nil}, + {"1234x", 0, fmt.Errorf("transport: timeout unit is not recognized: %q", "1234x")}, + {"1", 0, fmt.Errorf("transport: timeout string is too short: %q", "1")}, + {"", 0, fmt.Errorf("transport: timeout string is too short: %q", "")}, + } { + d, err := timeoutDecode(test.s) + if d != test.d || fmt.Sprint(err) != fmt.Sprint(test.err) { + t.Fatalf("timeoutDecode(%q) = %d, %v, want %d, %v", test.s, int64(d), err, int64(test.d), test.err) + } + } +} + +func TestValidContentType(t *testing.T) { + tests := []struct { + h string + want bool + }{ + {"application/grpc", true}, + {"application/grpc+", true}, + {"application/grpc+blah", true}, + {"application/grpc;", true}, + {"application/grpc;blah", true}, + {"application/grpcd", false}, + {"application/grpd", false}, + {"application/grp", false}, + } + for _, tt := range tests { + got := validContentType(tt.h) + if got != tt.want { + t.Errorf("validContentType(%q) = %v; want %v", tt.h, got, tt.want) + } + } +} diff --git a/vendor/google.golang.org/grpc/transport/testdata/ca.pem b/vendor/google.golang.org/grpc/transport/testdata/ca.pem new file mode 100644 index 00000000..6c8511a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/testdata/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/transport/testdata/server1.key b/vendor/google.golang.org/grpc/transport/testdata/server1.key new file mode 100644 index 00000000..143a5b87 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/testdata/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/vendor/google.golang.org/grpc/transport/testdata/server1.pem b/vendor/google.golang.org/grpc/transport/testdata/server1.pem new file mode 100644 index 00000000..f3d43fcc --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 +-----END CERTIFICATE----- diff --git a/vendor/google.golang.org/grpc/transport/transport.go b/vendor/google.golang.org/grpc/transport/transport.go new file mode 100644 index 00000000..d4c220a0 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/transport.go @@ -0,0 +1,515 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* +Package transport defines and implements message oriented communication channel +to complete various transactions (e.g., an RPC). +*/ +package transport // import "google.golang.org/grpc/transport" + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" +) + +// recvMsg represents the received msg from the transport. All transport +// protocol specific info has been removed. +type recvMsg struct { + data []byte + // nil: received some data + // io.EOF: stream is completed. data is nil. + // other non-nil error: transport failure. data is nil. + err error +} + +func (*recvMsg) item() {} + +// All items in an out of a recvBuffer should be the same type. +type item interface { + item() +} + +// recvBuffer is an unbounded channel of item. +type recvBuffer struct { + c chan item + mu sync.Mutex + backlog []item +} + +func newRecvBuffer() *recvBuffer { + b := &recvBuffer{ + c: make(chan item, 1), + } + return b +} + +func (b *recvBuffer) put(r item) { + b.mu.Lock() + defer b.mu.Unlock() + if len(b.backlog) == 0 { + select { + case b.c <- r: + return + default: + } + } + b.backlog = append(b.backlog, r) +} + +func (b *recvBuffer) load() { + b.mu.Lock() + defer b.mu.Unlock() + if len(b.backlog) > 0 { + select { + case b.c <- b.backlog[0]: + b.backlog = b.backlog[1:] + default: + } + } +} + +// get returns the channel that receives an item in the buffer. +// +// Upon receipt of an item, the caller should call load to send another +// item onto the channel if there is any. +func (b *recvBuffer) get() <-chan item { + return b.c +} + +// recvBufferReader implements io.Reader interface to read the data from +// recvBuffer. +type recvBufferReader struct { + ctx context.Context + recv *recvBuffer + last *bytes.Reader // Stores the remaining data in the previous calls. + err error +} + +// Read reads the next len(p) bytes from last. If last is drained, it tries to +// read additional data from recv. It blocks if there no additional data available +// in recv. If Read returns any non-nil error, it will continue to return that error. +func (r *recvBufferReader) Read(p []byte) (n int, err error) { + if r.err != nil { + return 0, r.err + } + defer func() { r.err = err }() + if r.last != nil && r.last.Len() > 0 { + // Read remaining data left in last call. + return r.last.Read(p) + } + select { + case <-r.ctx.Done(): + return 0, ContextErr(r.ctx.Err()) + case i := <-r.recv.get(): + r.recv.load() + m := i.(*recvMsg) + if m.err != nil { + return 0, m.err + } + r.last = bytes.NewReader(m.data) + return r.last.Read(p) + } +} + +type streamState uint8 + +const ( + streamActive streamState = iota + streamWriteDone // EndStream sent + streamReadDone // EndStream received + streamDone // sendDone and recvDone or RSTStreamFrame is sent or received. +) + +// Stream represents an RPC in the transport layer. +type Stream struct { + id uint32 + // nil for client side Stream. + st ServerTransport + // ctx is the associated context of the stream. + ctx context.Context + cancel context.CancelFunc + // method records the associated RPC method of the stream. + method string + recvCompress string + sendCompress string + buf *recvBuffer + dec io.Reader + fc *inFlow + recvQuota uint32 + // The accumulated inbound quota pending for window update. + updateQuota uint32 + // The handler to control the window update procedure for both this + // particular stream and the associated transport. + windowHandler func(int) + + sendQuotaPool *quotaPool + // Close headerChan to indicate the end of reception of header metadata. + headerChan chan struct{} + // header caches the received header metadata. + header metadata.MD + // The key-value map of trailer metadata. + trailer metadata.MD + + mu sync.RWMutex // guard the following + // headerOK becomes true from the first header is about to send. + headerOk bool + state streamState + // true iff headerChan is closed. Used to avoid closing headerChan + // multiple times. + headerDone bool + // the status received from the server. + statusCode codes.Code + statusDesc string +} + +// RecvCompress returns the compression algorithm applied to the inbound +// message. It is empty string if there is no compression applied. +func (s *Stream) RecvCompress() string { + return s.recvCompress +} + +// SetSendCompress sets the compression algorithm to the stream. +func (s *Stream) SetSendCompress(str string) { + s.sendCompress = str +} + +// Header acquires the key-value pairs of header metadata once it +// is available. It blocks until i) the metadata is ready or ii) there is no +// header metadata or iii) the stream is cancelled/expired. +func (s *Stream) Header() (metadata.MD, error) { + select { + case <-s.ctx.Done(): + return nil, ContextErr(s.ctx.Err()) + case <-s.headerChan: + return s.header.Copy(), nil + } +} + +// Trailer returns the cached trailer metedata. Note that if it is not called +// after the entire stream is done, it could return an empty MD. Client +// side only. +func (s *Stream) Trailer() metadata.MD { + s.mu.RLock() + defer s.mu.RUnlock() + return s.trailer.Copy() +} + +// ServerTransport returns the underlying ServerTransport for the stream. +// The client side stream always returns nil. +func (s *Stream) ServerTransport() ServerTransport { + return s.st +} + +// Context returns the context of the stream. +func (s *Stream) Context() context.Context { + return s.ctx +} + +// TraceContext recreates the context of s with a trace.Trace. +func (s *Stream) TraceContext(tr trace.Trace) { + s.ctx = trace.NewContext(s.ctx, tr) +} + +// Method returns the method for the stream. +func (s *Stream) Method() string { + return s.method +} + +// StatusCode returns statusCode received from the server. +func (s *Stream) StatusCode() codes.Code { + return s.statusCode +} + +// StatusDesc returns statusDesc received from the server. +func (s *Stream) StatusDesc() string { + return s.statusDesc +} + +// ErrIllegalTrailerSet indicates that the trailer has already been set or it +// is too late to do so. +var ErrIllegalTrailerSet = errors.New("transport: trailer has been set") + +// SetTrailer sets the trailer metadata which will be sent with the RPC status +// by the server. This can only be called at most once. Server side only. +func (s *Stream) SetTrailer(md metadata.MD) error { + s.mu.Lock() + defer s.mu.Unlock() + if s.trailer != nil { + return ErrIllegalTrailerSet + } + s.trailer = md.Copy() + return nil +} + +func (s *Stream) write(m recvMsg) { + s.buf.put(&m) +} + +// Read reads all the data available for this Stream from the transport and +// passes them into the decoder, which converts them into a gRPC message stream. +// The error is io.EOF when the stream is done or another non-nil error if +// the stream broke. +func (s *Stream) Read(p []byte) (n int, err error) { + n, err = s.dec.Read(p) + if err != nil { + return + } + s.windowHandler(n) + return +} + +// The key to save transport.Stream in the context. +type streamKey struct{} + +// newContextWithStream creates a new context from ctx and attaches stream +// to it. +func newContextWithStream(ctx context.Context, stream *Stream) context.Context { + return context.WithValue(ctx, streamKey{}, stream) +} + +// StreamFromContext returns the stream saved in ctx. +func StreamFromContext(ctx context.Context) (s *Stream, ok bool) { + s, ok = ctx.Value(streamKey{}).(*Stream) + return +} + +// state of transport +type transportState int + +const ( + reachable transportState = iota + unreachable + closing + draining +) + +// NewServerTransport creates a ServerTransport with conn or non-nil error +// if it fails. +func NewServerTransport(protocol string, conn net.Conn, maxStreams uint32, authInfo credentials.AuthInfo) (ServerTransport, error) { + return newHTTP2Server(conn, maxStreams, authInfo) +} + +// ConnectOptions covers all relevant options for dialing a server. +type ConnectOptions struct { + // UserAgent is the application user agent. + UserAgent string + // Dialer specifies how to dial a network address. + Dialer func(string, time.Duration) (net.Conn, error) + // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. + PerRPCCredentials []credentials.PerRPCCredentials + // TransportCredentials stores the Authenticator required to setup a client connection. + TransportCredentials credentials.TransportCredentials + // Timeout specifies the timeout for dialing a ClientTransport. + Timeout time.Duration +} + +// NewClientTransport establishes the transport with the required ConnectOptions +// and returns it to the caller. +func NewClientTransport(target string, opts *ConnectOptions) (ClientTransport, error) { + return newHTTP2Client(target, opts) +} + +// Options provides additional hints and information for message +// transmission. +type Options struct { + // Last indicates whether this write is the last piece for + // this stream. + Last bool + + // Delay is a hint to the transport implementation for whether + // the data could be buffered for a batching write. The + // Transport implementation may ignore the hint. + Delay bool +} + +// CallHdr carries the information of a particular RPC. +type CallHdr struct { + // Host specifies the peer's host. + Host string + + // Method specifies the operation to perform. + Method string + + // RecvCompress specifies the compression algorithm applied on + // inbound messages. + RecvCompress string + + // SendCompress specifies the compression algorithm applied on + // outbound message. + SendCompress string + + // Flush indicates whether a new stream command should be sent + // to the peer without waiting for the first data. This is + // only a hint. The transport may modify the flush decision + // for performance purposes. + Flush bool +} + +// ClientTransport is the common interface for all gRPC client-side transport +// implementations. +type ClientTransport interface { + // Close tears down this transport. Once it returns, the transport + // should not be accessed any more. The caller must make sure this + // is called only once. + Close() error + + // GracefulClose starts to tear down the transport. It stops accepting + // new RPCs and wait the completion of the pending RPCs. + GracefulClose() error + + // Write sends the data for the given stream. A nil stream indicates + // the write is to be performed on the transport as a whole. + Write(s *Stream, data []byte, opts *Options) error + + // NewStream creates a Stream for an RPC. + NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) + + // CloseStream clears the footprint of a stream when the stream is + // not needed any more. The err indicates the error incurred when + // CloseStream is called. Must be called when a stream is finished + // unless the associated transport is closing. + CloseStream(stream *Stream, err error) + + // Error returns a channel that is closed when some I/O error + // happens. Typically the caller should have a goroutine to monitor + // this in order to take action (e.g., close the current transport + // and create a new one) in error case. It should not return nil + // once the transport is initiated. + Error() <-chan struct{} +} + +// ServerTransport is the common interface for all gRPC server-side transport +// implementations. +// +// Methods may be called concurrently from multiple goroutines, but +// Write methods for a given Stream will be called serially. +type ServerTransport interface { + // HandleStreams receives incoming streams using the given handler. + HandleStreams(func(*Stream)) + + // WriteHeader sends the header metadata for the given stream. + // WriteHeader may not be called on all streams. + WriteHeader(s *Stream, md metadata.MD) error + + // Write sends the data for the given stream. + // Write may not be called on all streams. + Write(s *Stream, data []byte, opts *Options) error + + // WriteStatus sends the status of a stream to the client. + // WriteStatus is the final call made on a stream and always + // occurs. + WriteStatus(s *Stream, statusCode codes.Code, statusDesc string) error + + // Close tears down the transport. Once it is called, the transport + // should not be accessed any more. All the pending streams and their + // handlers will be terminated asynchronously. + Close() error + + // RemoteAddr returns the remote network address. + RemoteAddr() net.Addr +} + +// StreamErrorf creates an StreamError with the specified error code and description. +func StreamErrorf(c codes.Code, format string, a ...interface{}) StreamError { + return StreamError{ + Code: c, + Desc: fmt.Sprintf(format, a...), + } +} + +// ConnectionErrorf creates an ConnectionError with the specified error description. +func ConnectionErrorf(format string, a ...interface{}) ConnectionError { + return ConnectionError{ + Desc: fmt.Sprintf(format, a...), + } +} + +// ConnectionError is an error that results in the termination of the +// entire connection and the retry of all the active streams. +type ConnectionError struct { + Desc string +} + +func (e ConnectionError) Error() string { + return fmt.Sprintf("connection error: desc = %q", e.Desc) +} + +// ErrConnClosing indicates that the transport is closing. +var ErrConnClosing = ConnectionError{Desc: "transport is closing"} + +// StreamError is an error that only affects one stream within a connection. +type StreamError struct { + Code codes.Code + Desc string +} + +func (e StreamError) Error() string { + return fmt.Sprintf("stream error: code = %d desc = %q", e.Code, e.Desc) +} + +// ContextErr converts the error from context package into a StreamError. +func ContextErr(err error) StreamError { + switch err { + case context.DeadlineExceeded: + return StreamErrorf(codes.DeadlineExceeded, "%v", err) + case context.Canceled: + return StreamErrorf(codes.Canceled, "%v", err) + } + panic(fmt.Sprintf("Unexpected error from context packet: %v", err)) +} + +// wait blocks until it can receive from ctx.Done, closing, or proceed. +// If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. +// If it receives from closing, it returns 0, ErrConnClosing. +// If it receives from proceed, it returns the received integer, nil. +func wait(ctx context.Context, closing <-chan struct{}, proceed <-chan int) (int, error) { + select { + case <-ctx.Done(): + return 0, ContextErr(ctx.Err()) + case <-closing: + return 0, ErrConnClosing + case i := <-proceed: + return i, nil + } +} diff --git a/vendor/google.golang.org/grpc/transport/transport_test.go b/vendor/google.golang.org/grpc/transport/transport_test.go new file mode 100644 index 00000000..ce015da2 --- /dev/null +++ b/vendor/google.golang.org/grpc/transport/transport_test.go @@ -0,0 +1,764 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package transport + +import ( + "bytes" + "fmt" + "io" + "math" + "net" + "reflect" + "strconv" + "sync" + "testing" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/http2" + "google.golang.org/grpc/codes" +) + +type server struct { + lis net.Listener + port string + startedErr chan error // error (or nil) with server start value + mu sync.Mutex + conns map[ServerTransport]bool +} + +var ( + expectedRequest = []byte("ping") + expectedResponse = []byte("pong") + expectedRequestLarge = make([]byte, initialWindowSize*2) + expectedResponseLarge = make([]byte, initialWindowSize*2) +) + +type testStreamHandler struct { + t ServerTransport +} + +type hType int + +const ( + normal hType = iota + suspended + misbehaved + malformedStatus +) + +func (h *testStreamHandler) handleStream(t *testing.T, s *Stream) { + req := expectedRequest + resp := expectedResponse + if s.Method() == "foo.Large" { + req = expectedRequestLarge + resp = expectedResponseLarge + } + p := make([]byte, len(req)) + _, err := io.ReadFull(s, p) + if err != nil { + return + } + if !bytes.Equal(p, req) { + t.Fatalf("handleStream got %v, want %v", p, req) + } + // send a response back to the client. + h.t.Write(s, resp, &Options{}) + // send the trailer to end the stream. + h.t.WriteStatus(s, codes.OK, "") +} + +// handleStreamSuspension blocks until s.ctx is canceled. +func (h *testStreamHandler) handleStreamSuspension(s *Stream) { + go func() { + <-s.ctx.Done() + }() +} + +func (h *testStreamHandler) handleStreamMisbehave(t *testing.T, s *Stream) { + conn, ok := s.ServerTransport().(*http2Server) + if !ok { + t.Fatalf("Failed to convert %v to *http2Server", s.ServerTransport()) + } + size := 1 + if s.Method() == "foo.MaxFrame" { + size = http2MaxFrameLen + } + // Drain the client side stream flow control window. + var sent int + for sent <= initialWindowSize { + <-conn.writableChan + if err := conn.framer.writeData(true, s.id, false, make([]byte, size)); err != nil { + conn.writableChan <- 0 + break + } + conn.writableChan <- 0 + sent += size + } +} + +func (h *testStreamHandler) handleStreamMalformedStatus(t *testing.T, s *Stream) { + // raw newline is not accepted by http2 framer and a http2.StreamError is + // generated. + h.t.WriteStatus(s, codes.Internal, "\n") +} + +// start starts server. Other goroutines should block on s.readyChan for further operations. +func (s *server) start(t *testing.T, port int, maxStreams uint32, ht hType) { + var err error + if port == 0 { + s.lis, err = net.Listen("tcp", "localhost:0") + } else { + s.lis, err = net.Listen("tcp", "localhost:"+strconv.Itoa(port)) + } + if err != nil { + s.startedErr <- fmt.Errorf("failed to listen: %v", err) + return + } + _, p, err := net.SplitHostPort(s.lis.Addr().String()) + if err != nil { + s.startedErr <- fmt.Errorf("failed to parse listener address: %v", err) + return + } + s.port = p + s.conns = make(map[ServerTransport]bool) + s.startedErr <- nil + for { + conn, err := s.lis.Accept() + if err != nil { + return + } + transport, err := NewServerTransport("http2", conn, maxStreams, nil) + if err != nil { + return + } + s.mu.Lock() + if s.conns == nil { + s.mu.Unlock() + transport.Close() + return + } + s.conns[transport] = true + s.mu.Unlock() + h := &testStreamHandler{transport} + switch ht { + case suspended: + go transport.HandleStreams(h.handleStreamSuspension) + case misbehaved: + go transport.HandleStreams(func(s *Stream) { + go h.handleStreamMisbehave(t, s) + }) + case malformedStatus: + go transport.HandleStreams(func(s *Stream) { + go h.handleStreamMalformedStatus(t, s) + }) + default: + go transport.HandleStreams(func(s *Stream) { + go h.handleStream(t, s) + }) + } + } +} + +func (s *server) wait(t *testing.T, timeout time.Duration) { + select { + case err := <-s.startedErr: + if err != nil { + t.Fatal(err) + } + case <-time.After(timeout): + t.Fatalf("Timed out after %v waiting for server to be ready", timeout) + } +} + +func (s *server) stop() { + s.lis.Close() + s.mu.Lock() + for c := range s.conns { + c.Close() + } + s.conns = nil + s.mu.Unlock() +} + +func setUp(t *testing.T, port int, maxStreams uint32, ht hType) (*server, ClientTransport) { + server := &server{startedErr: make(chan error, 1)} + go server.start(t, port, maxStreams, ht) + server.wait(t, 2*time.Second) + addr := "localhost:" + server.port + var ( + ct ClientTransport + connErr error + ) + ct, connErr = NewClientTransport(addr, &ConnectOptions{}) + if connErr != nil { + t.Fatalf("failed to create transport: %v", connErr) + } + return server, ct +} + +func TestClientSendAndReceive(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, normal) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Small", + } + s1, err1 := ct.NewStream(context.Background(), callHdr) + if err1 != nil { + t.Fatalf("failed to open stream: %v", err1) + } + if s1.id != 1 { + t.Fatalf("wrong stream id: %d", s1.id) + } + s2, err2 := ct.NewStream(context.Background(), callHdr) + if err2 != nil { + t.Fatalf("failed to open stream: %v", err2) + } + if s2.id != 3 { + t.Fatalf("wrong stream id: %d", s2.id) + } + opts := Options{ + Last: true, + Delay: false, + } + if err := ct.Write(s1, expectedRequest, &opts); err != nil { + t.Fatalf("failed to send data: %v", err) + } + p := make([]byte, len(expectedResponse)) + _, recvErr := io.ReadFull(s1, p) + if recvErr != nil || !bytes.Equal(p, expectedResponse) { + t.Fatalf("Error: %v, want ; Result: %v, want %v", recvErr, p, expectedResponse) + } + _, recvErr = io.ReadFull(s1, p) + if recvErr != io.EOF { + t.Fatalf("Error: %v; want ", recvErr) + } + ct.Close() + server.stop() +} + +func TestClientErrorNotify(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, normal) + go server.stop() + // ct.reader should detect the error and activate ct.Error(). + <-ct.Error() + ct.Close() +} + +func performOneRPC(ct ClientTransport) { + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Small", + } + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + return + } + opts := Options{ + Last: true, + Delay: false, + } + if err := ct.Write(s, expectedRequest, &opts); err == nil { + time.Sleep(5 * time.Millisecond) + // The following s.Recv()'s could error out because the + // underlying transport is gone. + // + // Read response + p := make([]byte, len(expectedResponse)) + io.ReadFull(s, p) + // Read io.EOF + io.ReadFull(s, p) + } +} + +func TestClientMix(t *testing.T) { + s, ct := setUp(t, 0, math.MaxUint32, normal) + go func(s *server) { + time.Sleep(5 * time.Second) + s.stop() + }(s) + go func(ct ClientTransport) { + <-ct.Error() + ct.Close() + }(ct) + for i := 0; i < 1000; i++ { + time.Sleep(10 * time.Millisecond) + go performOneRPC(ct) + } +} + +func TestLargeMessage(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, normal) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Large", + } + var wg sync.WaitGroup + for i := 0; i < 2; i++ { + wg.Add(1) + go func() { + defer wg.Done() + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Errorf("%v.NewStream(_, _) = _, %v, want _, ", ct, err) + } + if err := ct.Write(s, expectedRequestLarge, &Options{Last: true, Delay: false}); err != nil { + t.Errorf("%v.Write(_, _, _) = %v, want ", ct, err) + } + p := make([]byte, len(expectedResponseLarge)) + if _, err := io.ReadFull(s, p); err != nil || !bytes.Equal(p, expectedResponseLarge) { + t.Errorf("io.ReadFull(_, %v) = _, %v, want %v, ", err, p, expectedResponse) + } + if _, err = io.ReadFull(s, p); err != io.EOF { + t.Errorf("Failed to complete the stream %v; want ", err) + } + }() + } + wg.Wait() + ct.Close() + server.stop() +} + +func TestGracefulClose(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, normal) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Small", + } + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Fatalf("%v.NewStream(_, _) = _, %v, want _, ", ct, err) + } + if err = ct.GracefulClose(); err != nil { + t.Fatalf("%v.GracefulClose() = %v, want ", ct, err) + } + var wg sync.WaitGroup + // Expect the failure for all the follow-up streams because ct has been closed gracefully. + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + if _, err := ct.NewStream(context.Background(), callHdr); err != ErrConnClosing { + t.Errorf("%v.NewStream(_, _) = _, %v, want _, %v", ct, err, ErrConnClosing) + } + }() + } + opts := Options{ + Last: true, + Delay: false, + } + // The stream which was created before graceful close can still proceed. + if err := ct.Write(s, expectedRequest, &opts); err != nil { + t.Fatalf("%v.Write(_, _, _) = %v, want ", ct, err) + } + p := make([]byte, len(expectedResponse)) + if _, err := io.ReadFull(s, p); err != nil || !bytes.Equal(p, expectedResponse) { + t.Fatalf("io.ReadFull(_, %v) = _, %v, want %v, ", err, p, expectedResponse) + } + if _, err = io.ReadFull(s, p); err != io.EOF { + t.Fatalf("Failed to complete the stream %v; want ", err) + } + wg.Wait() + ct.Close() + server.stop() +} + +func TestLargeMessageSuspension(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, suspended) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Large", + } + // Set a long enough timeout for writing a large message out. + ctx, _ := context.WithTimeout(context.Background(), time.Second) + s, err := ct.NewStream(ctx, callHdr) + if err != nil { + t.Fatalf("failed to open stream: %v", err) + } + // Write should not be done successfully due to flow control. + err = ct.Write(s, expectedRequestLarge, &Options{Last: true, Delay: false}) + expectedErr := StreamErrorf(codes.DeadlineExceeded, "%v", context.DeadlineExceeded) + if err == nil || err != expectedErr { + t.Fatalf("Write got %v, want %v", err, expectedErr) + } + ct.Close() + server.stop() +} + +func TestMaxStreams(t *testing.T) { + server, ct := setUp(t, 0, 1, suspended) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo.Large", + } + // Have a pending stream which takes all streams quota. + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Fatalf("Failed to open stream: %v", err) + } + cc, ok := ct.(*http2Client) + if !ok { + t.Fatalf("Failed to convert %v to *http2Client", ct) + } + done := make(chan struct{}) + ch := make(chan int) + go func() { + for { + select { + case <-time.After(5 * time.Millisecond): + ch <- 0 + case <-time.After(5 * time.Second): + close(done) + return + } + } + }() + for { + select { + case <-ch: + case <-done: + t.Fatalf("Client has not received the max stream setting in 5 seconds.") + } + cc.mu.Lock() + // cc.streamsQuota should be initialized once receiving the 1st setting frame from + // the server. + if cc.streamsQuota != nil { + cc.mu.Unlock() + select { + case <-cc.streamsQuota.acquire(): + t.Fatalf("streamsQuota.acquire() becomes readable mistakenly.") + default: + if cc.streamsQuota.quota != 0 { + t.Fatalf("streamsQuota.quota got non-zero quota mistakenly.") + } + } + break + } + cc.mu.Unlock() + } + // Close the pending stream so that the streams quota becomes available for the next new stream. + ct.CloseStream(s, nil) + select { + case i := <-cc.streamsQuota.acquire(): + if i != 1 { + t.Fatalf("streamsQuota.acquire() got %d quota, want 1.", i) + } + cc.streamsQuota.add(i) + default: + t.Fatalf("streamsQuota.acquire() is not readable.") + } + if _, err := ct.NewStream(context.Background(), callHdr); err != nil { + t.Fatalf("Failed to open stream: %v", err) + } + ct.Close() + server.stop() +} + +func TestServerContextCanceledOnClosedConnection(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, suspended) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo", + } + var sc *http2Server + // Wait until the server transport is setup. + for { + server.mu.Lock() + if len(server.conns) == 0 { + server.mu.Unlock() + time.Sleep(time.Millisecond) + continue + } + for k := range server.conns { + var ok bool + sc, ok = k.(*http2Server) + if !ok { + t.Fatalf("Failed to convert %v to *http2Server", k) + } + } + server.mu.Unlock() + break + } + cc, ok := ct.(*http2Client) + if !ok { + t.Fatalf("Failed to convert %v to *http2Client", ct) + } + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Fatalf("Failed to open stream: %v", err) + } + // Make sure the headers frame is flushed out. + <-cc.writableChan + if err = cc.framer.writeData(true, s.id, false, make([]byte, http2MaxFrameLen)); err != nil { + t.Fatalf("Failed to write data: %v", err) + } + cc.writableChan <- 0 + // Loop until the server side stream is created. + var ss *Stream + for { + time.Sleep(time.Second) + sc.mu.Lock() + if len(sc.activeStreams) == 0 { + sc.mu.Unlock() + continue + } + ss = sc.activeStreams[s.id] + sc.mu.Unlock() + break + } + cc.Close() + select { + case <-ss.Context().Done(): + if ss.Context().Err() != context.Canceled { + t.Fatalf("ss.Context().Err() got %v, want %v", ss.Context().Err(), context.Canceled) + } + case <-time.After(5 * time.Second): + t.Fatalf("Failed to cancel the context of the sever side stream.") + } +} + +func TestServerWithMisbehavedClient(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, suspended) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo", + } + var sc *http2Server + // Wait until the server transport is setup. + for { + server.mu.Lock() + if len(server.conns) == 0 { + server.mu.Unlock() + time.Sleep(time.Millisecond) + continue + } + for k := range server.conns { + var ok bool + sc, ok = k.(*http2Server) + if !ok { + t.Fatalf("Failed to convert %v to *http2Server", k) + } + } + server.mu.Unlock() + break + } + cc, ok := ct.(*http2Client) + if !ok { + t.Fatalf("Failed to convert %v to *http2Client", ct) + } + // Test server behavior for violation of stream flow control window size restriction. + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Fatalf("Failed to open stream: %v", err) + } + var sent int + // Drain the stream flow control window + <-cc.writableChan + if err = cc.framer.writeData(true, s.id, false, make([]byte, http2MaxFrameLen)); err != nil { + t.Fatalf("Failed to write data: %v", err) + } + cc.writableChan <- 0 + sent += http2MaxFrameLen + // Wait until the server creates the corresponding stream and receive some data. + var ss *Stream + for { + time.Sleep(time.Millisecond) + sc.mu.Lock() + if len(sc.activeStreams) == 0 { + sc.mu.Unlock() + continue + } + ss = sc.activeStreams[s.id] + sc.mu.Unlock() + ss.fc.mu.Lock() + if ss.fc.pendingData > 0 { + ss.fc.mu.Unlock() + break + } + ss.fc.mu.Unlock() + } + if ss.fc.pendingData != http2MaxFrameLen || ss.fc.pendingUpdate != 0 || sc.fc.pendingData != http2MaxFrameLen || sc.fc.pendingUpdate != 0 { + t.Fatalf("Server mistakenly updates inbound flow control params: got %d, %d, %d, %d; want %d, %d, %d, %d", ss.fc.pendingData, ss.fc.pendingUpdate, sc.fc.pendingData, sc.fc.pendingUpdate, http2MaxFrameLen, 0, http2MaxFrameLen, 0) + } + // Keep sending until the server inbound window is drained for that stream. + for sent <= initialWindowSize { + <-cc.writableChan + if err = cc.framer.writeData(true, s.id, false, make([]byte, 1)); err != nil { + t.Fatalf("Failed to write data: %v", err) + } + cc.writableChan <- 0 + sent++ + } + // Server sent a resetStream for s already. + code := http2ErrConvTab[http2.ErrCodeFlowControl] + if _, err := io.ReadFull(s, make([]byte, 1)); err != io.EOF || s.statusCode != code { + t.Fatalf("%v got err %v with statusCode %d, want err with statusCode %d", s, err, s.statusCode, code) + } + + if ss.fc.pendingData != 0 || ss.fc.pendingUpdate != 0 || sc.fc.pendingData != 0 || sc.fc.pendingUpdate <= initialWindowSize { + t.Fatalf("Server mistakenly resets inbound flow control params: got %d, %d, %d, %d; want 0, 0, 0, >%d", ss.fc.pendingData, ss.fc.pendingUpdate, sc.fc.pendingData, sc.fc.pendingUpdate, initialWindowSize) + } + ct.CloseStream(s, nil) + // Test server behavior for violation of connection flow control window size restriction. + // + // Keep creating new streams until the connection window is drained on the server and + // the server tears down the connection. + for { + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + // The server tears down the connection. + break + } + <-cc.writableChan + cc.framer.writeData(true, s.id, true, make([]byte, http2MaxFrameLen)) + cc.writableChan <- 0 + } + ct.Close() + server.stop() +} + +func TestClientWithMisbehavedServer(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, misbehaved) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo", + } + conn, ok := ct.(*http2Client) + if !ok { + t.Fatalf("Failed to convert %v to *http2Client", ct) + } + // Test the logic for the violation of stream flow control window size restriction. + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + t.Fatalf("Failed to open stream: %v", err) + } + if err := ct.Write(s, expectedRequest, &Options{Last: true, Delay: false}); err != nil { + t.Fatalf("Failed to write: %v", err) + } + // Read without window update. + for { + p := make([]byte, http2MaxFrameLen) + if _, err = s.dec.Read(p); err != nil { + break + } + } + if s.fc.pendingData <= initialWindowSize || s.fc.pendingUpdate != 0 || conn.fc.pendingData <= initialWindowSize || conn.fc.pendingUpdate != 0 { + t.Fatalf("Client mistakenly updates inbound flow control params: got %d, %d, %d, %d; want >%d, %d, >%d, %d", s.fc.pendingData, s.fc.pendingUpdate, conn.fc.pendingData, conn.fc.pendingUpdate, initialWindowSize, 0, initialWindowSize, 0) + } + if err != io.EOF || s.statusCode != codes.Internal { + t.Fatalf("Got err %v and the status code %d, want and the code %d", err, s.statusCode, codes.Internal) + } + conn.CloseStream(s, err) + if s.fc.pendingData != 0 || s.fc.pendingUpdate != 0 || conn.fc.pendingData != 0 || conn.fc.pendingUpdate <= initialWindowSize { + t.Fatalf("Client mistakenly resets inbound flow control params: got %d, %d, %d, %d; want 0, 0, 0, >%d", s.fc.pendingData, s.fc.pendingUpdate, conn.fc.pendingData, conn.fc.pendingUpdate, initialWindowSize) + } + // Test the logic for the violation of the connection flow control window size restriction. + // + // Generate enough streams to drain the connection window. + callHdr = &CallHdr{ + Host: "localhost", + Method: "foo.MaxFrame", + } + for i := 0; i < int(initialConnWindowSize/initialWindowSize+10); i++ { + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + break + } + if err := ct.Write(s, expectedRequest, &Options{Last: true, Delay: false}); err != nil { + break + } + } + // http2Client.errChan is closed due to connection flow control window size violation. + <-conn.Error() + ct.Close() + server.stop() +} + +func TestMalformedStatus(t *testing.T) { + server, ct := setUp(t, 0, math.MaxUint32, malformedStatus) + callHdr := &CallHdr{ + Host: "localhost", + Method: "foo", + } + s, err := ct.NewStream(context.Background(), callHdr) + if err != nil { + return + } + opts := Options{ + Last: true, + Delay: false, + } + if err := ct.Write(s, expectedRequest, &opts); err != nil { + t.Fatalf("Failed to write the request: %v", err) + } + p := make([]byte, http2MaxFrameLen) + expectedErr := StreamErrorf(codes.Internal, "invalid header field value \"\\n\"") + if _, err = s.dec.Read(p); err != expectedErr { + t.Fatalf("Read the err %v, want %v", err, expectedErr) + } + ct.Close() + server.stop() +} + +func TestStreamContext(t *testing.T) { + expectedStream := Stream{} + ctx := newContextWithStream(context.Background(), &expectedStream) + s, ok := StreamFromContext(ctx) + if !ok || !reflect.DeepEqual(expectedStream, *s) { + t.Fatalf("GetStreamFromContext(%v) = %v, %t, want: %v, true", ctx, *s, ok, expectedStream) + } +} + +func TestIsReservedHeader(t *testing.T) { + tests := []struct { + h string + want bool + }{ + {"", false}, // but should be rejected earlier + {"foo", false}, + {"content-type", true}, + {"grpc-message-type", true}, + {"grpc-encoding", true}, + {"grpc-message", true}, + {"grpc-status", true}, + {"grpc-timeout", true}, + {"te", true}, + } + for _, tt := range tests { + got := isReservedHeader(tt.h) + if got != tt.want { + t.Errorf("isReservedHeader(%q) = %v; want %v", tt.h, got, tt.want) + } + } +}