parent
c751e782ed
commit
856380ca87
@ -1,2 +0,0 @@
|
||||
/pkg
|
||||
/bin
|
14
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
14
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
@ -1,14 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
: ${PROG:=$(basename ${BASH_SOURCE})}
|
||||
|
||||
_cli_bash_autocomplete() {
|
||||
local cur opts base
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _cli_bash_autocomplete $PROG
|
@ -1,5 +0,0 @@
|
||||
autoload -U compinit && compinit
|
||||
autoload -U bashcompinit && bashcompinit
|
||||
|
||||
script_dir=$(dirname $0)
|
||||
source ${script_dir}/bash_autocomplete
|
85
Godeps/_workspace/src/github.com/codegangsta/inject/translations/README_zh_cn.md
generated
vendored
85
Godeps/_workspace/src/github.com/codegangsta/inject/translations/README_zh_cn.md
generated
vendored
@ -1,19 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/codeskyblue/kexec"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := kexec.CommandString("python flask_main.py")
|
||||
p.Start()
|
||||
time.Sleep(3 * time.Second)
|
||||
err := p.Terminate(syscall.SIGKILL)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
import flask
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=46732, debug=True)
|
@ -1 +0,0 @@
|
||||
web: python flask_main.py
|
@ -1,11 +0,0 @@
|
||||
import flask
|
||||
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
def homepage():
|
||||
return 'Home'
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host='0.0.0.0')
|
@ -1,22 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kproc"
|
||||
"log"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := kproc.ProcString("python flask_main.py")
|
||||
p.Start()
|
||||
time.Sleep(10 * time.Second)
|
||||
err := p.Terminate(syscall.SIGKILL)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
out, _ := exec.Command("lsof", "-i:5000").CombinedOutput()
|
||||
fmt.Println(string(out))
|
||||
}
|
Binary file not shown.
196
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
196
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
@ -1,196 +0,0 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: proto3_proto/proto3.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto3_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
proto3_proto/proto3.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Message
|
||||
Nested
|
||||
MessageWithMap
|
||||
*/
|
||||
package proto3_proto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import google_protobuf "github.com/golang/protobuf/ptypes/any"
|
||||
import testdata "github.com/golang/protobuf/proto/testdata"
|
||||
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
type Message_Humour int32
|
||||
|
||||
const (
|
||||
Message_UNKNOWN Message_Humour = 0
|
||||
Message_PUNS Message_Humour = 1
|
||||
Message_SLAPSTICK Message_Humour = 2
|
||||
Message_BILL_BAILEY Message_Humour = 3
|
||||
)
|
||||
|
||||
var Message_Humour_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "PUNS",
|
||||
2: "SLAPSTICK",
|
||||
3: "BILL_BAILEY",
|
||||
}
|
||||
var Message_Humour_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"PUNS": 1,
|
||||
"SLAPSTICK": 2,
|
||||
"BILL_BAILEY": 3,
|
||||
}
|
||||
|
||||
func (x Message_Humour) String() string {
|
||||
return proto.EnumName(Message_Humour_name, int32(x))
|
||||
}
|
||||
func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
|
||||
|
||||
type Message struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
|
||||
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"`
|
||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"`
|
||||
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
|
||||
Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"`
|
||||
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
|
||||
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"`
|
||||
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"`
|
||||
ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Message) GetNested() *Nested {
|
||||
if m != nil {
|
||||
return m.Nested
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetTerrain() map[string]*Nested {
|
||||
if m != nil {
|
||||
return m.Terrain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Field() *testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Field
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetAnything() *google_protobuf.Any {
|
||||
if m != nil {
|
||||
return m.Anything
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetManyThings() []*google_protobuf.Any {
|
||||
if m != nil {
|
||||
return m.ManyThings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Nested) Reset() { *m = Nested{} }
|
||||
func (m *Nested) String() string { return proto.CompactTextString(m) }
|
||||
func (*Nested) ProtoMessage() {}
|
||||
func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
type MessageWithMap struct {
|
||||
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
|
||||
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageWithMap) ProtoMessage() {}
|
||||
func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
|
||||
if m != nil {
|
||||
return m.ByteMapping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
|
||||
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
|
||||
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
|
||||
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 593 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0xff, 0x6e, 0xd3, 0x30,
|
||||
0x10, 0xc7, 0x49, 0xdb, 0xa5, 0xd9, 0x25, 0xdd, 0x22, 0x33, 0x24, 0xaf, 0x42, 0x68, 0x14, 0x09,
|
||||
0x4d, 0xfc, 0xc8, 0x50, 0x11, 0xd2, 0x84, 0x10, 0x68, 0x1b, 0x43, 0x54, 0xeb, 0x4a, 0xe5, 0x6e,
|
||||
0x4c, 0xfc, 0x15, 0x39, 0xad, 0xdb, 0x46, 0x34, 0x4e, 0x95, 0x38, 0x48, 0x79, 0x1d, 0xde, 0x84,
|
||||
0x37, 0xc3, 0xb1, 0xd3, 0x2e, 0x9b, 0x0a, 0x7f, 0xd9, 0xbe, 0xfb, 0xdc, 0x9d, 0xef, 0x7b, 0x07,
|
||||
0xfb, 0xcb, 0x24, 0x16, 0xf1, 0x5b, 0x5f, 0x1d, 0x47, 0xfa, 0xe1, 0xa9, 0x03, 0x39, 0x55, 0x57,
|
||||
0x7b, 0x7f, 0x16, 0xc7, 0xb3, 0x05, 0xd3, 0x48, 0x90, 0x4d, 0x8f, 0x28, 0xcf, 0x35, 0xd8, 0x7e,
|
||||
0x28, 0x58, 0x2a, 0x26, 0x54, 0xd0, 0xa3, 0xe2, 0xa2, 0x8d, 0x9d, 0x3f, 0x26, 0x34, 0x2f, 0x59,
|
||||
0x9a, 0xd2, 0x19, 0x43, 0x08, 0x1a, 0x9c, 0x46, 0x0c, 0x1b, 0x07, 0xc6, 0xe1, 0x36, 0x51, 0x77,
|
||||
0x74, 0x0c, 0xd6, 0x3c, 0x5c, 0xd0, 0x24, 0x14, 0x39, 0xae, 0x49, 0xfb, 0x4e, 0xf7, 0xb1, 0x57,
|
||||
0x2d, 0xe8, 0x95, 0xc1, 0xde, 0xd7, 0x2c, 0x8a, 0xb3, 0x84, 0xac, 0x69, 0x74, 0x00, 0xce, 0x9c,
|
||||
0x85, 0xb3, 0xb9, 0xf0, 0x43, 0xee, 0x8f, 0x23, 0x5c, 0x97, 0xd1, 0x2d, 0x02, 0xda, 0xd6, 0xe3,
|
||||
0x67, 0x51, 0x51, 0xaf, 0xf8, 0x0e, 0x6e, 0x48, 0x8f, 0x43, 0xd4, 0x1d, 0x3d, 0x05, 0x27, 0x61,
|
||||
0x69, 0xb6, 0x10, 0xfe, 0x38, 0xce, 0xb8, 0xc0, 0x4d, 0xe9, 0xab, 0x13, 0x5b, 0xdb, 0xce, 0x0a,
|
||||
0x13, 0x7a, 0x06, 0x2d, 0x91, 0x64, 0xcc, 0x4f, 0xc7, 0xb1, 0x48, 0x23, 0xca, 0xb1, 0x25, 0x19,
|
||||
0x8b, 0x38, 0x85, 0x71, 0x54, 0xda, 0xd0, 0x1e, 0x6c, 0x49, 0x7f, 0xc2, 0xf0, 0xb6, 0x74, 0xd6,
|
||||
0x88, 0x7e, 0x20, 0x17, 0xea, 0x3f, 0x59, 0x8e, 0xb7, 0x0e, 0xea, 0x87, 0x0d, 0x52, 0x5c, 0xd1,
|
||||
0x2b, 0x30, 0xb9, 0x54, 0x83, 0x4d, 0xb0, 0x29, 0x41, 0xbb, 0xbb, 0x77, 0xb7, 0xbb, 0x81, 0xf2,
|
||||
0x91, 0x92, 0x41, 0x1f, 0xa0, 0x29, 0x58, 0x92, 0xd0, 0x90, 0x63, 0x90, 0x39, 0xec, 0x6e, 0x67,
|
||||
0xb3, 0x18, 0x57, 0x1a, 0x3a, 0xe7, 0x22, 0xc9, 0xc9, 0x2a, 0x44, 0x6a, 0xa9, 0x67, 0xd5, 0xf5,
|
||||
0xa7, 0x21, 0x5b, 0x4c, 0xb0, 0xad, 0x2a, 0x3e, 0xf2, 0x56, 0x73, 0xf1, 0x46, 0x59, 0xf0, 0x99,
|
||||
0x4d, 0xa9, 0xec, 0x34, 0x25, 0xb6, 0x46, 0xbf, 0x14, 0x24, 0xea, 0xad, 0x23, 0x7f, 0xd1, 0x45,
|
||||
0xc6, 0x70, 0x4b, 0x15, 0x7f, 0xbe, 0xb9, 0xf8, 0x50, 0x91, 0xdf, 0x0b, 0x50, 0x7f, 0xa0, 0x4c,
|
||||
0xa5, 0x2c, 0xe8, 0x0d, 0x58, 0x72, 0x25, 0xc4, 0x3c, 0xe4, 0x33, 0xbc, 0x53, 0xb6, 0xac, 0x77,
|
||||
0xc6, 0x5b, 0xed, 0x8c, 0x77, 0xc2, 0x73, 0xb2, 0xa6, 0xd0, 0x3b, 0xb0, 0xa5, 0xa2, 0xb9, 0xaf,
|
||||
0x5e, 0x29, 0xde, 0x55, 0xb5, 0x37, 0x07, 0x41, 0x01, 0x5e, 0x29, 0xae, 0x3d, 0x04, 0xa7, 0x2a,
|
||||
0xc3, 0x4a, 0x7b, 0xbd, 0x5c, 0x4a, 0xfb, 0x17, 0xb0, 0xa5, 0xdb, 0xa9, 0xfd, 0x47, 0x7a, 0x8d,
|
||||
0xbc, 0xaf, 0x1d, 0x1b, 0xed, 0x6b, 0x70, 0xef, 0xf7, 0xb6, 0x21, 0xeb, 0xcb, 0xbb, 0x59, 0xff,
|
||||
0x21, 0xef, 0x6d, 0xda, 0xce, 0x27, 0x30, 0xf5, 0xf2, 0x22, 0x1b, 0x9a, 0xd7, 0x83, 0x8b, 0xc1,
|
||||
0xb7, 0x9b, 0x81, 0xfb, 0x00, 0x59, 0xd0, 0x18, 0x5e, 0x0f, 0x46, 0xae, 0x81, 0x5a, 0xb0, 0x3d,
|
||||
0xea, 0x9f, 0x0c, 0x47, 0x57, 0xbd, 0xb3, 0x0b, 0xb7, 0x86, 0x76, 0xc1, 0x3e, 0xed, 0xf5, 0xfb,
|
||||
0xfe, 0xe9, 0x49, 0xaf, 0x7f, 0xfe, 0xc3, 0xad, 0x77, 0x9e, 0x80, 0xa9, 0x3f, 0x5b, 0x6c, 0x5d,
|
||||
0x90, 0x71, 0xbe, 0xfa, 0x8f, 0x7e, 0x74, 0x7e, 0x1b, 0xb0, 0x53, 0x0e, 0xe7, 0x26, 0x14, 0xf3,
|
||||
0x4b, 0xba, 0x44, 0x52, 0x9c, 0x20, 0x17, 0xcc, 0x8f, 0xe8, 0x72, 0x59, 0x4c, 0xc2, 0x50, 0xa2,
|
||||
0xbe, 0xde, 0x38, 0xd0, 0x32, 0xc6, 0x3b, 0x95, 0x01, 0x97, 0x9a, 0x2f, 0xe7, 0x1a, 0xdc, 0x5a,
|
||||
0xda, 0x1f, 0xc1, 0xbd, 0x0f, 0x54, 0xc5, 0xb1, 0xb4, 0x38, 0x7b, 0x55, 0x71, 0x9c, 0x8a, 0x0a,
|
||||
0x81, 0xa9, 0x4b, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xab, 0x07, 0xe8, 0xfe, 0x6a, 0x04, 0x00,
|
||||
0x00,
|
||||
}
|
72
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
72
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
@ -1,72 +0,0 @@
|
||||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 "google/protobuf/any.proto";
|
||||
import "testdata/test.proto";
|
||||
|
||||
package proto3_proto;
|
||||
|
||||
message Message {
|
||||
enum Humour {
|
||||
UNKNOWN = 0;
|
||||
PUNS = 1;
|
||||
SLAPSTICK = 2;
|
||||
BILL_BAILEY = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
Humour hilarity = 2;
|
||||
uint32 height_in_cm = 3;
|
||||
bytes data = 4;
|
||||
int64 result_count = 7;
|
||||
bool true_scotsman = 8;
|
||||
float score = 9;
|
||||
|
||||
repeated uint64 key = 5;
|
||||
Nested nested = 6;
|
||||
|
||||
map<string, Nested> terrain = 10;
|
||||
testdata.SubDefaults proto2_field = 11;
|
||||
map<string, testdata.SubDefaults> proto2_value = 13;
|
||||
|
||||
google.protobuf.Any anything = 14;
|
||||
repeated google.protobuf.Any many_things = 15;
|
||||
}
|
||||
|
||||
message Nested {
|
||||
string bunny = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<bool, bytes> byte_mapping = 1;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
// 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.5
|
||||
|
||||
package ctxhttp
|
||||
|
||||
import "net/http"
|
||||
|
||||
func canceler(client *http.Client, req *http.Request) func() {
|
||||
// TODO(djd): Respect any existing value of req.Cancel.
|
||||
ch := make(chan struct{})
|
||||
req.Cancel = ch
|
||||
|
||||
return func() {
|
||||
close(ch)
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// 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.5
|
||||
|
||||
package ctxhttp
|
||||
|
||||
import "net/http"
|
||||
|
||||
type requestCanceler interface {
|
||||
CancelRequest(*http.Request)
|
||||
}
|
||||
|
||||
func canceler(client *http.Client, req *http.Request) func() {
|
||||
rc, ok := client.Transport.(requestCanceler)
|
||||
if !ok {
|
||||
return func() {}
|
||||
}
|
||||
return func() {
|
||||
rc.CancelRequest(req)
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
||||
package 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
|
||||
}
|
||||
|
||||
// Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
|
||||
cancel := canceler(client, req)
|
||||
|
||||
type responseAndError struct {
|
||||
resp *http.Response
|
||||
err error
|
||||
}
|
||||
result := make(chan responseAndError, 1)
|
||||
|
||||
go func() {
|
||||
resp, err := client.Do(req)
|
||||
testHookDoReturned()
|
||||
result <- responseAndError{resp, err}
|
||||
}()
|
||||
|
||||
var resp *http.Response
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
testHookContextDoneBeforeHeaders()
|
||||
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():
|
||||
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
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// 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.5
|
||||
|
||||
package http2
|
||||
|
||||
import "net/http"
|
||||
|
||||
func requestCancel(req *http.Request) <-chan struct{} { return req.Cancel }
|
@ -1,5 +0,0 @@
|
||||
h2demo
|
||||
h2demo.linux
|
||||
client-id.dat
|
||||
client-secret.dat
|
||||
token.dat
|
@ -1,8 +0,0 @@
|
||||
h2demo.linux: h2demo.go
|
||||
GOOS=linux go build --tags=h2demo -o h2demo.linux .
|
||||
|
||||
FORCE:
|
||||
|
||||
upload: FORCE
|
||||
go install golang.org/x/build/cmd/upload
|
||||
upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo
|
@ -1,16 +0,0 @@
|
||||
|
||||
Client:
|
||||
-- Firefox nightly with about:config network.http.spdy.enabled.http2draft set true
|
||||
-- Chrome: go to chrome://flags/#enable-spdy4, save and restart (button at bottom)
|
||||
|
||||
Make CA:
|
||||
$ openssl genrsa -out rootCA.key 2048
|
||||
$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
|
||||
... install that to Firefox
|
||||
|
||||
Make cert:
|
||||
$ openssl genrsa -out server.key 2048
|
||||
$ openssl req -new -key server.key -out server.csr
|
||||
$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
|
||||
|
||||
|
@ -1,504 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build h2demo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"camlistore.org/pkg/googlestorage"
|
||||
"go4.org/syncutil/singleflight"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var (
|
||||
prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
|
||||
|
||||
httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
|
||||
httpAddr = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
|
||||
|
||||
hostHTTP = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
|
||||
hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
|
||||
)
|
||||
|
||||
func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, `<html>
|
||||
<body>
|
||||
<h1>Go + HTTP/2</h1>
|
||||
<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
|
||||
<p>Unfortunately, you're <b>not</b> using HTTP/2 right now. To do so:</p>
|
||||
<ul>
|
||||
<li>Use Firefox Nightly or go to <b>about:config</b> and enable "network.http.spdy.enabled.http2draft"</li>
|
||||
<li>Use Google Chrome Canary and/or go to <b>chrome://flags/#enable-spdy4</b> to <i>Enable SPDY/4</i> (Chrome's name for HTTP/2)</li>
|
||||
</ul>
|
||||
<p>See code & instructions for connecting at <a href="https://github.com/golang/net/tree/master/http2">https://github.com/golang/net/tree/master/http2</a>.</p>
|
||||
|
||||
</body></html>`)
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
io.WriteString(w, `<html>
|
||||
<body>
|
||||
<h1>Go + HTTP/2</h1>
|
||||
|
||||
<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a
|
||||
href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
|
||||
|
||||
<p>Congratulations, <b>you're using HTTP/2 right now</b>.</p>
|
||||
|
||||
<p>This server exists for others in the HTTP/2 community to test their HTTP/2 client implementations and point out flaws in our server.</p>
|
||||
|
||||
<p>
|
||||
The code is at <a href="https://golang.org/x/net/http2">golang.org/x/net/http2</a> and
|
||||
is used transparently by the Go standard library from Go 1.6 and later.
|
||||
</p>
|
||||
|
||||
<p>Contact info: <i>bradfitz@golang.org</i>, or <a
|
||||
href="https://golang.org/s/http2bug">file a bug</a>.</p>
|
||||
|
||||
<h2>Handlers for testing</h2>
|
||||
<ul>
|
||||
<li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li>
|
||||
<li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li>
|
||||
<li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li>
|
||||
<li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li>
|
||||
<li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li>
|
||||
<li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
|
||||
<li>GET <a href="/goroutines">/goroutines</a> to see all active goroutines in this server</li>
|
||||
<li>PUT something to <a href="/crc32">/crc32</a> to get a count of number of bytes and its CRC-32</li>
|
||||
<li>PUT something to <a href="/ECHO">/ECHO</a> and it will be streamed back to you capitalized</li>
|
||||
</ul>
|
||||
|
||||
</body></html>`)
|
||||
}
|
||||
|
||||
func reqInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "Method: %s\n", r.Method)
|
||||
fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
|
||||
fmt.Fprintf(w, "Host: %s\n", r.Host)
|
||||
fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
|
||||
fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
|
||||
fmt.Fprintf(w, "URL: %#v\n", r.URL)
|
||||
fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
|
||||
fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
|
||||
fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
|
||||
fmt.Fprintf(w, "\nHeaders:\n")
|
||||
r.Header.Write(w)
|
||||
}
|
||||
|
||||
func crcHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PUT" {
|
||||
http.Error(w, "PUT required.", 400)
|
||||
return
|
||||
}
|
||||
crc := crc32.NewIEEE()
|
||||
n, err := io.Copy(crc, r.Body)
|
||||
if err == nil {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "bytes=%d, CRC32=%x", n, crc.Sum(nil))
|
||||
}
|
||||
}
|
||||
|
||||
type capitalizeReader struct {
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (cr capitalizeReader) Read(p []byte) (n int, err error) {
|
||||
n, err = cr.r.Read(p)
|
||||
for i, b := range p[:n] {
|
||||
if b >= 'a' && b <= 'z' {
|
||||
p[i] = b - ('a' - 'A')
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type flushWriter struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (fw flushWriter) Write(p []byte) (n int, err error) {
|
||||
n, err = fw.w.Write(p)
|
||||
if f, ok := fw.w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PUT" {
|
||||
http.Error(w, "PUT required.", 400)
|
||||
return
|
||||
}
|
||||
io.Copy(flushWriter{w}, capitalizeReader{r.Body})
|
||||
}
|
||||
|
||||
var (
|
||||
fsGrp singleflight.Group
|
||||
fsMu sync.Mutex // guards fsCache
|
||||
fsCache = map[string]http.Handler{}
|
||||
)
|
||||
|
||||
// fileServer returns a file-serving handler that proxies URL.
|
||||
// It lazily fetches URL on the first access and caches its contents forever.
|
||||
func fileServer(url string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
hi, err := fsGrp.Do(url, func() (interface{}, error) {
|
||||
fsMu.Lock()
|
||||
if h, ok := fsCache[url]; ok {
|
||||
fsMu.Unlock()
|
||||
return h, nil
|
||||
}
|
||||
fsMu.Unlock()
|
||||
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modTime := time.Now()
|
||||
var h http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeContent(w, r, path.Base(url), modTime, bytes.NewReader(slurp))
|
||||
})
|
||||
fsMu.Lock()
|
||||
fsCache[url] = h
|
||||
fsMu.Unlock()
|
||||
return h, nil
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
hi.(http.Handler).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func clockStreamHandler(w http.ResponseWriter, r *http.Request) {
|
||||
clientGone := w.(http.CloseNotifier).CloseNotify()
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
|
||||
io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))
|
||||
|
||||
for {
|
||||
fmt.Fprintf(w, "%v\n", time.Now())
|
||||
w.(http.Flusher).Flush()
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-clientGone:
|
||||
log.Printf("Client %v disconnected from the clock", r.RemoteAddr)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func registerHandlers() {
|
||||
tiles := newGopherTilesHandler()
|
||||
|
||||
mux2 := http.NewServeMux()
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.TLS == nil {
|
||||
if r.URL.Path == "/gophertiles" {
|
||||
tiles.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
if r.ProtoMajor == 1 {
|
||||
if r.URL.Path == "/reqinfo" {
|
||||
reqInfoHandler(w, r)
|
||||
return
|
||||
}
|
||||
homeOldHTTP(w, r)
|
||||
return
|
||||
}
|
||||
mux2.ServeHTTP(w, r)
|
||||
})
|
||||
mux2.HandleFunc("/", home)
|
||||
mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png"))
|
||||
mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz"))
|
||||
mux2.HandleFunc("/reqinfo", reqInfoHandler)
|
||||
mux2.HandleFunc("/crc32", crcHandler)
|
||||
mux2.HandleFunc("/ECHO", echoCapitalHandler)
|
||||
mux2.HandleFunc("/clockstream", clockStreamHandler)
|
||||
mux2.Handle("/gophertiles", tiles)
|
||||
mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
})
|
||||
stripHomedir := regexp.MustCompile(`/(Users|home)/\w+`)
|
||||
mux2.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
buf := make([]byte, 2<<20)
|
||||
w.Write(stripHomedir.ReplaceAll(buf[:runtime.Stack(buf, true)], nil))
|
||||
})
|
||||
}
|
||||
|
||||
func newGopherTilesHandler() http.Handler {
|
||||
const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
|
||||
res, err := http.Get(gopherURL)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
log.Fatalf("Error fetching %s: %v", gopherURL, res.Status)
|
||||
}
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
im, err := jpeg.Decode(bytes.NewReader(slurp))
|
||||
if err != nil {
|
||||
if len(slurp) > 1024 {
|
||||
slurp = slurp[:1024]
|
||||
}
|
||||
log.Fatalf("Failed to decode gopher image: %v (got %q)", err, slurp)
|
||||
}
|
||||
|
||||
type subImager interface {
|
||||
SubImage(image.Rectangle) image.Image
|
||||
}
|
||||
const tileSize = 32
|
||||
xt := im.Bounds().Max.X / tileSize
|
||||
yt := im.Bounds().Max.Y / tileSize
|
||||
var tile [][][]byte // y -> x -> jpeg bytes
|
||||
for yi := 0; yi < yt; yi++ {
|
||||
var row [][]byte
|
||||
for xi := 0; xi < xt; xi++ {
|
||||
si := im.(subImager).SubImage(image.Rectangle{
|
||||
Min: image.Point{xi * tileSize, yi * tileSize},
|
||||
Max: image.Point{(xi + 1) * tileSize, (yi + 1) * tileSize},
|
||||
})
|
||||
buf := new(bytes.Buffer)
|
||||
if err := jpeg.Encode(buf, si, &jpeg.Options{Quality: 90}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
row = append(row, buf.Bytes())
|
||||
}
|
||||
tile = append(tile, row)
|
||||
}
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ms, _ := strconv.Atoi(r.FormValue("latency"))
|
||||
const nanosPerMilli = 1e6
|
||||
if r.FormValue("x") != "" {
|
||||
x, _ := strconv.Atoi(r.FormValue("x"))
|
||||
y, _ := strconv.Atoi(r.FormValue("y"))
|
||||
if ms <= 1000 {
|
||||
time.Sleep(time.Duration(ms) * nanosPerMilli)
|
||||
}
|
||||
if x >= 0 && x < xt && y >= 0 && y < yt {
|
||||
http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(tile[y][x]))
|
||||
return
|
||||
}
|
||||
}
|
||||
io.WriteString(w, "<html><body onload='showtimes()'>")
|
||||
fmt.Fprintf(w, "A grid of %d tiled images is below. Compare:<p>", xt*yt)
|
||||
for _, ms := range []int{0, 30, 200, 1000} {
|
||||
d := time.Duration(ms) * nanosPerMilli
|
||||
fmt.Fprintf(w, "[<a href='https://%s/gophertiles?latency=%d'>HTTP/2, %v latency</a>] [<a href='http://%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n",
|
||||
httpsHost(), ms, d,
|
||||
httpHost(), ms, d,
|
||||
)
|
||||
}
|
||||
io.WriteString(w, "<p>\n")
|
||||
cacheBust := time.Now().UnixNano()
|
||||
for y := 0; y < yt; y++ {
|
||||
for x := 0; x < xt; x++ {
|
||||
fmt.Fprintf(w, "<img width=%d height=%d src='/gophertiles?x=%d&y=%d&cachebust=%d&latency=%d'>",
|
||||
tileSize, tileSize, x, y, cacheBust, ms)
|
||||
}
|
||||
io.WriteString(w, "<br/>\n")
|
||||
}
|
||||
io.WriteString(w, `<p><div id='loadtimes'></div></p>
|
||||
<script>
|
||||
function showtimes() {
|
||||
var times = 'Times from connection start:<br>'
|
||||
times += 'DOM loaded: ' + (window.performance.timing.domContentLoadedEventEnd - window.performance.timing.connectStart) + 'ms<br>'
|
||||
times += 'DOM complete (images loaded): ' + (window.performance.timing.domComplete - window.performance.timing.connectStart) + 'ms<br>'
|
||||
document.getElementById('loadtimes').innerHTML = times
|
||||
}
|
||||
</script>
|
||||
<hr><a href='/'><< Back to Go HTTP/2 demo server</a></body></html>`)
|
||||
})
|
||||
}
|
||||
|
||||
func httpsHost() string {
|
||||
if *hostHTTPS != "" {
|
||||
return *hostHTTPS
|
||||
}
|
||||
if v := *httpsAddr; strings.HasPrefix(v, ":") {
|
||||
return "localhost" + v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func httpHost() string {
|
||||
if *hostHTTP != "" {
|
||||
return *hostHTTP
|
||||
}
|
||||
if v := *httpAddr; strings.HasPrefix(v, ":") {
|
||||
return "localhost" + v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func serveProdTLS() error {
|
||||
c, err := googlestorage.NewServiceClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slurp := func(key string) ([]byte, error) {
|
||||
const bucket = "http2-demo-server-tls"
|
||||
rc, _, err := c.GetObject(&googlestorage.Object{
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error fetching GCS object %q in bucket %q: %v", key, bucket, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
return ioutil.ReadAll(rc)
|
||||
}
|
||||
certPem, err := slurp("http2.golang.org.chained.pem")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPem, err := slurp("http2.golang.org.key")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cert, err := tls.X509KeyPair(certPem, keyPem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv := &http.Server{
|
||||
TLSConfig: &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
},
|
||||
}
|
||||
http2.ConfigureServer(srv, &http2.Server{})
|
||||
ln, err := net.Listen("tcp", ":443")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig))
|
||||
}
|
||||
|
||||
type tcpKeepAliveListener struct {
|
||||
*net.TCPListener
|
||||
}
|
||||
|
||||
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||
tc, err := ln.AcceptTCP()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
func serveProd() error {
|
||||
errc := make(chan error, 2)
|
||||
go func() { errc <- http.ListenAndServe(":80", nil) }()
|
||||
go func() { errc <- serveProdTLS() }()
|
||||
return <-errc
|
||||
}
|
||||
|
||||
const idleTimeout = 5 * time.Minute
|
||||
const activeTimeout = 10 * time.Minute
|
||||
|
||||
// TODO: put this into the standard library and actually send
|
||||
// PING frames and GOAWAY, etc: golang.org/issue/14204
|
||||
func idleTimeoutHook() func(net.Conn, http.ConnState) {
|
||||
var mu sync.Mutex
|
||||
m := map[net.Conn]*time.Timer{}
|
||||
return func(c net.Conn, cs http.ConnState) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if t, ok := m[c]; ok {
|
||||
delete(m, c)
|
||||
t.Stop()
|
||||
}
|
||||
var d time.Duration
|
||||
switch cs {
|
||||
case http.StateNew, http.StateIdle:
|
||||
d = idleTimeout
|
||||
case http.StateActive:
|
||||
d = activeTimeout
|
||||
default:
|
||||
return
|
||||
}
|
||||
m[c] = time.AfterFunc(d, func() {
|
||||
log.Printf("closing idle conn %v after %v", c.RemoteAddr(), d)
|
||||
go c.Close()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var srv http.Server
|
||||
flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.")
|
||||
flag.Parse()
|
||||
srv.Addr = *httpsAddr
|
||||
srv.ConnState = idleTimeoutHook()
|
||||
|
||||
registerHandlers()
|
||||
|
||||
if *prod {
|
||||
*hostHTTP = "http2.golang.org"
|
||||
*hostHTTPS = "http2.golang.org"
|
||||
log.Fatal(serveProd())
|
||||
}
|
||||
|
||||
url := "https://" + httpsHost() + "/"
|
||||
log.Printf("Listening on " + url)
|
||||
http2.ConfigureServer(&srv, &http2.Server{})
|
||||
|
||||
if *httpAddr != "" {
|
||||
go func() {
|
||||
log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)")
|
||||
log.Fatal(http.ListenAndServe(*httpAddr, nil))
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
|
||||
}()
|
||||
select {}
|
||||
}
|
@ -1,302 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
proj = flag.String("project", "symbolic-datum-552", "name of Project")
|
||||
zone = flag.String("zone", "us-central1-a", "GCE zone")
|
||||
mach = flag.String("machinetype", "n1-standard-1", "Machine type")
|
||||
instName = flag.String("instance_name", "http2-demo", "Name of VM instance.")
|
||||
sshPub = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
|
||||
staticIP = flag.String("static_ip", "130.211.116.44", "Static IP to use. If empty, automatic.")
|
||||
|
||||
writeObject = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
|
||||
publicObject = flag.Bool("write_object_is_public", false, "Whether the object created by --write_object should be public.")
|
||||
)
|
||||
|
||||
func readFile(v string) string {
|
||||
slurp, err := ioutil.ReadFile(v)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading %s: %v", v, err)
|
||||
}
|
||||
return strings.TrimSpace(string(slurp))
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
// The client-id and secret should be for an "Installed Application" when using
|
||||
// the CLI. Later we'll use a web application with a callback.
|
||||
ClientID: readFile("client-id.dat"),
|
||||
ClientSecret: readFile("client-secret.dat"),
|
||||
Endpoint: google.Endpoint,
|
||||
Scopes: []string{
|
||||
compute.DevstorageFullControlScope,
|
||||
compute.ComputeScope,
|
||||
"https://www.googleapis.com/auth/sqlservice",
|
||||
"https://www.googleapis.com/auth/sqlservice.admin",
|
||||
},
|
||||
RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
|
||||
}
|
||||
|
||||
const baseConfig = `#cloud-config
|
||||
coreos:
|
||||
units:
|
||||
- name: h2demo.service
|
||||
command: start
|
||||
content: |
|
||||
[Unit]
|
||||
Description=HTTP2 Demo
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/h2demo http://storage.googleapis.com/http2-demo-server-tls/h2demo && chmod +x /opt/bin/h2demo'
|
||||
ExecStart=/opt/bin/h2demo --prod
|
||||
RestartSec=5s
|
||||
Restart=always
|
||||
Type=simple
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *proj == "" {
|
||||
log.Fatalf("Missing --project flag")
|
||||
}
|
||||
prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
|
||||
machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
|
||||
|
||||
const tokenFileName = "token.dat"
|
||||
tokenFile := tokenCacheFile(tokenFileName)
|
||||
tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
|
||||
token, err := tokenSource.Token()
|
||||
if err != nil {
|
||||
if *writeObject != "" {
|
||||
log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
|
||||
}
|
||||
log.Printf("Error getting token from %s: %v", tokenFileName, err)
|
||||
log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
|
||||
fmt.Print("\nEnter auth code: ")
|
||||
sc := bufio.NewScanner(os.Stdin)
|
||||
sc.Scan()
|
||||
authCode := strings.TrimSpace(sc.Text())
|
||||
token, err = config.Exchange(oauth2.NoContext, authCode)
|
||||
if err != nil {
|
||||
log.Fatalf("Error exchanging auth code for a token: %v", err)
|
||||
}
|
||||
if err := tokenFile.WriteToken(token); err != nil {
|
||||
log.Fatalf("Error writing to %s: %v", tokenFileName, err)
|
||||
}
|
||||
tokenSource = oauth2.ReuseTokenSource(token, nil)
|
||||
}
|
||||
|
||||
oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
|
||||
|
||||
if *writeObject != "" {
|
||||
writeCloudStorageObject(oauthClient)
|
||||
return
|
||||
}
|
||||
|
||||
computeService, _ := compute.New(oauthClient)
|
||||
|
||||
natIP := *staticIP
|
||||
if natIP == "" {
|
||||
// Try to find it by name.
|
||||
aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
|
||||
IPLoop:
|
||||
for _, asl := range aggAddrList.Items {
|
||||
for _, addr := range asl.Addresses {
|
||||
if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
|
||||
natIP = addr.Address
|
||||
break IPLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cloudConfig := baseConfig
|
||||
if *sshPub != "" {
|
||||
key := strings.TrimSpace(readFile(*sshPub))
|
||||
cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", key)
|
||||
}
|
||||
if os.Getenv("USER") == "bradfitz" {
|
||||
cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
|
||||
}
|
||||
const maxCloudConfig = 32 << 10 // per compute API docs
|
||||
if len(cloudConfig) > maxCloudConfig {
|
||||
log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
|
||||
}
|
||||
|
||||
instance := &compute.Instance{
|
||||
Name: *instName,
|
||||
Description: "Go Builder",
|
||||
MachineType: machType,
|
||||
Disks: []*compute.AttachedDisk{instanceDisk(computeService)},
|
||||
Tags: &compute.Tags{
|
||||
Items: []string{"http-server", "https-server"},
|
||||
},
|
||||
Metadata: &compute.Metadata{
|
||||
Items: []*compute.MetadataItems{
|
||||
{
|
||||
Key: "user-data",
|
||||
Value: &cloudConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
NetworkInterfaces: []*compute.NetworkInterface{
|
||||
&compute.NetworkInterface{
|
||||
AccessConfigs: []*compute.AccessConfig{
|
||||
&compute.AccessConfig{
|
||||
Type: "ONE_TO_ONE_NAT",
|
||||
Name: "External NAT",
|
||||
NatIP: natIP,
|
||||
},
|
||||
},
|
||||
Network: prefix + "/global/networks/default",
|
||||
},
|
||||
},
|
||||
ServiceAccounts: []*compute.ServiceAccount{
|
||||
{
|
||||
Email: "default",
|
||||
Scopes: []string{
|
||||
compute.DevstorageFullControlScope,
|
||||
compute.ComputeScope,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("Creating instance...")
|
||||
op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create instance: %v", err)
|
||||
}
|
||||
opName := op.Name
|
||||
log.Printf("Created. Waiting on operation %v", opName)
|
||||
OpLoop:
|
||||
for {
|
||||
time.Sleep(2 * time.Second)
|
||||
op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get op %s: %v", opName, err)
|
||||
}
|
||||
switch op.Status {
|
||||
case "PENDING", "RUNNING":
|
||||
log.Printf("Waiting on operation %v", opName)
|
||||
continue
|
||||
case "DONE":
|
||||
if op.Error != nil {
|
||||
for _, operr := range op.Error.Errors {
|
||||
log.Printf("Error: %+v", operr)
|
||||
}
|
||||
log.Fatalf("Failed to start.")
|
||||
}
|
||||
log.Printf("Success. %+v", op)
|
||||
break OpLoop
|
||||
default:
|
||||
log.Fatalf("Unknown status %q: %+v", op.Status, op)
|
||||
}
|
||||
}
|
||||
|
||||
inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting instance after creation: %v", err)
|
||||
}
|
||||
ij, _ := json.MarshalIndent(inst, "", " ")
|
||||
log.Printf("Instance: %s", ij)
|
||||
}
|
||||
|
||||
func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
|
||||
const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-stable-444-5-0-v20141016"
|
||||
diskName := *instName + "-disk"
|
||||
|
||||
return &compute.AttachedDisk{
|
||||
AutoDelete: true,
|
||||
Boot: true,
|
||||
Type: "PERSISTENT",
|
||||
InitializeParams: &compute.AttachedDiskInitializeParams{
|
||||
DiskName: diskName,
|
||||
SourceImage: imageURL,
|
||||
DiskSizeGb: 50,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func writeCloudStorageObject(httpClient *http.Client) {
|
||||
content := os.Stdin
|
||||
const maxSlurp = 1 << 20
|
||||
var buf bytes.Buffer
|
||||
n, err := io.CopyN(&buf, content, maxSlurp)
|
||||
if err != nil && err != io.EOF {
|
||||
log.Fatalf("Error reading from stdin: %v, %v", n, err)
|
||||
}
|
||||
contentType := http.DetectContentType(buf.Bytes())
|
||||
|
||||
req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
req.Header.Set("x-goog-api-version", "2")
|
||||
if *publicObject {
|
||||
req.Header.Set("x-goog-acl", "public-read")
|
||||
}
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
res.Write(os.Stderr)
|
||||
log.Fatalf("Failed.")
|
||||
}
|
||||
log.Printf("Success.")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
type tokenCacheFile string
|
||||
|
||||
func (f tokenCacheFile) Token() (*oauth2.Token, error) {
|
||||
slurp, err := ioutil.ReadFile(string(f))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t := new(oauth2.Token)
|
||||
if err := json.Unmarshal(slurp, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
|
||||
jt, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(string(f), jt, 0600)
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSSR8Od0+9Q
|
||||
62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoTZjkUygby
|
||||
XDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYkJfODVGnV
|
||||
mr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3mOoLb4yJ
|
||||
JQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYWcaiW8LWZ
|
||||
SUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABAoIBAFFHV7JMAqPWnMYA
|
||||
nezY6J81v9+XN+7xABNWM2Q8uv4WdksbigGLTXR3/680Z2hXqJ7LMeC5XJACFT/e
|
||||
/Gr0vmpgOCygnCPfjGehGKpavtfksXV3edikUlnCXsOP1C//c1bFL+sMYmFCVgTx
|
||||
qYdDK8yKzXNGrKYT6q5YG7IglyRNV1rsQa8lM/5taFYiD1Ck/3tQi3YIq8Lcuser
|
||||
hrxsMABcQ6mi+EIvG6Xr4mfJug0dGJMHG4RG1UGFQn6RXrQq2+q53fC8ZbVUSi0j
|
||||
NQ918aKFzktwv+DouKU0ME4I9toks03gM860bAL7zCbKGmwR3hfgX/TqzVCWpG9E
|
||||
LDVfvekCgYEA8fk9N53jbBRmULUGEf4qWypcLGiZnNU0OeXWpbPV9aa3H0VDytA7
|
||||
8fCN2dPAVDPqlthMDdVe983NCNwp2Yo8ZimDgowyIAKhdC25s1kejuaiH9OAPj3c
|
||||
0f8KbriYX4n8zNHxFwK6Ae3pQ6EqOLJVCUsziUaZX9nyKY5aZlyX6xcCgYEAwjws
|
||||
K62PjC64U5wYddNLp+kNdJ4edx+a7qBb3mEgPvSFT2RO3/xafJyG8kQB30Mfstjd
|
||||
bRxyUV6N0vtX1zA7VQtRUAvfGCecpMo+VQZzcHXKzoRTnQ7eZg4Lmj5fQ9tOAKAo
|
||||
QCVBoSW/DI4PZL26CAMDcAba4Pa22ooLapoRIQsCgYA6pIfkkbxLNkpxpt2YwLtt
|
||||
Kr/590O7UaR9n6k8sW/aQBRDXNsILR1KDl2ifAIxpf9lnXgZJiwE7HiTfCAcW7c1
|
||||
nzwDCI0hWuHcMTS/NYsFYPnLsstyyjVZI3FY0h4DkYKV9Q9z3zJLQ2hz/nwoD3gy
|
||||
b2pHC7giFcTts1VPV4Nt8wKBgHeFn4ihHJweg76vZz3Z78w7VNRWGFklUalVdDK7
|
||||
gaQ7w2y/ROn/146mo0OhJaXFIFRlrpvdzVrU3GDf2YXJYDlM5ZRkObwbZADjksev
|
||||
WInzcgDy3KDg7WnPasRXbTfMU4t/AkW2p1QKbi3DnSVYuokDkbH2Beo45vxDxhKr
|
||||
C69RAoGBAIyo3+OJenoZmoNzNJl2WPW5MeBUzSh8T/bgyjFTdqFHF5WiYRD/lfHj
|
||||
x9Glyw2nutuT4hlOqHvKhgTYdDMsF2oQ72fe3v8Q5FU7FuKndNPEAyvKNXZaShVA
|
||||
hnlhv5DjXKb0wFWnt5PCCiQLtzG0yyHaITrrEme7FikkIcTxaX/Y
|
||||
-----END RSA PRIVATE KEY-----
|
@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWjCCA0KgAwIBAgIJALfRlWsI8YQHMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEUMBIG
|
||||
A1UEChMLQnJhZGZpdHppbmMxEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3
|
||||
DQEJARYOYnJhZEBkYW5nYS5jb20wHhcNMTQwNzE1MjA0NjA1WhcNMTcwNTA0MjA0
|
||||
NjA1WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBG
|
||||
cmFuY2lzY28xFDASBgNVBAoTC0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhv
|
||||
c3QxHTAbBgkqhkiG9w0BCQEWDmJyYWRAZGFuZ2EuY29tMIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSS
|
||||
R8Od0+9Q62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoT
|
||||
ZjkUygbyXDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYk
|
||||
JfODVGnVmr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3
|
||||
mOoLb4yJJQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYW
|
||||
caiW8LWZSUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABo4HgMIHdMB0G
|
||||
A1UdDgQWBBRcAROthS4P4U7vTfjByC569R7E6DCBrQYDVR0jBIGlMIGigBRcAROt
|
||||
hS4P4U7vTfjByC569R7E6KF/pH0wezELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB
|
||||
MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKEwtCcmFkZml0emluYzES
|
||||
MBAGA1UEAxMJbG9jYWxob3N0MR0wGwYJKoZIhvcNAQkBFg5icmFkQGRhbmdhLmNv
|
||||
bYIJALfRlWsI8YQHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG6h
|
||||
U9f9sNH0/6oBbGGy2EVU0UgITUQIrFWo9rFkrW5k/XkDjQm+3lzjT0iGR4IxE/Ao
|
||||
eU6sQhua7wrWeFEn47GL98lnCsJdD7oZNhFmQ95Tb/LnDUjs5Yj9brP0NWzXfYU4
|
||||
UK2ZnINJRcJpB8iRCaCxE8DdcUF0XqIEq6pA272snoLmiXLMvNl3kYEdm+je6voD
|
||||
58SNVEUsztzQyXmJEhCpwVI0A6QCjzXj+qvpmw3ZZHi8JwXei8ZZBLTSFBki8Z7n
|
||||
sH9BBH38/SzUmAN4QHSPy1gjqm00OAE8NaYDkh/bzE4d7mLGGMWp/WE3KPSu82HF
|
||||
kPe6XoSbiLm/kxk32T0=
|
||||
-----END CERTIFICATE-----
|
@ -1 +0,0 @@
|
||||
E2CE26BF3285059C
|
@ -1,20 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPjCCAiYCCQDizia/MoUFnDANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoT
|
||||
C0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhvc3QxHTAbBgkqhkiG9w0BCQEW
|
||||
DmJyYWRAZGFuZ2EuY29tMB4XDTE0MDcxNTIwNTAyN1oXDTE1MTEyNzIwNTAyN1ow
|
||||
RzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJTRjEeMBwGA1UE
|
||||
ChMVYnJhZGZpdHogaHR0cDIgc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDifx2l
|
||||
gZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1LmJ4c2
|
||||
dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nefb3HL
|
||||
A7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55mjws
|
||||
/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/fz88
|
||||
F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQC0zL+n/YpRZOdulSu9tS8FxrstXqGWoxfe+vIUgqfMZ5+0MkjJ/vW0FqlLDl2R
|
||||
rn4XaR3e7FmWkwdDVbq/UB6lPmoAaFkCgh9/5oapMaclNVNnfF3fjCJfRr+qj/iD
|
||||
EmJStTIN0ZuUjAlpiACmfnpEU55PafT5Zx+i1yE4FGjw8bJpFoyD4Hnm54nGjX19
|
||||
KeCuvcYFUPnBm3lcL0FalF2AjqV02WTHYNQk7YF/oeO7NKBoEgvGvKG3x+xaOeBI
|
||||
dwvdq175ZsGul30h+QjrRlXhH/twcuaT3GSdoysDl9cCYE8f1Mk8PD6gan3uBCJU
|
||||
90p6/CbU71bGbfpM2PHot2fm
|
||||
-----END CERTIFICATE-----
|
@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDi
|
||||
fx2lgZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1Lm
|
||||
J4c2dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nef
|
||||
b3HLA7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55
|
||||
mjws/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/
|
||||
fz88F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABAoIBADQ2spUwbY+bcz4p
|
||||
3M66ECrNQTBggP40gYl2XyHxGGOu2xhZ94f9ELf1hjRWU2DUKWco1rJcdZClV6q3
|
||||
qwmXvcM2Q/SMS8JW0ImkNVl/0/NqPxGatEnj8zY30d/L8hGFb0orzFu/XYA5gCP4
|
||||
NbN2WrXgk3ZLeqwcNxHHtSiJWGJ/fPyeDWAu/apy75u9Xf2GlzBZmV6HYD9EfK80
|
||||
LTlI60f5FO487CrJnboL7ovPJrIHn+k05xRQqwma4orpz932rTXnTjs9Lg6KtbQN
|
||||
a7PrqfAntIISgr11a66Mng3IYH1lYqJsWJJwX/xHT4WLEy0EH4/0+PfYemJekz2+
|
||||
Co62drECgYEA6O9zVJZXrLSDsIi54cfxA7nEZWm5CAtkYWeAHa4EJ+IlZ7gIf9sL
|
||||
W8oFcEfFGpvwVqWZ+AsQ70dsjXAv3zXaG0tmg9FtqWp7pzRSMPidifZcQwWkKeTO
|
||||
gJnFmnVyed8h6GfjTEu4gxo1/S5U0V+mYSha01z5NTnN6ltKx1Or3b0CgYEAxRgm
|
||||
S30nZxnyg/V7ys61AZhst1DG2tkZXEMcA7dYhabMoXPJAP/EfhlWwpWYYUs/u0gS
|
||||
Wwmf5IivX5TlYScgmkvb/NYz0u4ZmOXkLTnLPtdKKFXhjXJcHjUP67jYmOxNlJLp
|
||||
V4vLRnFxTpffAV+OszzRxsXX6fvruwZBANYJeXUCgYBVouLFsFgfWGYp2rpr9XP4
|
||||
KK25kvrBqF6JKOIDB1zjxNJ3pUMKrl8oqccCFoCyXa4oTM2kUX0yWxHfleUjrMq4
|
||||
yimwQKiOZmV7fVLSSjSw6e/VfBd0h3gb82ygcplZkN0IclkwTY5SNKqwn/3y07V5
|
||||
drqdhkrgdJXtmQ6O5YYECQKBgATERcDToQ1USlI4sKrB/wyv1AlG8dg/IebiVJ4e
|
||||
ZAyvcQmClFzq0qS+FiQUnB/WQw9TeeYrwGs1hxBHuJh16srwhLyDrbMvQP06qh8R
|
||||
48F8UXXSRec22dV9MQphaROhu2qZdv1AC0WD3tqov6L33aqmEOi+xi8JgbT/PLk5
|
||||
c/c1AoGBAI1A/02ryksW6/wc7/6SP2M2rTy4m1sD/GnrTc67EHnRcVBdKO6qH2RY
|
||||
nqC8YcveC2ZghgPTDsA3VGuzuBXpwY6wTyV99q6jxQJ6/xcrD9/NUG6Uwv/xfCxl
|
||||
IJLeBYEqQundSSny3VtaAUK8Ul1nxpTvVRNwtcyWTo8RHAAyNPWd
|
||||
-----END RSA PRIVATE KEY-----
|
@ -1,97 +0,0 @@
|
||||
# h2i
|
||||
|
||||
**h2i** is an interactive HTTP/2 ("h2") console debugger. Miss the good ol'
|
||||
days of telnetting to your HTTP/1.n servers? We're bringing you
|
||||
back.
|
||||
|
||||
Features:
|
||||
- send raw HTTP/2 frames
|
||||
- PING
|
||||
- SETTINGS
|
||||
- HEADERS
|
||||
- etc
|
||||
- type in HTTP/1.n and have it auto-HPACK/frame-ify it for HTTP/2
|
||||
- pretty print all received HTTP/2 frames from the peer (including HPACK decoding)
|
||||
- tab completion of commands, options
|
||||
|
||||
Not yet features, but soon:
|
||||
- unnecessary CONTINUATION frames on short boundaries, to test peer implementations
|
||||
- request bodies (DATA frames)
|
||||
- send invalid frames for testing server implementations (supported by underlying Framer)
|
||||
|
||||
Later:
|
||||
- act like a server
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get golang.org/x/net/http2/h2i
|
||||
$ h2i <host>
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
```
|
||||
$ h2i
|
||||
Usage: h2i <hostname>
|
||||
|
||||
-insecure
|
||||
Whether to skip TLS cert validation
|
||||
-nextproto string
|
||||
Comma-separated list of NPN/ALPN protocol names to negotiate. (default "h2,h2-14")
|
||||
|
||||
$ h2i google.com
|
||||
Connecting to google.com:443 ...
|
||||
Connected to 74.125.224.41:443
|
||||
Negotiated protocol "h2-14"
|
||||
[FrameHeader SETTINGS len=18]
|
||||
[MAX_CONCURRENT_STREAMS = 100]
|
||||
[INITIAL_WINDOW_SIZE = 1048576]
|
||||
[MAX_FRAME_SIZE = 16384]
|
||||
[FrameHeader WINDOW_UPDATE len=4]
|
||||
Window-Increment = 983041
|
||||
|
||||
h2i> PING h2iSayHI
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2iSayHI"
|
||||
h2i> headers
|
||||
(as HTTP/1.1)> GET / HTTP/1.1
|
||||
(as HTTP/1.1)> Host: ip.appspot.com
|
||||
(as HTTP/1.1)> User-Agent: h2i/brad-n-blake
|
||||
(as HTTP/1.1)>
|
||||
Opening Stream-ID 1:
|
||||
:authority = ip.appspot.com
|
||||
:method = GET
|
||||
:path = /
|
||||
:scheme = https
|
||||
user-agent = h2i/brad-n-blake
|
||||
[FrameHeader HEADERS flags=END_HEADERS stream=1 len=77]
|
||||
:status = "200"
|
||||
alternate-protocol = "443:quic,p=1"
|
||||
content-length = "15"
|
||||
content-type = "text/html"
|
||||
date = "Fri, 01 May 2015 23:06:56 GMT"
|
||||
server = "Google Frontend"
|
||||
[FrameHeader DATA flags=END_STREAM stream=1 len=15]
|
||||
"173.164.155.78\n"
|
||||
[FrameHeader PING len=8]
|
||||
Data = "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
h2i> ping
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2i_ping"
|
||||
h2i> ping
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2i_ping"
|
||||
h2i> ping
|
||||
[FrameHeader GOAWAY len=22]
|
||||
Last-Stream-ID = 1; Error-Code = PROTOCOL_ERROR (1)
|
||||
|
||||
ReadFrame: EOF
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
Quick few hour hack. So much yet to do. Feel free to file issues for
|
||||
bugs or wishlist items, but [@bmizerany](https://github.com/bmizerany/)
|
||||
and I aren't yet accepting pull requests until things settle down.
|
||||
|
@ -1,501 +0,0 @@
|
||||
// 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,!solaris
|
||||
|
||||
/*
|
||||
The h2i command is an interactive HTTP/2 console.
|
||||
|
||||
Usage:
|
||||
$ h2i [flags] <hostname>
|
||||
|
||||
Interactive commands in the console: (all parts case-insensitive)
|
||||
|
||||
ping [data]
|
||||
settings ack
|
||||
settings FOO=n BAR=z
|
||||
headers (open a new stream by typing HTTP/1.1)
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
// Flags
|
||||
var (
|
||||
flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
|
||||
flagInsecure = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
|
||||
flagSettings = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
|
||||
)
|
||||
|
||||
type command struct {
|
||||
run func(*h2i, []string) error // required
|
||||
|
||||
// complete optionally specifies tokens (case-insensitive) which are
|
||||
// valid for this subcommand.
|
||||
complete func() []string
|
||||
}
|
||||
|
||||
var commands = map[string]command{
|
||||
"ping": command{run: (*h2i).cmdPing},
|
||||
"settings": command{
|
||||
run: (*h2i).cmdSettings,
|
||||
complete: func() []string {
|
||||
return []string{
|
||||
"ACK",
|
||||
http2.SettingHeaderTableSize.String(),
|
||||
http2.SettingEnablePush.String(),
|
||||
http2.SettingMaxConcurrentStreams.String(),
|
||||
http2.SettingInitialWindowSize.String(),
|
||||
http2.SettingMaxFrameSize.String(),
|
||||
http2.SettingMaxHeaderListSize.String(),
|
||||
}
|
||||
},
|
||||
},
|
||||
"quit": command{run: (*h2i).cmdQuit},
|
||||
"headers": command{run: (*h2i).cmdHeaders},
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: h2i <hostname>\n\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
// withPort adds ":443" if another port isn't already present.
|
||||
func withPort(host string) string {
|
||||
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||
return net.JoinHostPort(host, "443")
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
// h2i is the app's state.
|
||||
type h2i struct {
|
||||
host string
|
||||
tc *tls.Conn
|
||||
framer *http2.Framer
|
||||
term *terminal.Terminal
|
||||
|
||||
// owned by the command loop:
|
||||
streamID uint32
|
||||
hbuf bytes.Buffer
|
||||
henc *hpack.Encoder
|
||||
|
||||
// owned by the readFrames loop:
|
||||
peerSetting map[http2.SettingID]uint32
|
||||
hdec *hpack.Decoder
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
log.SetFlags(0)
|
||||
|
||||
host := flag.Arg(0)
|
||||
app := &h2i{
|
||||
host: host,
|
||||
peerSetting: make(map[http2.SettingID]uint32),
|
||||
}
|
||||
app.henc = hpack.NewEncoder(&app.hbuf)
|
||||
|
||||
if err := app.Main(); err != nil {
|
||||
if app.term != nil {
|
||||
app.logf("%v\n", err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
}
|
||||
|
||||
func (app *h2i) Main() error {
|
||||
cfg := &tls.Config{
|
||||
ServerName: app.host,
|
||||
NextProtos: strings.Split(*flagNextProto, ","),
|
||||
InsecureSkipVerify: *flagInsecure,
|
||||
}
|
||||
|
||||
hostAndPort := withPort(app.host)
|
||||
log.Printf("Connecting to %s ...", hostAndPort)
|
||||
tc, err := tls.Dial("tcp", hostAndPort, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error dialing %s: %v", withPort(app.host), err)
|
||||
}
|
||||
log.Printf("Connected to %v", tc.RemoteAddr())
|
||||
defer tc.Close()
|
||||
|
||||
if err := tc.Handshake(); err != nil {
|
||||
return fmt.Errorf("TLS handshake: %v", err)
|
||||
}
|
||||
if !*flagInsecure {
|
||||
if err := tc.VerifyHostname(app.host); err != nil {
|
||||
return fmt.Errorf("VerifyHostname: %v", err)
|
||||
}
|
||||
}
|
||||
state := tc.ConnectionState()
|
||||
log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
|
||||
if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
|
||||
return fmt.Errorf("Could not negotiate protocol mutually")
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.framer = http2.NewFramer(tc, tc)
|
||||
|
||||
oldState, err := terminal.MakeRaw(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer terminal.Restore(0, oldState)
|
||||
|
||||
var screen = struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
}{os.Stdin, os.Stdout}
|
||||
|
||||
app.term = terminal.NewTerminal(screen, "h2i> ")
|
||||
lastWord := regexp.MustCompile(`.+\W(\w+)$`)
|
||||
app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
|
||||
if key != '\t' {
|
||||
return
|
||||
}
|
||||
if pos != len(line) {
|
||||
// TODO: we're being lazy for now, only supporting tab completion at the end.
|
||||
return
|
||||
}
|
||||
// Auto-complete for the command itself.
|
||||
if !strings.Contains(line, " ") {
|
||||
var name string
|
||||
name, _, ok = lookupCommand(line)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
return name, len(name), true
|
||||
}
|
||||
_, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
|
||||
if !ok || c.complete == nil {
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(line, " ") {
|
||||
app.logf("%s", strings.Join(c.complete(), " "))
|
||||
return line, pos, true
|
||||
}
|
||||
m := lastWord.FindStringSubmatch(line)
|
||||
if m == nil {
|
||||
return line, len(line), true
|
||||
}
|
||||
soFar := m[1]
|
||||
var match []string
|
||||
for _, cand := range c.complete() {
|
||||
if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
|
||||
continue
|
||||
}
|
||||
match = append(match, cand)
|
||||
}
|
||||
if len(match) == 0 {
|
||||
return
|
||||
}
|
||||
if len(match) > 1 {
|
||||
// TODO: auto-complete any common prefix
|
||||
app.logf("%s", strings.Join(match, " "))
|
||||
return line, pos, true
|
||||
}
|
||||
newLine = line[:len(line)-len(soFar)] + match[0]
|
||||
return newLine, len(newLine), true
|
||||
|
||||
}
|
||||
|
||||
errc := make(chan error, 2)
|
||||
go func() { errc <- app.readFrames() }()
|
||||
go func() { errc <- app.readConsole() }()
|
||||
return <-errc
|
||||
}
|
||||
|
||||
func (app *h2i) logf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(app.term, format+"\n", args...)
|
||||
}
|
||||
|
||||
func (app *h2i) readConsole() error {
|
||||
if s := *flagSettings; s != "omit" {
|
||||
var args []string
|
||||
if s != "empty" {
|
||||
args = strings.Split(s, ",")
|
||||
}
|
||||
_, c, ok := lookupCommand("settings")
|
||||
if !ok {
|
||||
panic("settings command not found")
|
||||
}
|
||||
c.run(app, args)
|
||||
}
|
||||
|
||||
for {
|
||||
line, err := app.term.ReadLine()
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("terminal.ReadLine: %v", err)
|
||||
}
|
||||
f := strings.Fields(line)
|
||||
if len(f) == 0 {
|
||||
continue
|
||||
}
|
||||
cmd, args := f[0], f[1:]
|
||||
if _, c, ok := lookupCommand(cmd); ok {
|
||||
err = c.run(app, args)
|
||||
} else {
|
||||
app.logf("Unknown command %q", line)
|
||||
}
|
||||
if err == errExitApp {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lookupCommand(prefix string) (name string, c command, ok bool) {
|
||||
prefix = strings.ToLower(prefix)
|
||||
if c, ok = commands[prefix]; ok {
|
||||
return prefix, c, ok
|
||||
}
|
||||
|
||||
for full, candidate := range commands {
|
||||
if strings.HasPrefix(full, prefix) {
|
||||
if c.run != nil {
|
||||
return "", command{}, false // ambiguous
|
||||
}
|
||||
c = candidate
|
||||
name = full
|
||||
}
|
||||
}
|
||||
return name, c, c.run != nil
|
||||
}
|
||||
|
||||
var errExitApp = errors.New("internal sentinel error value to quit the console reading loop")
|
||||
|
||||
func (a *h2i) cmdQuit(args []string) error {
|
||||
if len(args) > 0 {
|
||||
a.logf("the QUIT command takes no argument")
|
||||
return nil
|
||||
}
|
||||
return errExitApp
|
||||
}
|
||||
|
||||
func (a *h2i) cmdSettings(args []string) error {
|
||||
if len(args) == 1 && strings.EqualFold(args[0], "ACK") {
|
||||
return a.framer.WriteSettingsAck()
|
||||
}
|
||||
var settings []http2.Setting
|
||||
for _, arg := range args {
|
||||
if strings.EqualFold(arg, "ACK") {
|
||||
a.logf("Error: ACK must be only argument with the SETTINGS command")
|
||||
return nil
|
||||
}
|
||||
eq := strings.Index(arg, "=")
|
||||
if eq == -1 {
|
||||
a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
|
||||
return nil
|
||||
}
|
||||
sid, ok := settingByName(arg[:eq])
|
||||
if !ok {
|
||||
a.logf("Error: unknown setting name %q", arg[:eq])
|
||||
return nil
|
||||
}
|
||||
val, err := strconv.ParseUint(arg[eq+1:], 10, 32)
|
||||
if err != nil {
|
||||
a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
|
||||
return nil
|
||||
}
|
||||
settings = append(settings, http2.Setting{
|
||||
ID: sid,
|
||||
Val: uint32(val),
|
||||
})
|
||||
}
|
||||
a.logf("Sending: %v", settings)
|
||||
return a.framer.WriteSettings(settings...)
|
||||
}
|
||||
|
||||
func settingByName(name string) (http2.SettingID, bool) {
|
||||
for _, sid := range [...]http2.SettingID{
|
||||
http2.SettingHeaderTableSize,
|
||||
http2.SettingEnablePush,
|
||||
http2.SettingMaxConcurrentStreams,
|
||||
http2.SettingInitialWindowSize,
|
||||
http2.SettingMaxFrameSize,
|
||||
http2.SettingMaxHeaderListSize,
|
||||
} {
|
||||
if strings.EqualFold(sid.String(), name) {
|
||||
return sid, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (app *h2i) cmdPing(args []string) error {
|
||||
if len(args) > 1 {
|
||||
app.logf("invalid PING usage: only accepts 0 or 1 args")
|
||||
return nil // nil means don't end the program
|
||||
}
|
||||
var data [8]byte
|
||||
if len(args) == 1 {
|
||||
copy(data[:], args[0])
|
||||
} else {
|
||||
copy(data[:], "h2i_ping")
|
||||
}
|
||||
return app.framer.WritePing(false, data)
|
||||
}
|
||||
|
||||
func (app *h2i) cmdHeaders(args []string) error {
|
||||
if len(args) > 0 {
|
||||
app.logf("Error: HEADERS doesn't yet take arguments.")
|
||||
// TODO: flags for restricting window size, to force CONTINUATION
|
||||
// frames.
|
||||
return nil
|
||||
}
|
||||
var h1req bytes.Buffer
|
||||
app.term.SetPrompt("(as HTTP/1.1)> ")
|
||||
defer app.term.SetPrompt("h2i> ")
|
||||
for {
|
||||
line, err := app.term.ReadLine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h1req.WriteString(line)
|
||||
h1req.WriteString("\r\n")
|
||||
if line == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
req, err := http.ReadRequest(bufio.NewReader(&h1req))
|
||||
if err != nil {
|
||||
app.logf("Invalid HTTP/1.1 request: %v", err)
|
||||
return nil
|
||||
}
|
||||
if app.streamID == 0 {
|
||||
app.streamID = 1
|
||||
} else {
|
||||
app.streamID += 2
|
||||
}
|
||||
app.logf("Opening Stream-ID %d:", app.streamID)
|
||||
hbf := app.encodeHeaders(req)
|
||||
if len(hbf) > 16<<10 {
|
||||
app.logf("TODO: h2i doesn't yet write CONTINUATION frames. Copy it from transport.go")
|
||||
return nil
|
||||
}
|
||||
return app.framer.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: app.streamID,
|
||||
BlockFragment: hbf,
|
||||
EndStream: req.Method == "GET" || req.Method == "HEAD", // good enough for now
|
||||
EndHeaders: true, // for now
|
||||
})
|
||||
}
|
||||
|
||||
func (app *h2i) readFrames() error {
|
||||
for {
|
||||
f, err := app.framer.ReadFrame()
|
||||
if err != nil {
|
||||
return fmt.Errorf("ReadFrame: %v", err)
|
||||
}
|
||||
app.logf("%v", f)
|
||||
switch f := f.(type) {
|
||||
case *http2.PingFrame:
|
||||
app.logf(" Data = %q", f.Data)
|
||||
case *http2.SettingsFrame:
|
||||
f.ForeachSetting(func(s http2.Setting) error {
|
||||
app.logf(" %v", s)
|
||||
app.peerSetting[s.ID] = s.Val
|
||||
return nil
|
||||
})
|
||||
case *http2.WindowUpdateFrame:
|
||||
app.logf(" Window-Increment = %v\n", f.Increment)
|
||||
case *http2.GoAwayFrame:
|
||||
app.logf(" Last-Stream-ID = %d; Error-Code = %v (%d)\n", f.LastStreamID, f.ErrCode, f.ErrCode)
|
||||
case *http2.DataFrame:
|
||||
app.logf(" %q", f.Data())
|
||||
case *http2.HeadersFrame:
|
||||
if f.HasPriority() {
|
||||
app.logf(" PRIORITY = %v", f.Priority)
|
||||
}
|
||||
if app.hdec == nil {
|
||||
// TODO: if the user uses h2i to send a SETTINGS frame advertising
|
||||
// something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
|
||||
// and stuff here instead of using the 4k default. But for now:
|
||||
tableSize := uint32(4 << 10)
|
||||
app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
|
||||
}
|
||||
app.hdec.Write(f.HeaderBlockFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called from readLoop
|
||||
func (app *h2i) onNewHeaderField(f hpack.HeaderField) {
|
||||
if f.Sensitive {
|
||||
app.logf(" %s = %q (SENSITIVE)", f.Name, f.Value)
|
||||
}
|
||||
app.logf(" %s = %q", f.Name, f.Value)
|
||||
}
|
||||
|
||||
func (app *h2i) encodeHeaders(req *http.Request) []byte {
|
||||
app.hbuf.Reset()
|
||||
|
||||
// TODO(bradfitz): figure out :authority-vs-Host stuff between http2 and Go
|
||||
host := req.Host
|
||||
if host == "" {
|
||||
host = req.URL.Host
|
||||
}
|
||||
|
||||
path := req.URL.Path
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
|
||||
app.writeHeader(":authority", host) // probably not right for all sites
|
||||
app.writeHeader(":method", req.Method)
|
||||
app.writeHeader(":path", path)
|
||||
app.writeHeader(":scheme", "https")
|
||||
|
||||
for k, vv := range req.Header {
|
||||
lowKey := strings.ToLower(k)
|
||||
if lowKey == "host" {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
app.writeHeader(lowKey, v)
|
||||
}
|
||||
}
|
||||
return app.hbuf.Bytes()
|
||||
}
|
||||
|
||||
func (app *h2i) writeHeader(name, value string) {
|
||||
app.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
|
||||
app.logf(" %s = %s", name, value)
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// 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.5
|
||||
|
||||
package http2
|
||||
|
||||
import "net/http"
|
||||
|
||||
func requestCancel(req *http.Request) <-chan struct{} { return nil }
|
41
Godeps/_workspace/src/google.golang.org/grpc/Documentation/grpc-auth-support.md
generated
vendored
41
Godeps/_workspace/src/google.golang.org/grpc/Documentation/grpc-auth-support.md
generated
vendored
@ -1,41 +0,0 @@
|
||||
# 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)))
|
||||
```
|
||||
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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 (
|
||||
"io"
|
||||
"math"
|
||||
"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.TestService_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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StartServer starts a gRPC server serving a benchmark service on the given
|
||||
// address, which may be something like "localhost:0". It returns its listen
|
||||
// address and a function to stop the server.
|
||||
func StartServer(addr string) (string, func()) {
|
||||
lis, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
grpclog.Fatalf("Failed to listen: %v", err)
|
||||
}
|
||||
s := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint32))
|
||||
testpb.RegisterTestServiceServer(s, &testServer{})
|
||||
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.TestServiceClient, reqSize, respSize int) {
|
||||
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 {
|
||||
grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
// DoStreamingRoundTrip performs a round trip for a single streaming rpc.
|
||||
func DoStreamingRoundTrip(tc testpb.TestServiceClient, stream testpb.TestService_StreamingCallClient, reqSize, respSize int) {
|
||||
pl := newPayload(testpb.PayloadType_COMPRESSABLE, reqSize)
|
||||
req := &testpb.SimpleRequest{
|
||||
ResponseType: pl.Type,
|
||||
ResponseSize: int32(respSize),
|
||||
Payload: pl,
|
||||
}
|
||||
if err := stream.Send(req); err != nil {
|
||||
grpclog.Fatalf("StreamingCall(_).Send: %v", err)
|
||||
}
|
||||
if _, err := stream.Recv(); err != nil {
|
||||
grpclog.Fatalf("StreamingCall(_).Recv: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// NewClientConn creates a gRPC client connection to addr.
|
||||
func NewClientConn(addr string) *grpc.ClientConn {
|
||||
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
grpclog.Fatalf("NewClientConn(%q) failed to create a ClientConn %v", addr, err)
|
||||
}
|
||||
return conn
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
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.TestServiceClient) {
|
||||
benchmark.DoUnaryCall(client, 1, 1)
|
||||
}
|
||||
|
||||
func streamCaller(client testpb.TestServiceClient, stream testpb.TestService_StreamingCallClient) {
|
||||
benchmark.DoStreamingRoundTrip(client, stream, 1, 1)
|
||||
}
|
||||
|
||||
func buildConnection() (s *stats.Stats, conn *grpc.ClientConn, tc testpb.TestServiceClient) {
|
||||
s = stats.NewStats(256)
|
||||
conn = benchmark.NewClientConn(*server)
|
||||
tc = testpb.NewTestServiceClient(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(tc, stream)
|
||||
}
|
||||
for range ch {
|
||||
start := time.Now()
|
||||
streamCaller(tc, 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()
|
||||
}
|
||||
}
|
941
Godeps/_workspace/src/google.golang.org/grpc/benchmark/grpc_testing/test.pb.go
generated
vendored
941
Godeps/_workspace/src/google.golang.org/grpc/benchmark/grpc_testing/test.pb.go
generated
vendored
@ -1,941 +0,0 @@
|
||||
// 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:
|
||||
StatsRequest
|
||||
ServerStats
|
||||
Payload
|
||||
HistogramData
|
||||
ClientConfig
|
||||
Mark
|
||||
ClientArgs
|
||||
ClientStats
|
||||
ClientStatus
|
||||
ServerConfig
|
||||
ServerArgs
|
||||
ServerStatus
|
||||
SimpleRequest
|
||||
SimpleResponse
|
||||
*/
|
||||
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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
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 fileDescriptor0, []int{0} }
|
||||
|
||||
type ClientType int32
|
||||
|
||||
const (
|
||||
ClientType_SYNCHRONOUS_CLIENT ClientType = 0
|
||||
ClientType_ASYNC_CLIENT ClientType = 1
|
||||
)
|
||||
|
||||
var ClientType_name = map[int32]string{
|
||||
0: "SYNCHRONOUS_CLIENT",
|
||||
1: "ASYNC_CLIENT",
|
||||
}
|
||||
var ClientType_value = map[string]int32{
|
||||
"SYNCHRONOUS_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{1} }
|
||||
|
||||
type ServerType int32
|
||||
|
||||
const (
|
||||
ServerType_SYNCHRONOUS_SERVER ServerType = 0
|
||||
ServerType_ASYNC_SERVER ServerType = 1
|
||||
)
|
||||
|
||||
var ServerType_name = map[int32]string{
|
||||
0: "SYNCHRONOUS_SERVER",
|
||||
1: "ASYNC_SERVER",
|
||||
}
|
||||
var ServerType_value = map[string]int32{
|
||||
"SYNCHRONOUS_SERVER": 0,
|
||||
"ASYNC_SERVER": 1,
|
||||
}
|
||||
|
||||
func (x ServerType) String() string {
|
||||
return proto.EnumName(ServerType_name, int32(x))
|
||||
}
|
||||
func (ServerType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
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{3} }
|
||||
|
||||
type StatsRequest struct {
|
||||
// run number
|
||||
TestNum int32 `protobuf:"varint,1,opt,name=test_num" json:"test_num,omitempty"`
|
||||
}
|
||||
|
||||
func (m *StatsRequest) Reset() { *m = StatsRequest{} }
|
||||
func (m *StatsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*StatsRequest) ProtoMessage() {}
|
||||
func (*StatsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type ServerStats struct {
|
||||
// wall clock time
|
||||
TimeElapsed float64 `protobuf:"fixed64,1,opt,name=time_elapsed" json:"time_elapsed,omitempty"`
|
||||
// user time used by the server process and threads
|
||||
TimeUser float64 `protobuf:"fixed64,2,opt,name=time_user" json:"time_user,omitempty"`
|
||||
// server time used by the server process and all threads
|
||||
TimeSystem float64 `protobuf:"fixed64,3,opt,name=time_system" 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 fileDescriptor0, []int{1} }
|
||||
|
||||
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 fileDescriptor0, []int{2} }
|
||||
|
||||
type HistogramData struct {
|
||||
Bucket []uint32 `protobuf:"varint,1,rep,name=bucket" json:"bucket,omitempty"`
|
||||
MinSeen float64 `protobuf:"fixed64,2,opt,name=min_seen" json:"min_seen,omitempty"`
|
||||
MaxSeen float64 `protobuf:"fixed64,3,opt,name=max_seen" 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:"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 fileDescriptor0, []int{3} }
|
||||
|
||||
type ClientConfig struct {
|
||||
ServerTargets []string `protobuf:"bytes,1,rep,name=server_targets" json:"server_targets,omitempty"`
|
||||
ClientType ClientType `protobuf:"varint,2,opt,name=client_type,enum=grpc.testing.ClientType" json:"client_type,omitempty"`
|
||||
EnableSsl bool `protobuf:"varint,3,opt,name=enable_ssl" json:"enable_ssl,omitempty"`
|
||||
OutstandingRpcsPerChannel int32 `protobuf:"varint,4,opt,name=outstanding_rpcs_per_channel" json:"outstanding_rpcs_per_channel,omitempty"`
|
||||
ClientChannels int32 `protobuf:"varint,5,opt,name=client_channels" json:"client_channels,omitempty"`
|
||||
PayloadSize int32 `protobuf:"varint,6,opt,name=payload_size" json:"payload_size,omitempty"`
|
||||
// only for async client:
|
||||
AsyncClientThreads int32 `protobuf:"varint,7,opt,name=async_client_threads" json:"async_client_threads,omitempty"`
|
||||
RpcType RpcType `protobuf:"varint,8,opt,name=rpc_type,enum=grpc.testing.RpcType" json:"rpc_type,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{4} }
|
||||
|
||||
// Request current stats
|
||||
type Mark struct {
|
||||
}
|
||||
|
||||
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{5} }
|
||||
|
||||
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{6} }
|
||||
|
||||
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 ClientStats struct {
|
||||
Latencies *HistogramData `protobuf:"bytes,1,opt,name=latencies" json:"latencies,omitempty"`
|
||||
TimeElapsed float64 `protobuf:"fixed64,3,opt,name=time_elapsed" json:"time_elapsed,omitempty"`
|
||||
TimeUser float64 `protobuf:"fixed64,4,opt,name=time_user" json:"time_user,omitempty"`
|
||||
TimeSystem float64 `protobuf:"fixed64,5,opt,name=time_system" 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 fileDescriptor0, []int{7} }
|
||||
|
||||
func (m *ClientStats) GetLatencies() *HistogramData {
|
||||
if m != nil {
|
||||
return m.Latencies
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
ServerType ServerType `protobuf:"varint,1,opt,name=server_type,enum=grpc.testing.ServerType" json:"server_type,omitempty"`
|
||||
Threads int32 `protobuf:"varint,2,opt,name=threads" json:"threads,omitempty"`
|
||||
EnableSsl bool `protobuf:"varint,3,opt,name=enable_ssl" json:"enable_ssl,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{9} }
|
||||
|
||||
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{10} }
|
||||
|
||||
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"`
|
||||
Port int32 `protobuf:"varint,2,opt,name=port" json:"port,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{11} }
|
||||
|
||||
func (m *ServerStatus) GetStats() *ServerStats {
|
||||
if m != nil {
|
||||
return m.Stats
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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,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:"response_size,omitempty"`
|
||||
// Optional input payload sent along with the request.
|
||||
Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,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 fileDescriptor0, []int{12} }
|
||||
|
||||
func (m *SimpleRequest) GetPayload() *Payload {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SimpleResponse struct {
|
||||
Payload *Payload `protobuf:"bytes,1,opt,name=payload" json:"payload,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 fileDescriptor0, []int{13} }
|
||||
|
||||
func (m *SimpleResponse) GetPayload() *Payload {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*StatsRequest)(nil), "grpc.testing.StatsRequest")
|
||||
proto.RegisterType((*ServerStats)(nil), "grpc.testing.ServerStats")
|
||||
proto.RegisterType((*Payload)(nil), "grpc.testing.Payload")
|
||||
proto.RegisterType((*HistogramData)(nil), "grpc.testing.HistogramData")
|
||||
proto.RegisterType((*ClientConfig)(nil), "grpc.testing.ClientConfig")
|
||||
proto.RegisterType((*Mark)(nil), "grpc.testing.Mark")
|
||||
proto.RegisterType((*ClientArgs)(nil), "grpc.testing.ClientArgs")
|
||||
proto.RegisterType((*ClientStats)(nil), "grpc.testing.ClientStats")
|
||||
proto.RegisterType((*ClientStatus)(nil), "grpc.testing.ClientStatus")
|
||||
proto.RegisterType((*ServerConfig)(nil), "grpc.testing.ServerConfig")
|
||||
proto.RegisterType((*ServerArgs)(nil), "grpc.testing.ServerArgs")
|
||||
proto.RegisterType((*ServerStatus)(nil), "grpc.testing.ServerStatus")
|
||||
proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest")
|
||||
proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse")
|
||||
proto.RegisterEnum("grpc.testing.PayloadType", PayloadType_name, PayloadType_value)
|
||||
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)
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// Client API for TestService service
|
||||
|
||||
type TestServiceClient 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) (TestService_StreamingCallClient, error)
|
||||
}
|
||||
|
||||
type testServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient {
|
||||
return &testServiceClient{cc}
|
||||
}
|
||||
|
||||
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) StreamingCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingCallClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[0], c.cc, "/grpc.testing.TestService/StreamingCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceStreamingCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_StreamingCallClient interface {
|
||||
Send(*SimpleRequest) error
|
||||
Recv() (*SimpleResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceStreamingCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingCallClient) Send(m *SimpleRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingCallClient) Recv() (*SimpleResponse, error) {
|
||||
m := new(SimpleResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Server API for TestService service
|
||||
|
||||
type TestServiceServer 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(TestService_StreamingCallServer) error
|
||||
}
|
||||
|
||||
func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
|
||||
s.RegisterService(&_TestService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func _TestService_StreamingCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).StreamingCall(&testServiceStreamingCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_StreamingCallServer interface {
|
||||
Send(*SimpleResponse) error
|
||||
Recv() (*SimpleRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceStreamingCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingCallServer) Send(m *SimpleResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingCallServer) Recv() (*SimpleRequest, error) {
|
||||
m := new(SimpleRequest)
|
||||
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: "UnaryCall",
|
||||
Handler: _TestService_UnaryCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "StreamingCall",
|
||||
Handler: _TestService_StreamingCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Client API for Worker service
|
||||
|
||||
type WorkerClient interface {
|
||||
// Start test with specified workload
|
||||
RunTest(ctx context.Context, opts ...grpc.CallOption) (Worker_RunTestClient, error)
|
||||
// Start test with specified workload
|
||||
RunServer(ctx context.Context, opts ...grpc.CallOption) (Worker_RunServerClient, error)
|
||||
}
|
||||
|
||||
type workerClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewWorkerClient(cc *grpc.ClientConn) WorkerClient {
|
||||
return &workerClient{cc}
|
||||
}
|
||||
|
||||
func (c *workerClient) RunTest(ctx context.Context, opts ...grpc.CallOption) (Worker_RunTestClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_Worker_serviceDesc.Streams[0], c.cc, "/grpc.testing.Worker/RunTest", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &workerRunTestClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Worker_RunTestClient interface {
|
||||
Send(*ClientArgs) error
|
||||
Recv() (*ClientStatus, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type workerRunTestClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *workerRunTestClient) Send(m *ClientArgs) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *workerRunTestClient) Recv() (*ClientStatus, error) {
|
||||
m := new(ClientStatus)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *workerClient) RunServer(ctx context.Context, opts ...grpc.CallOption) (Worker_RunServerClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_Worker_serviceDesc.Streams[1], c.cc, "/grpc.testing.Worker/RunServer", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &workerRunServerClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Worker_RunServerClient interface {
|
||||
Send(*ServerArgs) error
|
||||
Recv() (*ServerStatus, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type workerRunServerClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *workerRunServerClient) Send(m *ServerArgs) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *workerRunServerClient) Recv() (*ServerStatus, error) {
|
||||
m := new(ServerStatus)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Server API for Worker service
|
||||
|
||||
type WorkerServer interface {
|
||||
// Start test with specified workload
|
||||
RunTest(Worker_RunTestServer) error
|
||||
// Start test with specified workload
|
||||
RunServer(Worker_RunServerServer) error
|
||||
}
|
||||
|
||||
func RegisterWorkerServer(s *grpc.Server, srv WorkerServer) {
|
||||
s.RegisterService(&_Worker_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Worker_RunTest_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(WorkerServer).RunTest(&workerRunTestServer{stream})
|
||||
}
|
||||
|
||||
type Worker_RunTestServer interface {
|
||||
Send(*ClientStatus) error
|
||||
Recv() (*ClientArgs, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type workerRunTestServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *workerRunTestServer) Send(m *ClientStatus) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *workerRunTestServer) Recv() (*ClientArgs, error) {
|
||||
m := new(ClientArgs)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _Worker_RunServer_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(WorkerServer).RunServer(&workerRunServerServer{stream})
|
||||
}
|
||||
|
||||
type Worker_RunServerServer interface {
|
||||
Send(*ServerStatus) error
|
||||
Recv() (*ServerArgs, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type workerRunServerServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *workerRunServerServer) Send(m *ServerStatus) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *workerRunServerServer) Recv() (*ServerArgs, error) {
|
||||
m := new(ServerArgs)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _Worker_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.testing.Worker",
|
||||
HandlerType: (*WorkerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "RunTest",
|
||||
Handler: _Worker_RunTest_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "RunServer",
|
||||
Handler: _Worker_RunServer_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 988 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x6f, 0x1b, 0x45,
|
||||
0x10, 0xef, 0xc5, 0xff, 0xe2, 0x39, 0x27, 0x44, 0xab, 0x52, 0x39, 0x69, 0x11, 0x70, 0x05, 0x11,
|
||||
0x22, 0x91, 0x56, 0x46, 0x42, 0xea, 0x0b, 0x91, 0xeb, 0x1a, 0x52, 0x29, 0x71, 0xa2, 0xbd, 0x04,
|
||||
0xd4, 0xa7, 0xd3, 0xc6, 0xde, 0xb8, 0xa7, 0x9c, 0xef, 0xae, 0xb7, 0x7b, 0xa8, 0xe6, 0x09, 0xf1,
|
||||
0x19, 0xf8, 0x0a, 0x3c, 0x20, 0xbe, 0x24, 0xb3, 0xb3, 0x7b, 0x89, 0x9d, 0x9a, 0x36, 0x52, 0x9f,
|
||||
0x72, 0x3b, 0xf3, 0x9b, 0xdf, 0xce, 0xfe, 0xe6, 0x8f, 0x03, 0xa0, 0xa5, 0xd2, 0xfb, 0x79, 0x91,
|
||||
0xe9, 0x8c, 0x75, 0xa6, 0x45, 0x3e, 0xde, 0x37, 0x86, 0x38, 0x9d, 0x06, 0xdf, 0x42, 0x27, 0xd4,
|
||||
0x42, 0x2b, 0x2e, 0xdf, 0x94, 0x68, 0x62, 0xdb, 0xb0, 0x6e, 0x5c, 0x51, 0x5a, 0xce, 0xba, 0xde,
|
||||
0x17, 0xde, 0x6e, 0x83, 0xb7, 0xcc, 0x79, 0x54, 0xce, 0x82, 0x14, 0xfc, 0x50, 0x16, 0xbf, 0xc9,
|
||||
0x82, 0x02, 0xd8, 0x97, 0xd0, 0xd1, 0xf1, 0x4c, 0x46, 0x32, 0x11, 0xb9, 0x92, 0x13, 0x42, 0x7b,
|
||||
0xdc, 0x37, 0xb6, 0xa1, 0x35, 0xb1, 0x87, 0xd0, 0x26, 0x48, 0xa9, 0x64, 0xd1, 0x5d, 0x23, 0xff,
|
||||
0xba, 0x31, 0x9c, 0xe3, 0x99, 0x7d, 0x0e, 0x84, 0x8d, 0xd4, 0x5c, 0x69, 0x39, 0xeb, 0xd6, 0xc8,
|
||||
0x0d, 0xc6, 0x14, 0x92, 0x25, 0x38, 0x82, 0xd6, 0xa9, 0x98, 0x27, 0x99, 0x98, 0xb0, 0xef, 0xa0,
|
||||
0xae, 0xe7, 0xb9, 0xa4, 0x3b, 0x36, 0x7b, 0xdb, 0xfb, 0x8b, 0x4f, 0xd8, 0x77, 0xa0, 0x33, 0x04,
|
||||
0x70, 0x82, 0x31, 0x06, 0xf5, 0x8b, 0x6c, 0x32, 0xa7, 0x2b, 0x3b, 0x9c, 0xbe, 0x83, 0x7f, 0x3d,
|
||||
0xd8, 0x38, 0x8c, 0x95, 0xce, 0xa6, 0x85, 0x98, 0xbd, 0x10, 0x5a, 0xb0, 0x07, 0xd0, 0xbc, 0x28,
|
||||
0xc7, 0x57, 0x52, 0x23, 0x6d, 0x6d, 0x77, 0x83, 0xbb, 0x93, 0x91, 0x60, 0x16, 0xa7, 0x91, 0x92,
|
||||
0x32, 0x75, 0x49, 0xb7, 0xf0, 0x1c, 0xe2, 0x91, 0x5c, 0xe2, 0xad, 0x75, 0xd5, 0x9c, 0x4b, 0xbc,
|
||||
0x25, 0xd7, 0x16, 0xd4, 0x14, 0x6a, 0x56, 0x27, 0xab, 0xf9, 0x64, 0x5f, 0xc1, 0x26, 0xfe, 0x89,
|
||||
0xb2, 0xcb, 0x48, 0xbd, 0x29, 0x45, 0x21, 0x55, 0xb7, 0x41, 0xce, 0x0e, 0x5a, 0x4f, 0x2e, 0x43,
|
||||
0x6b, 0x63, 0xf7, 0xa1, 0x31, 0xce, 0xca, 0x54, 0x77, 0x9b, 0xe4, 0xb4, 0x87, 0xe0, 0x8f, 0x1a,
|
||||
0x74, 0x06, 0x49, 0x2c, 0x53, 0x3d, 0xc8, 0xd2, 0xcb, 0x78, 0xca, 0xbe, 0x46, 0x32, 0x12, 0x3f,
|
||||
0xd2, 0xa2, 0x98, 0x4a, 0xad, 0x28, 0xe9, 0x36, 0xdf, 0xb0, 0xd6, 0x33, 0x6b, 0x64, 0xcf, 0xc0,
|
||||
0x1f, 0x53, 0x58, 0x44, 0x7a, 0xad, 0x91, 0x5e, 0xdd, 0x65, 0xbd, 0x2c, 0x2f, 0xc9, 0x05, 0xe3,
|
||||
0xeb, 0x6f, 0xf6, 0x19, 0x80, 0x4c, 0xc5, 0x45, 0x82, 0x15, 0x51, 0x09, 0xbd, 0x6e, 0x9d, 0xb7,
|
||||
0xad, 0x25, 0x54, 0x09, 0x3b, 0x80, 0x47, 0x59, 0xa9, 0x95, 0x16, 0xe9, 0x04, 0x49, 0x22, 0x24,
|
||||
0x54, 0x51, 0x8e, 0xe9, 0x8c, 0x5f, 0x8b, 0x34, 0x95, 0x09, 0x3d, 0xbc, 0xc1, 0xb7, 0x17, 0x30,
|
||||
0x1c, 0x21, 0xa7, 0xb2, 0x18, 0x58, 0x00, 0xfb, 0x06, 0x3e, 0x71, 0xa9, 0xb9, 0x10, 0xab, 0x47,
|
||||
0x83, 0x6f, 0x5a, 0xb3, 0xc3, 0x51, 0x63, 0xe5, 0xb6, 0xa4, 0x91, 0x8a, 0x7f, 0x97, 0x24, 0x4c,
|
||||
0x83, 0xfb, 0xce, 0x16, 0xa2, 0x89, 0x3d, 0x85, 0xfb, 0x42, 0xcd, 0xd3, 0x71, 0x54, 0x3d, 0xf6,
|
||||
0x75, 0x21, 0xc5, 0x44, 0x75, 0x5b, 0x04, 0x65, 0xe4, 0x73, 0xcf, 0xb4, 0x1e, 0x8c, 0x58, 0xc7,
|
||||
0x94, 0xad, 0x2a, 0xeb, 0xa4, 0xca, 0xa7, 0xcb, 0xaa, 0x60, 0xb6, 0x24, 0x49, 0xab, 0xb0, 0x1f,
|
||||
0x41, 0x13, 0xea, 0xc7, 0xa2, 0xb8, 0x0a, 0x4a, 0x00, 0x4b, 0xd5, 0x2f, 0xa6, 0x8a, 0xf5, 0xa0,
|
||||
0xa1, 0xa4, 0x2e, 0x73, 0x6a, 0x45, 0xbf, 0xb7, 0xb3, 0x4a, 0x5a, 0x5b, 0xb2, 0xc3, 0x7b, 0xdc,
|
||||
0x42, 0xd9, 0x2e, 0xd4, 0x67, 0xc8, 0x44, 0xd5, 0xf0, 0x7b, 0x6c, 0x39, 0xc4, 0xdc, 0x81, 0x50,
|
||||
0x42, 0x3c, 0x6f, 0x43, 0x0b, 0x0b, 0x69, 0x92, 0x0c, 0xfe, 0xf1, 0xc0, 0xb7, 0x74, 0x76, 0xdc,
|
||||
0x9e, 0x41, 0x3b, 0x11, 0x5a, 0xa6, 0xe3, 0x58, 0x2a, 0x77, 0xf9, 0xc3, 0x65, 0xa6, 0xa5, 0xee,
|
||||
0xe6, 0x37, 0xe8, 0x77, 0x26, 0xb5, 0xf6, 0x81, 0x49, 0xad, 0xbf, 0x7f, 0x52, 0x1b, 0xef, 0x4c,
|
||||
0xea, 0x41, 0xd5, 0xac, 0x26, 0xd5, 0x52, 0xb1, 0x27, 0x28, 0x92, 0x49, 0xda, 0xe5, 0xb9, 0xbd,
|
||||
0x4a, 0x24, 0xbb, 0x75, 0x2c, 0x2e, 0xf8, 0xd3, 0xc3, 0x35, 0x44, 0x8d, 0xec, 0xda, 0x1d, 0xfb,
|
||||
0xb8, 0x6a, 0xf7, 0x9b, 0xb9, 0xbf, 0xd5, 0xc7, 0x36, 0xc0, 0xf6, 0xb1, 0xba, 0xfe, 0x66, 0x5d,
|
||||
0x68, 0x55, 0xed, 0xb0, 0xe6, 0x16, 0x98, 0xeb, 0x81, 0xf7, 0x77, 0xb8, 0x29, 0xb4, 0xa5, 0xbc,
|
||||
0x43, 0xa1, 0x17, 0x93, 0xfd, 0xc8, 0x42, 0x87, 0xd5, 0xd3, 0xef, 0x24, 0xde, 0xc2, 0x06, 0x76,
|
||||
0xe2, 0x99, 0x6d, 0x97, 0x67, 0x85, 0x76, 0xaf, 0xa5, 0xef, 0xe0, 0x6f, 0xdc, 0x76, 0x61, 0x3c,
|
||||
0xcb, 0x13, 0x59, 0x2d, 0xf6, 0x1f, 0x61, 0x03, 0xd7, 0x4d, 0x9e, 0xa5, 0x4a, 0x46, 0x77, 0xdb,
|
||||
0xa5, 0x9d, 0x0a, 0x4f, 0xb2, 0x3e, 0x5e, 0x88, 0xa7, 0xb1, 0xb4, 0xd7, 0x5d, 0x83, 0x68, 0x2e,
|
||||
0x9f, 0x40, 0xcb, 0x8d, 0x29, 0xc9, 0xeb, 0xdf, 0x1e, 0x32, 0x47, 0xcf, 0x2b, 0x54, 0xd0, 0x87,
|
||||
0xcd, 0x2a, 0x4d, 0x4b, 0xb3, 0x48, 0xe1, 0xdd, 0x85, 0x62, 0xef, 0x00, 0xfc, 0x85, 0xac, 0x71,
|
||||
0x0f, 0x77, 0x06, 0x27, 0xc7, 0xa7, 0x7c, 0x18, 0x86, 0xfd, 0xe7, 0x47, 0xc3, 0xad, 0x7b, 0xa8,
|
||||
0xcf, 0xe6, 0xf9, 0x68, 0xc9, 0xe6, 0x31, 0x80, 0x26, 0xef, 0x8f, 0x5e, 0x9c, 0x1c, 0x6f, 0xad,
|
||||
0xed, 0xfd, 0x50, 0x0d, 0x38, 0xc5, 0x3f, 0x00, 0x16, 0xbe, 0x1a, 0x0d, 0x0e, 0xf9, 0xc9, 0xe8,
|
||||
0xe4, 0x3c, 0x8c, 0x06, 0x47, 0x2f, 0x87, 0xa3, 0x33, 0x64, 0x41, 0xde, 0xbe, 0x71, 0x54, 0x16,
|
||||
0xcf, 0xc4, 0xdd, 0xb4, 0xe0, 0xed, 0xb8, 0x70, 0xc8, 0x7f, 0x19, 0xf2, 0xc5, 0x38, 0x67, 0xf1,
|
||||
0xf6, 0x1e, 0x43, 0xcb, 0x2d, 0x1b, 0xd6, 0x86, 0xc6, 0xf9, 0xa8, 0xcf, 0x5f, 0x21, 0x6e, 0x03,
|
||||
0xda, 0xe1, 0x19, 0x1f, 0xf6, 0x8f, 0x5f, 0x8e, 0x7e, 0xde, 0xf2, 0x7a, 0x58, 0x40, 0xff, 0x0c,
|
||||
0x9f, 0x6c, 0x6e, 0x88, 0xc7, 0x92, 0xfd, 0x04, 0xed, 0xf3, 0x54, 0x14, 0xf3, 0x81, 0x48, 0x12,
|
||||
0x76, 0x6b, 0xf0, 0x97, 0x0a, 0xbd, 0xf3, 0x68, 0xb5, 0xd3, 0xc9, 0x3b, 0xc2, 0xbe, 0xd0, 0x38,
|
||||
0x0e, 0xf8, 0x8b, 0x36, 0xfd, 0x48, 0xae, 0x5d, 0xef, 0xa9, 0xd7, 0xfb, 0xcb, 0x83, 0xe6, 0xaf,
|
||||
0x59, 0x71, 0x85, 0x6b, 0x62, 0x80, 0xef, 0x2a, 0x53, 0x93, 0x34, 0x5b, 0xf9, 0x8b, 0x63, 0xc6,
|
||||
0x6a, 0x67, 0xe7, 0xff, 0x76, 0x41, 0xa9, 0x0c, 0x1f, 0x1b, 0x42, 0x1b, 0x49, 0xac, 0xae, 0x6c,
|
||||
0xe5, 0xc0, 0xaf, 0xa2, 0x59, 0x1c, 0x20, 0x43, 0x73, 0xd1, 0xa4, 0xff, 0x75, 0xbe, 0xff, 0x2f,
|
||||
0x00, 0x00, 0xff, 0xff, 0xe3, 0xb1, 0x00, 0x4d, 0xf9, 0x08, 0x00, 0x00,
|
||||
}
|
148
Godeps/_workspace/src/google.golang.org/grpc/benchmark/grpc_testing/test.proto
generated
vendored
148
Godeps/_workspace/src/google.golang.org/grpc/benchmark/grpc_testing/test.proto
generated
vendored
@ -1,148 +0,0 @@
|
||||
// An integration test service that covers all the method signature permutations
|
||||
// of unary/streaming requests/responses.
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.testing;
|
||||
|
||||
enum PayloadType {
|
||||
// Compressable text format.
|
||||
COMPRESSABLE = 0;
|
||||
|
||||
// Uncompressable binary format.
|
||||
UNCOMPRESSABLE = 1;
|
||||
|
||||
// Randomly chosen from all other formats defined in this enum.
|
||||
RANDOM = 2;
|
||||
}
|
||||
|
||||
message StatsRequest {
|
||||
// run number
|
||||
int32 test_num = 1;
|
||||
}
|
||||
|
||||
message ServerStats {
|
||||
// wall clock time
|
||||
double time_elapsed = 1;
|
||||
|
||||
// user time used by the server process and threads
|
||||
double time_user = 2;
|
||||
|
||||
// server time used by the server process and all threads
|
||||
double time_system = 3;
|
||||
}
|
||||
|
||||
message Payload {
|
||||
// The type of data in body.
|
||||
PayloadType type = 1;
|
||||
// Primary contents of payload.
|
||||
bytes body = 2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
enum ClientType {
|
||||
SYNCHRONOUS_CLIENT = 0;
|
||||
ASYNC_CLIENT = 1;
|
||||
}
|
||||
|
||||
enum ServerType {
|
||||
SYNCHRONOUS_SERVER = 0;
|
||||
ASYNC_SERVER = 1;
|
||||
}
|
||||
|
||||
enum RpcType {
|
||||
UNARY = 0;
|
||||
STREAMING = 1;
|
||||
}
|
||||
|
||||
message ClientConfig {
|
||||
repeated string server_targets = 1;
|
||||
ClientType client_type = 2;
|
||||
bool enable_ssl = 3;
|
||||
int32 outstanding_rpcs_per_channel = 4;
|
||||
int32 client_channels = 5;
|
||||
int32 payload_size = 6;
|
||||
// only for async client:
|
||||
int32 async_client_threads = 7;
|
||||
RpcType rpc_type = 8;
|
||||
}
|
||||
|
||||
// Request current stats
|
||||
message Mark {}
|
||||
|
||||
message ClientArgs {
|
||||
oneof argtype {
|
||||
ClientConfig setup = 1;
|
||||
Mark mark = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ClientStats {
|
||||
HistogramData latencies = 1;
|
||||
double time_elapsed = 3;
|
||||
double time_user = 4;
|
||||
double time_system = 5;
|
||||
}
|
||||
|
||||
message ClientStatus {
|
||||
ClientStats stats = 1;
|
||||
}
|
||||
|
||||
message ServerConfig {
|
||||
ServerType server_type = 1;
|
||||
int32 threads = 2;
|
||||
bool enable_ssl = 3;
|
||||
}
|
||||
|
||||
message ServerArgs {
|
||||
oneof argtype {
|
||||
ServerConfig setup = 1;
|
||||
Mark mark = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ServerStatus {
|
||||
ServerStats stats = 1;
|
||||
int32 port = 2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
message SimpleResponse {
|
||||
Payload payload = 1;
|
||||
}
|
||||
|
||||
service TestService {
|
||||
// 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 Worker {
|
||||
// Start test with specified workload
|
||||
rpc RunTest(stream ClientArgs) returns (stream ClientStatus);
|
||||
// Start test with specified workload
|
||||
rpc RunServer(stream ServerArgs) returns (stream ServerStatus);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
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(":0") // listen on all interfaces
|
||||
grpclog.Println("Server Address: ", addr)
|
||||
<-time.After(time.Duration(*duration) * time.Second)
|
||||
stopper()
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// TimeNow is used for testing.
|
||||
TimeNow = time.Now
|
||||
)
|
||||
|
||||
const (
|
||||
hour = 0
|
||||
tenminutes = 1
|
||||
minute = 2
|
||||
)
|
||||
|
||||
// Counter is a counter that keeps track of its recent values over a given
|
||||
// period of time, and with a given resolution. Use newCounter() to instantiate.
|
||||
type Counter struct {
|
||||
mu sync.RWMutex
|
||||
ts [3]*timeseries
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
// newCounter returns a new Counter.
|
||||
func newCounter() *Counter {
|
||||
now := TimeNow()
|
||||
c := &Counter{}
|
||||
c.ts[hour] = newTimeSeries(now, time.Hour, time.Minute)
|
||||
c.ts[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
|
||||
c.ts[minute] = newTimeSeries(now, time.Minute, time.Second)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Counter) advance() time.Time {
|
||||
now := TimeNow()
|
||||
for _, ts := range c.ts {
|
||||
ts.advanceTime(now)
|
||||
}
|
||||
return now
|
||||
}
|
||||
|
||||
// Value returns the current value of the counter.
|
||||
func (c *Counter) Value() int64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.ts[minute].headValue()
|
||||
}
|
||||
|
||||
// LastUpdate returns the last update time of the counter.
|
||||
func (c *Counter) LastUpdate() time.Time {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.lastUpdate
|
||||
}
|
||||
|
||||
// Set updates the current value of the counter.
|
||||
func (c *Counter) Set(value int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.lastUpdate = c.advance()
|
||||
for _, ts := range c.ts {
|
||||
ts.set(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Incr increments the current value of the counter by 'delta'.
|
||||
func (c *Counter) Incr(delta int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.lastUpdate = c.advance()
|
||||
for _, ts := range c.ts {
|
||||
ts.incr(delta)
|
||||
}
|
||||
}
|
||||
|
||||
// Delta1h returns the delta for the last hour.
|
||||
func (c *Counter) Delta1h() int64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[hour].delta()
|
||||
}
|
||||
|
||||
// Delta10m returns the delta for the last 10 minutes.
|
||||
func (c *Counter) Delta10m() int64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[tenminutes].delta()
|
||||
}
|
||||
|
||||
// Delta1m returns the delta for the last minute.
|
||||
func (c *Counter) Delta1m() int64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[minute].delta()
|
||||
}
|
||||
|
||||
// Rate1h returns the rate of change of the counter in the last hour.
|
||||
func (c *Counter) Rate1h() float64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[hour].rate()
|
||||
}
|
||||
|
||||
// Rate10m returns the rate of change of the counter in the last 10 minutes.
|
||||
func (c *Counter) Rate10m() float64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[tenminutes].rate()
|
||||
}
|
||||
|
||||
// Rate1m returns the rate of change of the counter in the last minute.
|
||||
func (c *Counter) Rate1m() float64 {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
c.advance()
|
||||
return c.ts[minute].rate()
|
||||
}
|
||||
|
||||
// Reset resets the counter to an empty state.
|
||||
func (c *Counter) Reset() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
now := TimeNow()
|
||||
for _, ts := range c.ts {
|
||||
ts.reset(now)
|
||||
}
|
||||
}
|
@ -1,255 +0,0 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HistogramValue is the value of Histogram objects.
|
||||
type HistogramValue 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
|
||||
// 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
|
||||
}
|
||||
|
||||
// HistogramBucket is one histogram bucket.
|
||||
type HistogramBucket struct {
|
||||
// LowBound is the lower bound of the bucket.
|
||||
LowBound int64
|
||||
// Count is the number of values in the bucket.
|
||||
Count int64
|
||||
}
|
||||
|
||||
// Print writes textual output of the histogram values.
|
||||
func (v HistogramValue) Print(w io.Writer) {
|
||||
avg := float64(v.Sum) / float64(v.Count)
|
||||
fmt.Fprintf(w, "Count: %d Min: %d Max: %d Avg: %.2f\n", v.Count, v.Min, v.Max, avg)
|
||||
fmt.Fprintf(w, "%s\n", strings.Repeat("-", 60))
|
||||
if v.Count <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
maxBucketDigitLen := len(strconv.FormatInt(v.Buckets[len(v.Buckets)-1].LowBound, 10))
|
||||
if maxBucketDigitLen < 3 {
|
||||
// For "inf".
|
||||
maxBucketDigitLen = 3
|
||||
}
|
||||
maxCountDigitLen := len(strconv.FormatInt(v.Count, 10))
|
||||
percentMulti := 100 / float64(v.Count)
|
||||
|
||||
accCount := int64(0)
|
||||
for i, b := range v.Buckets {
|
||||
fmt.Fprintf(w, "[%*d, ", maxBucketDigitLen, b.LowBound)
|
||||
if i+1 < len(v.Buckets) {
|
||||
fmt.Fprintf(w, "%*d)", maxBucketDigitLen, v.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 (v HistogramValue) String() string {
|
||||
var b bytes.Buffer
|
||||
v.Print(&b)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// A Histogram accumulates values in the form of a histogram. The type of the
|
||||
// values is int64, which is suitable for keeping track of things like RPC
|
||||
// latency in milliseconds. New histogram objects should be obtained via the
|
||||
// New() function.
|
||||
type Histogram struct {
|
||||
opts HistogramOptions
|
||||
buckets []bucketInternal
|
||||
count *Counter
|
||||
sum *Counter
|
||||
tracker *Tracker
|
||||
}
|
||||
|
||||
// HistogramOptions contains the parameters that define the histogram's buckets.
|
||||
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
|
||||
// SmallestBucketSize is the size of the first bucket. Bucket sizes are
|
||||
// rounded down to the nearest integer.
|
||||
SmallestBucketSize float64
|
||||
// MinValue is the lower bound of the first bucket.
|
||||
MinValue int64
|
||||
}
|
||||
|
||||
// bucketInternal is the internal representation of a bucket, which includes a
|
||||
// rate counter.
|
||||
type bucketInternal struct {
|
||||
lowBound int64
|
||||
count *Counter
|
||||
}
|
||||
|
||||
// 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.SmallestBucketSize == 0.0 {
|
||||
opts.SmallestBucketSize = 1.0
|
||||
}
|
||||
h := Histogram{
|
||||
opts: opts,
|
||||
buckets: make([]bucketInternal, opts.NumBuckets),
|
||||
count: newCounter(),
|
||||
sum: newCounter(),
|
||||
tracker: newTracker(),
|
||||
}
|
||||
low := opts.MinValue
|
||||
delta := opts.SmallestBucketSize
|
||||
for i := 0; i < opts.NumBuckets; i++ {
|
||||
h.buckets[i].lowBound = low
|
||||
h.buckets[i].count = newCounter()
|
||||
low = low + int64(delta)
|
||||
delta = delta * (1.0 + opts.GrowthFactor)
|
||||
}
|
||||
return &h
|
||||
}
|
||||
|
||||
// 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.Incr(1)
|
||||
h.count.Incr(1)
|
||||
h.sum.Incr(value)
|
||||
h.tracker.Push(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LastUpdate returns the time at which the object was last updated.
|
||||
func (h *Histogram) LastUpdate() time.Time {
|
||||
return h.count.LastUpdate()
|
||||
}
|
||||
|
||||
// Value returns the accumulated state of the histogram since it was created.
|
||||
func (h *Histogram) Value() HistogramValue {
|
||||
b := make([]HistogramBucket, len(h.buckets))
|
||||
for i, v := range h.buckets {
|
||||
b[i] = HistogramBucket{
|
||||
LowBound: v.lowBound,
|
||||
Count: v.count.Value(),
|
||||
}
|
||||
}
|
||||
|
||||
v := HistogramValue{
|
||||
Count: h.count.Value(),
|
||||
Sum: h.sum.Value(),
|
||||
Min: h.tracker.Min(),
|
||||
Max: h.tracker.Max(),
|
||||
Buckets: b,
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Delta1h returns the change in the last hour.
|
||||
func (h *Histogram) Delta1h() HistogramValue {
|
||||
b := make([]HistogramBucket, len(h.buckets))
|
||||
for i, v := range h.buckets {
|
||||
b[i] = HistogramBucket{
|
||||
LowBound: v.lowBound,
|
||||
Count: v.count.Delta1h(),
|
||||
}
|
||||
}
|
||||
|
||||
v := HistogramValue{
|
||||
Count: h.count.Delta1h(),
|
||||
Sum: h.sum.Delta1h(),
|
||||
Min: h.tracker.Min1h(),
|
||||
Max: h.tracker.Max1h(),
|
||||
Buckets: b,
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Delta10m returns the change in the last 10 minutes.
|
||||
func (h *Histogram) Delta10m() HistogramValue {
|
||||
b := make([]HistogramBucket, len(h.buckets))
|
||||
for i, v := range h.buckets {
|
||||
b[i] = HistogramBucket{
|
||||
LowBound: v.lowBound,
|
||||
Count: v.count.Delta10m(),
|
||||
}
|
||||
}
|
||||
|
||||
v := HistogramValue{
|
||||
Count: h.count.Delta10m(),
|
||||
Sum: h.sum.Delta10m(),
|
||||
Min: h.tracker.Min10m(),
|
||||
Max: h.tracker.Max10m(),
|
||||
Buckets: b,
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Delta1m returns the change in the last 10 minutes.
|
||||
func (h *Histogram) Delta1m() HistogramValue {
|
||||
b := make([]HistogramBucket, len(h.buckets))
|
||||
for i, v := range h.buckets {
|
||||
b[i] = HistogramBucket{
|
||||
LowBound: v.lowBound,
|
||||
Count: v.count.Delta1m(),
|
||||
}
|
||||
}
|
||||
|
||||
v := HistogramValue{
|
||||
Count: h.count.Delta1m(),
|
||||
Sum: h.sum.Delta1m(),
|
||||
Min: h.tracker.Min1m(),
|
||||
Max: h.tracker.Max1m(),
|
||||
Buckets: b,
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// findBucket does a binary search to find in which bucket the value goes.
|
||||
func (h *Histogram) findBucket(value int64) (int, error) {
|
||||
lastBucket := len(h.buckets) - 1
|
||||
min, max := 0, lastBucket
|
||||
for max >= min {
|
||||
b := (min + max) / 2
|
||||
if value >= h.buckets[b].lowBound && (b == lastBucket || value < h.buckets[b+1].lowBound) {
|
||||
return b, nil
|
||||
}
|
||||
if value < h.buckets[b].lowBound {
|
||||
max = b - 1
|
||||
continue
|
||||
}
|
||||
min = b + 1
|
||||
}
|
||||
return 0, fmt.Errorf("no bucket for value: %d", value)
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
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(i.e., Nth lower bound) = min + (1 + growthFactor)^(numBuckets-2).
|
||||
GrowthFactor: math.Pow(float64(stats.max-stats.min), 1/float64(stats.numBuckets-2)) - 1,
|
||||
SmallestBucketSize: 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.Value().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()
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// timeseries holds the history of a changing value over a predefined period of
|
||||
// time.
|
||||
type timeseries struct {
|
||||
size int // The number of time slots. Equivalent to len(slots).
|
||||
resolution time.Duration // The time resolution of each slot.
|
||||
stepCount int64 // The number of intervals seen since creation.
|
||||
head int // The position of the current time in slots.
|
||||
time time.Time // The time at the beginning of the current time slot.
|
||||
slots []int64 // A circular buffer of time slots.
|
||||
}
|
||||
|
||||
// newTimeSeries returns a newly allocated timeseries that covers the requested
|
||||
// period with the given resolution.
|
||||
func newTimeSeries(initialTime time.Time, period, resolution time.Duration) *timeseries {
|
||||
size := int(period.Nanoseconds()/resolution.Nanoseconds()) + 1
|
||||
return ×eries{
|
||||
size: size,
|
||||
resolution: resolution,
|
||||
stepCount: 1,
|
||||
time: initialTime,
|
||||
slots: make([]int64, size),
|
||||
}
|
||||
}
|
||||
|
||||
// advanceTimeWithFill moves the timeseries forward to time t and fills in any
|
||||
// slots that get skipped in the process with the given value. Values older than
|
||||
// the timeseries period are lost.
|
||||
func (ts *timeseries) advanceTimeWithFill(t time.Time, value int64) {
|
||||
advanceTo := t.Truncate(ts.resolution)
|
||||
if !advanceTo.After(ts.time) {
|
||||
// This is shortcut for the most common case of a busy counter
|
||||
// where updates come in many times per ts.resolution.
|
||||
ts.time = advanceTo
|
||||
return
|
||||
}
|
||||
steps := int(advanceTo.Sub(ts.time).Nanoseconds() / ts.resolution.Nanoseconds())
|
||||
ts.stepCount += int64(steps)
|
||||
if steps > ts.size {
|
||||
steps = ts.size
|
||||
}
|
||||
for steps > 0 {
|
||||
ts.head = (ts.head + 1) % ts.size
|
||||
ts.slots[ts.head] = value
|
||||
steps--
|
||||
}
|
||||
ts.time = advanceTo
|
||||
}
|
||||
|
||||
// advanceTime moves the timeseries forward to time t and fills in any slots
|
||||
// that get skipped in the process with the head value. Values older than the
|
||||
// timeseries period are lost.
|
||||
func (ts *timeseries) advanceTime(t time.Time) {
|
||||
ts.advanceTimeWithFill(t, ts.slots[ts.head])
|
||||
}
|
||||
|
||||
// set sets the current value of the timeseries.
|
||||
func (ts *timeseries) set(value int64) {
|
||||
ts.slots[ts.head] = value
|
||||
}
|
||||
|
||||
// incr sets the current value of the timeseries.
|
||||
func (ts *timeseries) incr(delta int64) {
|
||||
ts.slots[ts.head] += delta
|
||||
}
|
||||
|
||||
// headValue returns the latest value from the timeseries.
|
||||
func (ts *timeseries) headValue() int64 {
|
||||
return ts.slots[ts.head]
|
||||
}
|
||||
|
||||
// headTime returns the time of the latest value from the timeseries.
|
||||
func (ts *timeseries) headTime() time.Time {
|
||||
return ts.time
|
||||
}
|
||||
|
||||
// tailValue returns the oldest value from the timeseries.
|
||||
func (ts *timeseries) tailValue() int64 {
|
||||
if ts.stepCount < int64(ts.size) {
|
||||
return 0
|
||||
}
|
||||
return ts.slots[(ts.head+1)%ts.size]
|
||||
}
|
||||
|
||||
// tailTime returns the time of the oldest value from the timeseries.
|
||||
func (ts *timeseries) tailTime() time.Time {
|
||||
size := int64(ts.size)
|
||||
if ts.stepCount < size {
|
||||
size = ts.stepCount
|
||||
}
|
||||
return ts.time.Add(-time.Duration(size-1) * ts.resolution)
|
||||
}
|
||||
|
||||
// delta returns the difference between the newest and oldest values from the
|
||||
// timeseries.
|
||||
func (ts *timeseries) delta() int64 {
|
||||
return ts.headValue() - ts.tailValue()
|
||||
}
|
||||
|
||||
// rate returns the rate of change between the oldest and newest values from
|
||||
// the timeseries in units per second.
|
||||
func (ts *timeseries) rate() float64 {
|
||||
deltaTime := ts.headTime().Sub(ts.tailTime()).Seconds()
|
||||
if deltaTime == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(ts.delta()) / deltaTime
|
||||
}
|
||||
|
||||
// min returns the smallest value from the timeseries.
|
||||
func (ts *timeseries) min() int64 {
|
||||
to := ts.size
|
||||
if ts.stepCount < int64(ts.size) {
|
||||
to = ts.head + 1
|
||||
}
|
||||
tail := (ts.head + 1) % ts.size
|
||||
min := int64(math.MaxInt64)
|
||||
for b := 0; b < to; b++ {
|
||||
if b != tail && ts.slots[b] < min {
|
||||
min = ts.slots[b]
|
||||
}
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
// max returns the largest value from the timeseries.
|
||||
func (ts *timeseries) max() int64 {
|
||||
to := ts.size
|
||||
if ts.stepCount < int64(ts.size) {
|
||||
to = ts.head + 1
|
||||
}
|
||||
tail := (ts.head + 1) % ts.size
|
||||
max := int64(math.MinInt64)
|
||||
for b := 0; b < to; b++ {
|
||||
if b != tail && ts.slots[b] > max {
|
||||
max = ts.slots[b]
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
// reset resets the timeseries to an empty state.
|
||||
func (ts *timeseries) reset(t time.Time) {
|
||||
ts.head = 0
|
||||
ts.time = t
|
||||
ts.stepCount = 1
|
||||
ts.slots = make([]int64, ts.size)
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Tracker is a min/max value tracker that keeps track of its min/max values
|
||||
// over a given period of time, and with a given resolution. The initial min
|
||||
// and max values are math.MaxInt64 and math.MinInt64 respectively.
|
||||
type Tracker struct {
|
||||
mu sync.RWMutex
|
||||
min, max int64 // All time min/max.
|
||||
minTS, maxTS [3]*timeseries
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
// newTracker returns a new Tracker.
|
||||
func newTracker() *Tracker {
|
||||
now := TimeNow()
|
||||
t := &Tracker{}
|
||||
t.minTS[hour] = newTimeSeries(now, time.Hour, time.Minute)
|
||||
t.minTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
|
||||
t.minTS[minute] = newTimeSeries(now, time.Minute, time.Second)
|
||||
t.maxTS[hour] = newTimeSeries(now, time.Hour, time.Minute)
|
||||
t.maxTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
|
||||
t.maxTS[minute] = newTimeSeries(now, time.Minute, time.Second)
|
||||
t.init()
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Tracker) init() {
|
||||
t.min = math.MaxInt64
|
||||
t.max = math.MinInt64
|
||||
for _, ts := range t.minTS {
|
||||
ts.set(math.MaxInt64)
|
||||
}
|
||||
for _, ts := range t.maxTS {
|
||||
ts.set(math.MinInt64)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tracker) advance() time.Time {
|
||||
now := TimeNow()
|
||||
for _, ts := range t.minTS {
|
||||
ts.advanceTimeWithFill(now, math.MaxInt64)
|
||||
}
|
||||
for _, ts := range t.maxTS {
|
||||
ts.advanceTimeWithFill(now, math.MinInt64)
|
||||
}
|
||||
return now
|
||||
}
|
||||
|
||||
// LastUpdate returns the last update time of the range.
|
||||
func (t *Tracker) LastUpdate() time.Time {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
return t.lastUpdate
|
||||
}
|
||||
|
||||
// Push adds a new value if it is a new minimum or maximum.
|
||||
func (t *Tracker) Push(value int64) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.lastUpdate = t.advance()
|
||||
if t.min > value {
|
||||
t.min = value
|
||||
}
|
||||
if t.max < value {
|
||||
t.max = value
|
||||
}
|
||||
for _, ts := range t.minTS {
|
||||
if ts.headValue() > value {
|
||||
ts.set(value)
|
||||
}
|
||||
}
|
||||
for _, ts := range t.maxTS {
|
||||
if ts.headValue() < value {
|
||||
ts.set(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Min returns the minimum value of the tracker
|
||||
func (t *Tracker) Min() int64 {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
return t.min
|
||||
}
|
||||
|
||||
// Max returns the maximum value of the tracker.
|
||||
func (t *Tracker) Max() int64 {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
return t.max
|
||||
}
|
||||
|
||||
// Min1h returns the minimum value for the last hour.
|
||||
func (t *Tracker) Min1h() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.minTS[hour].min()
|
||||
}
|
||||
|
||||
// Max1h returns the maximum value for the last hour.
|
||||
func (t *Tracker) Max1h() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.maxTS[hour].max()
|
||||
}
|
||||
|
||||
// Min10m returns the minimum value for the last 10 minutes.
|
||||
func (t *Tracker) Min10m() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.minTS[tenminutes].min()
|
||||
}
|
||||
|
||||
// Max10m returns the maximum value for the last 10 minutes.
|
||||
func (t *Tracker) Max10m() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.maxTS[tenminutes].max()
|
||||
}
|
||||
|
||||
// Min1m returns the minimum value for the last 1 minute.
|
||||
func (t *Tracker) Min1m() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.minTS[minute].min()
|
||||
}
|
||||
|
||||
// Max1m returns the maximum value for the last 1 minute.
|
||||
func (t *Tracker) Max1m() int64 {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.advance()
|
||||
return t.maxTS[minute].max()
|
||||
}
|
||||
|
||||
// Reset resets the range to an empty state.
|
||||
func (t *Tracker) Reset() {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
now := TimeNow()
|
||||
for _, ts := range t.minTS {
|
||||
ts.reset(now)
|
||||
}
|
||||
for _, ts := range t.maxTS {
|
||||
ts.reset(now)
|
||||
}
|
||||
t.init()
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
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)
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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 credentials 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.TokenType + " " + token.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ts TokenSource) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type jwtAccess struct {
|
||||
jsonKey []byte
|
||||
}
|
||||
|
||||
func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, 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)
|
||||
}
|
||||
|
||||
func NewJWTAccessFromKey(jsonKey []byte) (credentials.Credentials, 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 credentials from a given token.
|
||||
type oauthAccess struct {
|
||||
token oauth2.Token
|
||||
}
|
||||
|
||||
// NewOauthAccess constructs the credentials using a given token.
|
||||
func NewOauthAccess(token *oauth2.Token) credentials.Credentials {
|
||||
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 credentials 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.Credentials {
|
||||
return TokenSource{google.ComputeTokenSource("")}
|
||||
}
|
||||
|
||||
// serviceAccount represents credentials 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 credentials using the JSON key slice
|
||||
// from a Google Developers service account.
|
||||
func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Credentials, error) {
|
||||
config, err := google.JWTConfigFromJSON(jsonKey, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return serviceAccount{config: config}, nil
|
||||
}
|
||||
|
||||
// NewServiceAccountFromFile constructs the credentials using the JSON key file
|
||||
// of a Google Developers service account.
|
||||
func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Credentials, 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.Credentials, error) {
|
||||
t, err := google.DefaultTokenSource(ctx, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return TokenSource{t}, nil
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
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
|
||||
```
|
@ -1,431 +0,0 @@
|
||||
#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.
|
||||
|
||||
|
||||
<a name="server"></a>
|
||||
## 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.
|
||||
|
||||
<a name="client"></a>
|
||||
## 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
|
||||
```
|
||||
|
69
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/greeter_client/main.go
generated
vendored
69
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/greeter_client/main.go
generated
vendored
@ -1,69 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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"
|
||||
|
||||
pb "google.golang.org/grpc/examples/helloworld/helloworld"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
65
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/greeter_server/main.go
generated
vendored
65
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/greeter_server/main.go
generated
vendored
@ -1,65 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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"
|
||||
|
||||
pb "google.golang.org/grpc/examples/helloworld/helloworld"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
137
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.pb.go
generated
vendored
137
Godeps/_workspace/src/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.pb.go
generated
vendored
@ -1,137 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// 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
|
||||
|
||||
// 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) (interface{}, error) {
|
||||
in := new(HelloRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(GreeterServer).SayHello(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
var _Greeter_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "helloworld.Greeter",
|
||||
HandlerType: (*GreeterServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "SayHello",
|
||||
Handler: _Greeter_SayHello_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 181 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, 0xe3, 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, 0xb8, 0x88, 0x89, 0xd9, 0xc3,
|
||||
0x27, 0x3c, 0x89, 0x0d, 0xec, 0x43, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0x0a, 0xdc,
|
||||
0xe8, 0xf5, 0x00, 0x00, 0x00,
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
// 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";
|
||||
option objc_class_prefix = "HLW";
|
||||
|
||||
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;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
# 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
|
||||
```
|
202
Godeps/_workspace/src/google.golang.org/grpc/examples/route_guide/client/client.go
generated
vendored
202
Godeps/_workspace/src/google.golang.org/grpc/examples/route_guide/client/client.go
generated
vendored
@ -1,202 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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{0, 1}, "First message"},
|
||||
{&pb.Point{0, 2}, "Second message"},
|
||||
{&pb.Point{0, 3}, "Third message"},
|
||||
{&pb.Point{0, 1}, "Fourth message"},
|
||||
{&pb.Point{0, 2}, "Fifth message"},
|
||||
{&pb.Point{0, 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.TransportAuthenticator
|
||||
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{400000000, -750000000}, &pb.Point{420000000, -730000000}})
|
||||
|
||||
// RecordRoute
|
||||
runRecordRoute(client)
|
||||
|
||||
// RouteChat
|
||||
runRouteChat(client)
|
||||
}
|
@ -1,473 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// 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:"point_count,omitempty"`
|
||||
// The number of known features passed while traversing the route.
|
||||
FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count" 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:"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
|
||||
|
||||
// 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) (interface{}, error) {
|
||||
in := new(Point)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(RouteGuideServer).GetFeature(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 412 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0xd1, 0x6a, 0xa3, 0x40,
|
||||
0x14, 0xcd, 0x98, 0x64, 0xb3, 0x5e, 0x5d, 0x96, 0xcc, 0xb2, 0x20, 0xd9, 0x85, 0xb6, 0xf6, 0x25,
|
||||
0x2f, 0x95, 0x90, 0x42, 0x1e, 0x5b, 0x9a, 0x40, 0xf3, 0x12, 0x4a, 0x6a, 0xf3, 0x1e, 0xa6, 0x3a,
|
||||
0x35, 0x03, 0xea, 0x88, 0x8e, 0xd0, 0x7e, 0x40, 0xbf, 0xa0, 0x7f, 0xd0, 0x2f, 0xed, 0x38, 0x6a,
|
||||
0x62, 0xda, 0x84, 0xbe, 0x39, 0xe7, 0x9e, 0x73, 0xef, 0xb9, 0xe7, 0x22, 0xf4, 0x53, 0x9e, 0x0b,
|
||||
0xba, 0x0e, 0x72, 0xe6, 0x53, 0x27, 0x49, 0xb9, 0xe0, 0x18, 0x14, 0xa4, 0x10, 0xfb, 0x06, 0xba,
|
||||
0x4b, 0xce, 0x62, 0x81, 0x07, 0xf0, 0x33, 0x24, 0x82, 0x89, 0xdc, 0xa7, 0x16, 0x3a, 0x45, 0xc3,
|
||||
0xae, 0xbb, 0x7d, 0xe3, 0xff, 0xa0, 0x87, 0x3c, 0x0e, 0xca, 0xa2, 0xa6, 0x8a, 0x3b, 0xc0, 0xbe,
|
||||
0x07, 0xdd, 0xa5, 0x9e, 0x20, 0x71, 0x10, 0x52, 0x7c, 0x06, 0x5a, 0xc8, 0x55, 0x03, 0x63, 0xdc,
|
||||
0x77, 0x76, 0x83, 0x1c, 0x35, 0xc5, 0x95, 0xc5, 0x82, 0xb2, 0x61, 0xaa, 0xcd, 0x61, 0xca, 0x86,
|
||||
0xd9, 0x0b, 0xe8, 0xdd, 0x52, 0x22, 0xf2, 0x94, 0x62, 0x0c, 0x9d, 0x98, 0x44, 0xa5, 0x27, 0xdd,
|
||||
0x55, 0xdf, 0xf8, 0x42, 0x7a, 0xe5, 0x9e, 0x74, 0xc7, 0xe3, 0xe3, 0x7d, 0xb6, 0x14, 0x7b, 0x25,
|
||||
0x0d, 0x16, 0xd5, 0x3b, 0x2e, 0xf6, 0xb5, 0xe8, 0x5b, 0x2d, 0xb6, 0xa0, 0x17, 0xd1, 0x2c, 0x23,
|
||||
0x41, 0xb9, 0xb8, 0xee, 0xd6, 0x4f, 0xfb, 0x0d, 0x81, 0xa9, 0xda, 0x3e, 0xe4, 0x51, 0x44, 0xd2,
|
||||
0x17, 0x7c, 0x02, 0x46, 0x52, 0xa8, 0xd7, 0x1e, 0xcf, 0x63, 0x51, 0x85, 0x08, 0x0a, 0x9a, 0x15,
|
||||
0x08, 0x3e, 0x87, 0x5f, 0x4f, 0xe5, 0x56, 0x15, 0xa5, 0x8c, 0xd2, 0xac, 0xc0, 0x92, 0x24, 0xef,
|
||||
0xe0, 0xb3, 0x4c, 0xa6, 0xe9, 0x51, 0xab, 0x5d, 0xde, 0xa1, 0x7e, 0xcb, 0xe4, 0x4c, 0x1a, 0x92,
|
||||
0x24, 0xa3, 0xfe, 0x5a, 0x30, 0x99, 0x49, 0x47, 0xd5, 0x8d, 0x0a, 0x5b, 0x49, 0x68, 0xfc, 0xaa,
|
||||
0x01, 0x28, 0x57, 0xf3, 0x62, 0x1d, 0x3c, 0x01, 0x98, 0x53, 0x51, 0x67, 0xf9, 0x75, 0xd3, 0xc1,
|
||||
0x9f, 0x26, 0x54, 0xf1, 0xec, 0x16, 0xbe, 0x02, 0x73, 0x21, 0xa7, 0x56, 0x40, 0x86, 0xff, 0x36,
|
||||
0x69, 0xdb, 0x6b, 0x1f, 0x51, 0x8f, 0x90, 0xd4, 0x1b, 0x92, 0xc5, 0x53, 0x5f, 0x79, 0x39, 0x34,
|
||||
0xd8, 0xda, 0xeb, 0xd8, 0xc8, 0xd1, 0x6e, 0x0d, 0x11, 0xbe, 0xae, 0x4e, 0x36, 0xdb, 0x10, 0xf1,
|
||||
0x69, 0x78, 0x7d, 0xc9, 0xc1, 0x61, 0xb8, 0x90, 0x8f, 0xd0, 0x74, 0x02, 0xff, 0x18, 0x77, 0x82,
|
||||
0x34, 0xf1, 0x1c, 0xfa, 0x4c, 0xa2, 0x24, 0xa4, 0x59, 0x83, 0x3e, 0xfd, 0xbd, 0xcb, 0x68, 0x59,
|
||||
0xfc, 0x13, 0x4b, 0xf4, 0xae, 0xb5, 0xdd, 0xd5, 0xfc, 0xf1, 0x87, 0xfa, 0x45, 0x2e, 0x3f, 0x02,
|
||||
0x00, 0x00, 0xff, 0xff, 0xf3, 0xe2, 0x76, 0x5e, 0x37, 0x03, 0x00, 0x00,
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
// 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";
|
||||
option objc_class_prefix = "RTG";
|
||||
|
||||
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;
|
||||
}
|
239
Godeps/_workspace/src/google.golang.org/grpc/examples/route_guide/server/server.go
generated
vendored
239
Godeps/_workspace/src/google.golang.org/grpc/examples/route_guide/server/server.go
generated
vendored
@ -1,239 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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 comtained 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)
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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...)
|
||||
}
|
162
Godeps/_workspace/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
generated
vendored
162
Godeps/_workspace/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
generated
vendored
@ -1,162 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
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
|
||||
|
||||
// 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) (interface{}, error) {
|
||||
in := new(HealthCheckRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(HealthServer).Check(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
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{},
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 209 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, 0x12, 0x4e, 0x2f, 0x2a, 0x48, 0xd6, 0x83,
|
||||
0x0a, 0x95, 0x19, 0x26, 0xe6, 0x14, 0x64, 0x24, 0x2a, 0xe9, 0x71, 0x09, 0x79, 0x80, 0x45, 0x9c,
|
||||
0x33, 0x52, 0x93, 0xb3, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x24, 0xb8, 0xd8, 0x8b,
|
||||
0x53, 0x8b, 0xca, 0x32, 0x93, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x60, 0x5c, 0xa5,
|
||||
0x85, 0x8c, 0x5c, 0xc2, 0x28, 0x1a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0xfc, 0xb8, 0xd8,
|
||||
0x8a, 0x4b, 0x12, 0x4b, 0x4a, 0x8b, 0xc1, 0x1a, 0xf8, 0x8c, 0xcc, 0xf4, 0xb0, 0xd8, 0xa6, 0x87,
|
||||
0x45, 0xa7, 0x5e, 0x30, 0xc8, 0xe4, 0xbc, 0xf4, 0x60, 0xb0, 0xee, 0x20, 0xa8, 0x29, 0x4a, 0x56,
|
||||
0x5c, 0xbc, 0x28, 0x12, 0x42, 0xdc, 0x5c, 0xec, 0xa1, 0x7e, 0xde, 0x7e, 0xfe, 0xe1, 0x7e, 0x02,
|
||||
0x0c, 0x20, 0x4e, 0xb0, 0x6b, 0x50, 0x98, 0xa7, 0x9f, 0xbb, 0x00, 0xa3, 0x10, 0x3f, 0x17, 0xb7,
|
||||
0x9f, 0x7f, 0x48, 0x3c, 0x4c, 0x80, 0xc9, 0x28, 0x85, 0x8b, 0x0d, 0x62, 0x91, 0x50, 0x14, 0x17,
|
||||
0x2b, 0xd8, 0x32, 0x21, 0x75, 0xc2, 0xce, 0x01, 0xfb, 0x5c, 0x4a, 0x83, 0x58, 0x77, 0x27, 0xb1,
|
||||
0x81, 0x43, 0xd5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x3f, 0xd0, 0xe1, 0x65, 0x01, 0x00,
|
||||
0x00,
|
||||
}
|
20
Godeps/_workspace/src/google.golang.org/grpc/health/grpc_health_v1/health.proto
generated
vendored
20
Godeps/_workspace/src/google.golang.org/grpc/health/grpc_health_v1/health.proto
generated
vendored
@ -1,20 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// 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()
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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.TransportAuthenticator
|
||||
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)
|
||||
case "large_unary":
|
||||
interop.DoLargeUnaryCall(tc)
|
||||
case "client_streaming":
|
||||
interop.DoClientStreaming(tc)
|
||||
case "server_streaming":
|
||||
interop.DoServerStreaming(tc)
|
||||
case "ping_pong":
|
||||
interop.DoPingPong(tc)
|
||||
case "empty_stream":
|
||||
interop.DoEmptyStream(tc)
|
||||
case "timeout_on_sleeping_server":
|
||||
interop.DoTimeoutOnSleepingServer(tc)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
case "cancel_after_begin":
|
||||
interop.DoCancelAfterBegin(tc)
|
||||
case "cancel_after_first_response":
|
||||
interop.DoCancelAfterFirstResponse(tc)
|
||||
default:
|
||||
grpclog.Fatal("Unsupported test case: ", *testCase)
|
||||
}
|
||||
}
|
@ -1,767 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// 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,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:"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:"fill_username,omitempty"`
|
||||
// Whether SimpleResponse should include OAuth scope.
|
||||
FillOauthScope *bool `protobuf:"varint,5,opt,name=fill_oauth_scope" 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:"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:"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:"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,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
|
||||
// Configuration for each expected response message.
|
||||
ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters" 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
|
||||
|
||||
// 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) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(TestServiceServer).EmptyCall(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
// 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);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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)
|
||||
}
|
@ -1,607 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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{})
|
||||
}
|
||||
grpclog.Println("EmptyUnaryCall done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("LargeUnaryCall done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("ClientStreaming done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("ServerStreaming done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("Pingpong done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("Emptystream done")
|
||||
}
|
||||
|
||||
// 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 {
|
||||
grpclog.Println("TimeoutOnSleepingServer done")
|
||||
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)
|
||||
}
|
||||
grpclog.Println("TimeoutOnSleepingServer done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("ComputeEngineCreds done")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
grpclog.Println("ServiceAccountCreds done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("JWTtokenCreds done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("Oauth2TokenCreds done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("PerRPCCreds done")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
grpclog.Println("CancelAfterBegin done")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
grpclog.Println("CancelAfterFirstResponse done")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// 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;
|
||||
}
|
@ -1,767 +0,0 @@
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// 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,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:"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:"fill_username,omitempty"`
|
||||
// Whether SimpleResponse should include OAuth scope.
|
||||
FillOauthScope *bool `protobuf:"varint,5,opt,name=fill_oauth_scope" 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:"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:"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:"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,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
|
||||
// Configuration for each expected response message.
|
||||
ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters" 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
|
||||
|
||||
// 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) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(TestServiceServer).EmptyCall(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
// 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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue