Commit ead87d4f authored by Yifan Gu's avatar Yifan Gu Committed by Jonathan Boulle

Godeps: Bump rkt api, go grpc, go protobuf.

parent 0b044158
......@@ -136,10 +136,6 @@
"Rev": "ee4a0888a9abe7eefe5a0992ca4cb06864839873"
},
{
"ImportPath": "github.com/bradfitz/http2",
"Rev": "3e36af6d3af0e56fa3da71099f864933dea3d9fb"
},
{
"ImportPath": "github.com/camlistore/go4/errorutil",
"Rev": "3b6feb5cf32f573fb124905de36a54c24ee14ac1"
},
......@@ -150,123 +146,123 @@
},
{
"ImportPath": "github.com/coreos/etcd/client",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/discovery",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/error",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/etcdserver",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/crc",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/timeutil",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/transport",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/types",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/pkg/wait",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/raft",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/rafthttp",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/snap",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/storage",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/store",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/version",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/etcd/wal",
"Comment": "v2.2.2-4-ge0c7768",
"Rev": "e0c7768f94cdc268b2fce31ada1dea823f11f505"
"Comment": "v2.2.5",
"Rev": "bc9ddf260115d2680191c46977ae72b837785472"
},
{
"ImportPath": "github.com/coreos/go-etcd/etcd",
......@@ -340,8 +336,8 @@
},
{
"ImportPath": "github.com/coreos/rkt/api/v1alpha",
"Comment": "v0.15.0-22-g8ac03ac",
"Rev": "8ac03ace42034b4d6b31af9e3ef574b9e71ccc1a"
"Comment": "v1.0.0",
"Rev": "1ddc36601c8688ff207210bc9ecbf973d09573fa"
},
{
"ImportPath": "github.com/cpuguy83/go-md2man/md2man",
......@@ -425,7 +421,6 @@
},
{
"ImportPath": "github.com/fsouza/go-dockerclient",
"Comment": "0.2.1-860-g25bc220",
"Rev": "25bc220b299845ae5489fd19bf89c5278864b050"
},
{
......@@ -452,118 +447,118 @@
},
{
"ImportPath": "github.com/gogo/protobuf/gogoproto",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/defaultcheck",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/description",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/embedcheck",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/enumstringer",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/equal",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/face",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/gostring",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/grpc",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/marshalto",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/oneofcheck",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/populate",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/size",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/stringer",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/testgen",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/union",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/plugin/unmarshal",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/proto",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/generator",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/plugin",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/sortkeys",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/gogo/protobuf/vanity",
"Comment": "v0.1-108-g9dc5109",
"Rev": "9dc510915846dd5a05607d3b5bf41f5ca5cce972"
"Comment": "v0.1-125-g82d16f7",
"Rev": "82d16f734d6d871204a3feb1a73cb220cc92574c"
},
{
"ImportPath": "github.com/golang/glog",
......@@ -575,7 +570,7 @@
},
{
"ImportPath": "github.com/golang/protobuf/proto",
"Rev": "7f07925444bb51fa4cf9dfe6f7661876f8852275"
"Rev": "b982704f8bb716bb608144408cff30e15fbde841"
},
{
"ImportPath": "github.com/google/btree",
......@@ -971,6 +966,10 @@
"Rev": "c2528b2dd8352441850638a8bb678c2ad056fd3e"
},
{
"ImportPath": "golang.org/x/net/http2",
"Rev": "c2528b2dd8352441850638a8bb678c2ad056fd3e"
},
{
"ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "c2528b2dd8352441850638a8bb678c2ad056fd3e"
},
......@@ -1028,7 +1027,7 @@
},
{
"ImportPath": "google.golang.org/grpc",
"Rev": "4bd040ce23a624ff9a1d07b0e729ee189bddd51c"
"Rev": "933601d8cd6418a8a891bd9075a7161b0a67badb"
},
{
"ImportPath": "gopkg.in/natefinch/lumberjack.v2",
......@@ -1041,7 +1040,7 @@
},
{
"ImportPath": "k8s.io/heapster/api/v1/types",
"Comment": "v0.19.1",
"Comment": "v0.19.1-44-g0991ac5",
"Rev": "0991ac528ea24aae194e45d6dcf01896cb42cbea"
},
{
......
......@@ -13,7 +13,6 @@ github.com/aws/aws-sdk-go | Apache-2
github.com/beorn7/perks/quantile | MIT?
github.com/blang/semver | MITname
github.com/boltdb/bolt | MITname
github.com/bradfitz/http2 | BSDlikeRef
github.com/camlistore/go4 | Apache-2
github.com/ClusterHQ/flocker-go | UNKNOWN
github.com/codegangsta/negroni | MITname
......@@ -23,7 +22,7 @@ github.com/coreos/go-oidc | Apache-2
github.com/coreos/go-semver | Apache-2
github.com/coreos/go-systemd | Apache-2
github.com/coreos/pkg | Apache-2
github.com/coreos/rkt | Apache-2
github.com/coreos/rkt | MITname
github.com/cpuguy83/go-md2man | MITname
github.com/davecgh/go-spew | MIToldwithoutSellandNoDocumentationRequi
github.com/daviddengcn/go-colortext | BSD?
......
# This file is like Go's AUTHORS file: it lists Copyright holders.
# The list of humans who have contributd is in the CONTRIBUTORS file.
#
# To contribute to this project, because it will eventually be folded
# back in to Go itself, you need to submit a CLA:
#
# http://golang.org/doc/contribute.html#copyright
#
# Then you get added to CONTRIBUTORS and you or your company get added
# to the AUTHORS file.
Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
Google, Inc.
Keith Rarick <kr@xph.us> github=kr
Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
Matt Layher <mdlayher@gmail.com> github=mdlayher
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t
# This file is like Go's CONTRIBUTORS file: it lists humans.
# The list of copyright holders (which may be companies) are in the AUTHORS file.
#
# To contribute to this project, because it will eventually be folded
# back in to Go itself, you need to submit a CLA:
#
# http://golang.org/doc/contribute.html#copyright
#
# Then you get added to CONTRIBUTORS and you or your company get added
# to the AUTHORS file.
Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
Brad Fitzpatrick <bradfitz@golang.org> github=bradfitz
Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
Keith Rarick <kr@xph.us> github=kr
Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
Matt Layher <mdlayher@gmail.com> github=mdlayher
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t
We only accept contributions from users who have gone through Go's
contribution process (signed a CLA).
Please acknowledge whether you have (and use the same email) if
sending a pull request.
Copyright 2014 Google & the Go AUTHORS
Go AUTHORS are:
See https://code.google.com/p/go/source/browse/AUTHORS
Licensed under the terms of Go itself:
https://code.google.com/p/go/source/browse/LICENSE
......@@ -24,6 +24,7 @@ import (
"net/url"
"reflect"
"sort"
"strconv"
"sync"
"time"
......@@ -99,6 +100,8 @@ type Config struct {
// watch start. But if server is behind some kind of proxy, the response
// header may be cached at proxy, and Client cannot rely on this behavior.
//
// Especially, wait request will ignore this timeout.
//
// One API call may send multiple requests to different etcd servers until it
// succeeds. Use context of the API to specify the overall timeout.
//
......@@ -162,6 +165,11 @@ type Client interface {
// this may differ from the initial Endpoints provided in the Config.
Endpoints() []string
// SetEndpoints sets the set of API endpoints used by Client to resolve
// HTTP requests. If the given endpoints are not valid, an error will be
// returned
SetEndpoints(eps []string) error
httpClient
}
......@@ -176,7 +184,7 @@ func New(cfg Config) (Client, error) {
password: cfg.Password,
}
}
if err := c.reset(cfg.Endpoints); err != nil {
if err := c.SetEndpoints(cfg.Endpoints); err != nil {
return nil, err
}
return c, nil
......@@ -219,7 +227,7 @@ type httpClusterClient struct {
rand *rand.Rand
}
func (c *httpClusterClient) reset(eps []string) error {
func (c *httpClusterClient) SetEndpoints(eps []string) error {
if len(eps) == 0 {
return ErrNoEndpoints
}
......@@ -341,7 +349,7 @@ func (c *httpClusterClient) Sync(ctx context.Context) error {
return nil
}
return c.reset(eps)
return c.SetEndpoints(eps)
}
func (c *httpClusterClient) AutoSync(ctx context.Context, interval time.Duration) error {
......@@ -378,9 +386,21 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon
return nil, nil, err
}
isWait := false
if req != nil && req.URL != nil {
ws := req.URL.Query().Get("wait")
if len(ws) != 0 {
var err error
isWait, err = strconv.ParseBool(ws)
if err != nil {
return nil, nil, fmt.Errorf("wrong wait value %s (%v for %+v)", ws, err, req)
}
}
}
var hctx context.Context
var hcancel context.CancelFunc
if c.headerTimeout > 0 {
if !isWait && c.headerTimeout > 0 {
hctx, hcancel = context.WithTimeout(ctx, c.headerTimeout)
} else {
hctx, hcancel = context.WithCancel(ctx)
......
......@@ -95,8 +95,7 @@ type store struct {
timeout time.Duration
ensuredOnce bool
mu sync.Mutex // protect enabled
enabled *bool
mu sync.Mutex
}
type User struct {
......@@ -409,8 +408,6 @@ func (s *store) EnableAuth() error {
}
err = s.enableAuth()
if err == nil {
b := true
s.enabled = &b
plog.Noticef("auth: enabled auth")
} else {
plog.Errorf("error enabling auth (%v)", err)
......@@ -428,8 +425,6 @@ func (s *store) DisableAuth() error {
err := s.disableAuth()
if err == nil {
b := false
s.enabled = &b
plog.Noticef("auth: disabled auth")
} else {
plog.Errorf("error disabling auth (%v)", err)
......
......@@ -85,15 +85,10 @@ func (s *store) detectAuth() bool {
if s.server == nil {
return false
}
if s.enabled != nil {
return *s.enabled
}
value, err := s.requestResource("/enabled", false)
if err != nil {
if e, ok := err.(*etcderr.Error); ok {
if e.ErrorCode == etcderr.EcodeKeyNotFound {
b := false
s.enabled = &b
return false
}
}
......@@ -107,7 +102,6 @@ func (s *store) detectAuth() bool {
plog.Errorf("internal bookkeeping value for enabled isn't valid JSON (%v)", err)
return false
}
s.enabled = &u
return u
}
......
......@@ -13,38 +13,56 @@
It has these top-level messages:
Request
Metadata
InternalRaftRequest
ResponseHeader
RangeRequest
RangeResponse
PutRequest
PutResponse
DeleteRangeRequest
DeleteRangeResponse
RequestUnion
ResponseUnion
Compare
TxnRequest
TxnResponse
CompactionRequest
CompactionResponse
*/
package etcdserverpb
import proto "github.com/gogo/protobuf/proto"
import math "math"
import (
"fmt"
proto "github.com/gogo/protobuf/proto"
)
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type Request struct {
ID uint64 `protobuf:"varint,1,opt" json:"ID"`
Method string `protobuf:"bytes,2,opt" json:"Method"`
Path string `protobuf:"bytes,3,opt" json:"Path"`
Val string `protobuf:"bytes,4,opt" json:"Val"`
Dir bool `protobuf:"varint,5,opt" json:"Dir"`
PrevValue string `protobuf:"bytes,6,opt" json:"PrevValue"`
PrevIndex uint64 `protobuf:"varint,7,opt" json:"PrevIndex"`
PrevExist *bool `protobuf:"varint,8,opt" json:"PrevExist,omitempty"`
Expiration int64 `protobuf:"varint,9,opt" json:"Expiration"`
Wait bool `protobuf:"varint,10,opt" json:"Wait"`
Since uint64 `protobuf:"varint,11,opt" json:"Since"`
Recursive bool `protobuf:"varint,12,opt" json:"Recursive"`
Sorted bool `protobuf:"varint,13,opt" json:"Sorted"`
Quorum bool `protobuf:"varint,14,opt" json:"Quorum"`
Time int64 `protobuf:"varint,15,opt" json:"Time"`
Stream bool `protobuf:"varint,16,opt" json:"Stream"`
ID uint64 `protobuf:"varint,1,opt,name=ID" json:"ID"`
Method string `protobuf:"bytes,2,opt,name=Method" json:"Method"`
Path string `protobuf:"bytes,3,opt,name=Path" json:"Path"`
Val string `protobuf:"bytes,4,opt,name=Val" json:"Val"`
Dir bool `protobuf:"varint,5,opt,name=Dir" json:"Dir"`
PrevValue string `protobuf:"bytes,6,opt,name=PrevValue" json:"PrevValue"`
PrevIndex uint64 `protobuf:"varint,7,opt,name=PrevIndex" json:"PrevIndex"`
PrevExist *bool `protobuf:"varint,8,opt,name=PrevExist" json:"PrevExist,omitempty"`
Expiration int64 `protobuf:"varint,9,opt,name=Expiration" json:"Expiration"`
Wait bool `protobuf:"varint,10,opt,name=Wait" json:"Wait"`
Since uint64 `protobuf:"varint,11,opt,name=Since" json:"Since"`
Recursive bool `protobuf:"varint,12,opt,name=Recursive" json:"Recursive"`
Sorted bool `protobuf:"varint,13,opt,name=Sorted" json:"Sorted"`
Quorum bool `protobuf:"varint,14,opt,name=Quorum" json:"Quorum"`
Time int64 `protobuf:"varint,15,opt,name=Time" json:"Time"`
Stream bool `protobuf:"varint,16,opt,name=Stream" json:"Stream"`
XXX_unrecognized []byte `json:"-"`
}
......@@ -53,8 +71,8 @@ func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
type Metadata struct {
NodeID uint64 `protobuf:"varint,1,opt" json:"NodeID"`
ClusterID uint64 `protobuf:"varint,2,opt" json:"ClusterID"`
NodeID uint64 `protobuf:"varint,1,opt,name=NodeID" json:"NodeID"`
ClusterID uint64 `protobuf:"varint,2,opt,name=ClusterID" json:"ClusterID"`
XXX_unrecognized []byte `json:"-"`
}
......@@ -62,6 +80,10 @@ func (m *Metadata) Reset() { *m = Metadata{} }
func (m *Metadata) String() string { return proto.CompactTextString(m) }
func (*Metadata) ProtoMessage() {}
func init() {
proto.RegisterType((*Request)(nil), "etcdserverpb.Request")
proto.RegisterType((*Metadata)(nil), "etcdserverpb.Metadata")
}
func (m *Request) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -287,8 +309,12 @@ func (m *Request) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -301,6 +327,12 @@ func (m *Request) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Request: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -308,6 +340,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.ID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -324,6 +359,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -350,6 +388,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -376,6 +417,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -402,6 +446,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -419,6 +466,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -445,6 +495,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.PrevIndex = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -461,6 +514,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -479,6 +535,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.Expiration = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -495,6 +554,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -512,6 +574,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.Since = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -528,6 +593,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -545,6 +613,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -562,6 +633,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -579,6 +653,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.Time = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -595,6 +672,9 @@ func (m *Request) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -607,15 +687,7 @@ func (m *Request) Unmarshal(data []byte) error {
}
m.Stream = bool(v != 0)
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipEtcdserver(data[iNdEx:])
if err != nil {
return err
......@@ -631,14 +703,21 @@ func (m *Request) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Metadata) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -651,6 +730,12 @@ func (m *Metadata) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Metadata: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Metadata: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -658,6 +743,9 @@ func (m *Metadata) Unmarshal(data []byte) error {
}
m.NodeID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -674,6 +762,9 @@ func (m *Metadata) Unmarshal(data []byte) error {
}
m.ClusterID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -685,15 +776,7 @@ func (m *Metadata) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipEtcdserver(data[iNdEx:])
if err != nil {
return err
......@@ -709,6 +792,9 @@ func (m *Metadata) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipEtcdserver(data []byte) (n int, err error) {
......@@ -717,6 +803,9 @@ func skipEtcdserver(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -730,7 +819,10 @@ func skipEtcdserver(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -746,6 +838,9 @@ func skipEtcdserver(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -766,6 +861,9 @@ func skipEtcdserver(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEtcdserver
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -801,4 +899,5 @@ func skipEtcdserver(data []byte) (n int, err error) {
var (
ErrInvalidLengthEtcdserver = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowEtcdserver = fmt.Errorf("proto: integer overflow")
)
......@@ -4,15 +4,20 @@
package etcdserverpb
import proto "github.com/gogo/protobuf/proto"
import (
"fmt"
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// An InternalRaftRequest is the union of all requests which can be
// sent via raft.
......@@ -28,6 +33,9 @@ func (m *InternalRaftRequest) Reset() { *m = InternalRaftRequest{} }
func (m *InternalRaftRequest) String() string { return proto.CompactTextString(m) }
func (*InternalRaftRequest) ProtoMessage() {}
func init() {
proto.RegisterType((*InternalRaftRequest)(nil), "etcdserverpb.InternalRaftRequest")
}
func (m *InternalRaftRequest) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -162,48 +170,16 @@ func sovRaftInternal(x uint64) (n int) {
func sozRaftInternal(x uint64) (n int) {
return sovRaftInternal(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *InternalRaftRequest) GetValue() interface{} {
if this.V2 != nil {
return this.V2
}
if this.Range != nil {
return this.Range
}
if this.Put != nil {
return this.Put
}
if this.DeleteRange != nil {
return this.DeleteRange
}
if this.Txn != nil {
return this.Txn
}
return nil
}
func (this *InternalRaftRequest) SetValue(value interface{}) bool {
switch vt := value.(type) {
case *Request:
this.V2 = vt
case *RangeRequest:
this.Range = vt
case *PutRequest:
this.Put = vt
case *DeleteRangeRequest:
this.DeleteRange = vt
case *TxnRequest:
this.Txn = vt
default:
return false
}
return true
}
func (m *InternalRaftRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -216,6 +192,12 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: InternalRaftRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: InternalRaftRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -223,6 +205,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -253,6 +238,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -283,6 +271,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -313,6 +304,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -343,6 +337,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -368,15 +365,7 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaftInternal(data[iNdEx:])
if err != nil {
return err
......@@ -391,6 +380,9 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipRaftInternal(data []byte) (n int, err error) {
......@@ -399,6 +391,9 @@ func skipRaftInternal(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -412,7 +407,10 @@ func skipRaftInternal(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -428,6 +426,9 @@ func skipRaftInternal(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -448,6 +449,9 @@ func skipRaftInternal(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaftInternal
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -483,4 +487,5 @@ func skipRaftInternal(data []byte) (n int, err error) {
var (
ErrInvalidLengthRaftInternal = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRaftInternal = fmt.Errorf("proto: integer overflow")
)
......@@ -13,12 +13,9 @@ option (gogoproto.goproto_getters_all) = false;
// An InternalRaftRequest is the union of all requests which can be
// sent via raft.
message InternalRaftRequest {
option (gogoproto.onlyone) = true;
oneof value {
Request v2 = 1;
RangeRequest range = 2;
PutRequest put = 3;
DeleteRangeRequest delete_range = 4;
TxnRequest txn = 5;
}
}
......@@ -4,9 +4,14 @@
package etcdserverpb
import proto "github.com/gogo/protobuf/proto"
import (
"fmt"
proto "github.com/gogo/protobuf/proto"
)
import math "math"
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
import storagepb "github.com/coreos/etcd/storage/storagepb"
import (
......@@ -15,10 +20,11 @@ import (
)
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type Compare_CompareResult int32
......@@ -178,86 +184,404 @@ func (m *DeleteRangeResponse) GetHeader() *ResponseHeader {
}
type RequestUnion struct {
RequestRange *RangeRequest `protobuf:"bytes,1,opt,name=request_range" json:"request_range,omitempty"`
RequestPut *PutRequest `protobuf:"bytes,2,opt,name=request_put" json:"request_put,omitempty"`
RequestDeleteRange *DeleteRangeRequest `protobuf:"bytes,3,opt,name=request_delete_range" json:"request_delete_range,omitempty"`
// Types that are valid to be assigned to Request:
// *RequestUnion_RequestRange
// *RequestUnion_RequestPut
// *RequestUnion_RequestDeleteRange
Request isRequestUnion_Request `protobuf_oneof:"request"`
}
func (m *RequestUnion) Reset() { *m = RequestUnion{} }
func (m *RequestUnion) String() string { return proto.CompactTextString(m) }
func (*RequestUnion) ProtoMessage() {}
func (m *RequestUnion) GetRequestRange() *RangeRequest {
type isRequestUnion_Request interface {
isRequestUnion_Request()
MarshalTo([]byte) (int, error)
Size() int
}
type RequestUnion_RequestRange struct {
RequestRange *RangeRequest `protobuf:"bytes,1,opt,name=request_range,oneof"`
}
type RequestUnion_RequestPut struct {
RequestPut *PutRequest `protobuf:"bytes,2,opt,name=request_put,oneof"`
}
type RequestUnion_RequestDeleteRange struct {
RequestDeleteRange *DeleteRangeRequest `protobuf:"bytes,3,opt,name=request_delete_range,oneof"`
}
func (*RequestUnion_RequestRange) isRequestUnion_Request() {}
func (*RequestUnion_RequestPut) isRequestUnion_Request() {}
func (*RequestUnion_RequestDeleteRange) isRequestUnion_Request() {}
func (m *RequestUnion) GetRequest() isRequestUnion_Request {
if m != nil {
return m.RequestRange
return m.Request
}
return nil
}
func (m *RequestUnion) GetRequestRange() *RangeRequest {
if x, ok := m.GetRequest().(*RequestUnion_RequestRange); ok {
return x.RequestRange
}
return nil
}
func (m *RequestUnion) GetRequestPut() *PutRequest {
if m != nil {
return m.RequestPut
if x, ok := m.GetRequest().(*RequestUnion_RequestPut); ok {
return x.RequestPut
}
return nil
}
func (m *RequestUnion) GetRequestDeleteRange() *DeleteRangeRequest {
if m != nil {
return m.RequestDeleteRange
if x, ok := m.GetRequest().(*RequestUnion_RequestDeleteRange); ok {
return x.RequestDeleteRange
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*RequestUnion) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), []interface{}) {
return _RequestUnion_OneofMarshaler, _RequestUnion_OneofUnmarshaler, []interface{}{
(*RequestUnion_RequestRange)(nil),
(*RequestUnion_RequestPut)(nil),
(*RequestUnion_RequestDeleteRange)(nil),
}
}
func _RequestUnion_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*RequestUnion)
// request
switch x := m.Request.(type) {
case *RequestUnion_RequestRange:
_ = b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.RequestRange); err != nil {
return err
}
case *RequestUnion_RequestPut:
_ = b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.RequestPut); err != nil {
return err
}
case *RequestUnion_RequestDeleteRange:
_ = b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.RequestDeleteRange); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("RequestUnion.Request has unexpected type %T", x)
}
return nil
}
func _RequestUnion_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*RequestUnion)
switch tag {
case 1: // request.request_range
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(RangeRequest)
err := b.DecodeMessage(msg)
m.Request = &RequestUnion_RequestRange{msg}
return true, err
case 2: // request.request_put
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(PutRequest)
err := b.DecodeMessage(msg)
m.Request = &RequestUnion_RequestPut{msg}
return true, err
case 3: // request.request_delete_range
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(DeleteRangeRequest)
err := b.DecodeMessage(msg)
m.Request = &RequestUnion_RequestDeleteRange{msg}
return true, err
default:
return false, nil
}
}
type ResponseUnion struct {
ResponseRange *RangeResponse `protobuf:"bytes,1,opt,name=response_range" json:"response_range,omitempty"`
ResponsePut *PutResponse `protobuf:"bytes,2,opt,name=response_put" json:"response_put,omitempty"`
ResponseDeleteRange *DeleteRangeResponse `protobuf:"bytes,3,opt,name=response_delete_range" json:"response_delete_range,omitempty"`
// Types that are valid to be assigned to Response:
// *ResponseUnion_ResponseRange
// *ResponseUnion_ResponsePut
// *ResponseUnion_ResponseDeleteRange
Response isResponseUnion_Response `protobuf_oneof:"response"`
}
func (m *ResponseUnion) Reset() { *m = ResponseUnion{} }
func (m *ResponseUnion) String() string { return proto.CompactTextString(m) }
func (*ResponseUnion) ProtoMessage() {}
func (m *ResponseUnion) GetResponseRange() *RangeResponse {
type isResponseUnion_Response interface {
isResponseUnion_Response()
MarshalTo([]byte) (int, error)
Size() int
}
type ResponseUnion_ResponseRange struct {
ResponseRange *RangeResponse `protobuf:"bytes,1,opt,name=response_range,oneof"`
}
type ResponseUnion_ResponsePut struct {
ResponsePut *PutResponse `protobuf:"bytes,2,opt,name=response_put,oneof"`
}
type ResponseUnion_ResponseDeleteRange struct {
ResponseDeleteRange *DeleteRangeResponse `protobuf:"bytes,3,opt,name=response_delete_range,oneof"`
}
func (*ResponseUnion_ResponseRange) isResponseUnion_Response() {}
func (*ResponseUnion_ResponsePut) isResponseUnion_Response() {}
func (*ResponseUnion_ResponseDeleteRange) isResponseUnion_Response() {}
func (m *ResponseUnion) GetResponse() isResponseUnion_Response {
if m != nil {
return m.ResponseRange
return m.Response
}
return nil
}
func (m *ResponseUnion) GetResponseRange() *RangeResponse {
if x, ok := m.GetResponse().(*ResponseUnion_ResponseRange); ok {
return x.ResponseRange
}
return nil
}
func (m *ResponseUnion) GetResponsePut() *PutResponse {
if m != nil {
return m.ResponsePut
if x, ok := m.GetResponse().(*ResponseUnion_ResponsePut); ok {
return x.ResponsePut
}
return nil
}
func (m *ResponseUnion) GetResponseDeleteRange() *DeleteRangeResponse {
if m != nil {
return m.ResponseDeleteRange
if x, ok := m.GetResponse().(*ResponseUnion_ResponseDeleteRange); ok {
return x.ResponseDeleteRange
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*ResponseUnion) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), []interface{}) {
return _ResponseUnion_OneofMarshaler, _ResponseUnion_OneofUnmarshaler, []interface{}{
(*ResponseUnion_ResponseRange)(nil),
(*ResponseUnion_ResponsePut)(nil),
(*ResponseUnion_ResponseDeleteRange)(nil),
}
}
func _ResponseUnion_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*ResponseUnion)
// response
switch x := m.Response.(type) {
case *ResponseUnion_ResponseRange:
_ = b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.ResponseRange); err != nil {
return err
}
case *ResponseUnion_ResponsePut:
_ = b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.ResponsePut); err != nil {
return err
}
case *ResponseUnion_ResponseDeleteRange:
_ = b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.ResponseDeleteRange); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("ResponseUnion.Response has unexpected type %T", x)
}
return nil
}
func _ResponseUnion_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*ResponseUnion)
switch tag {
case 1: // response.response_range
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(RangeResponse)
err := b.DecodeMessage(msg)
m.Response = &ResponseUnion_ResponseRange{msg}
return true, err
case 2: // response.response_put
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(PutResponse)
err := b.DecodeMessage(msg)
m.Response = &ResponseUnion_ResponsePut{msg}
return true, err
case 3: // response.response_delete_range
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(DeleteRangeResponse)
err := b.DecodeMessage(msg)
m.Response = &ResponseUnion_ResponseDeleteRange{msg}
return true, err
default:
return false, nil
}
}
type Compare struct {
Result Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult" json:"result,omitempty"`
Target Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget" json:"target,omitempty"`
// key path
Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"`
// version of the given key
Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"`
// create revision of the given key
CreateRevision int64 `protobuf:"varint,5,opt,name=create_revision,proto3" json:"create_revision,omitempty"`
// last modified revision of the given key
ModRevision int64 `protobuf:"varint,6,opt,name=mod_revision,proto3" json:"mod_revision,omitempty"`
// value of the given key
Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"`
// Types that are valid to be assigned to TargetUnion:
// *Compare_Version
// *Compare_CreateRevision
// *Compare_ModRevision
// *Compare_Value
TargetUnion isCompare_TargetUnion `protobuf_oneof:"target_union"`
}
func (m *Compare) Reset() { *m = Compare{} }
func (m *Compare) String() string { return proto.CompactTextString(m) }
func (*Compare) ProtoMessage() {}
type isCompare_TargetUnion interface {
isCompare_TargetUnion()
MarshalTo([]byte) (int, error)
Size() int
}
type Compare_Version struct {
Version int64 `protobuf:"varint,4,opt,name=version,proto3,oneof"`
}
type Compare_CreateRevision struct {
CreateRevision int64 `protobuf:"varint,5,opt,name=create_revision,proto3,oneof"`
}
type Compare_ModRevision struct {
ModRevision int64 `protobuf:"varint,6,opt,name=mod_revision,proto3,oneof"`
}
type Compare_Value struct {
Value []byte `protobuf:"bytes,7,opt,name=value,proto3,oneof"`
}
func (*Compare_Version) isCompare_TargetUnion() {}
func (*Compare_CreateRevision) isCompare_TargetUnion() {}
func (*Compare_ModRevision) isCompare_TargetUnion() {}
func (*Compare_Value) isCompare_TargetUnion() {}
func (m *Compare) GetTargetUnion() isCompare_TargetUnion {
if m != nil {
return m.TargetUnion
}
return nil
}
func (m *Compare) GetVersion() int64 {
if x, ok := m.GetTargetUnion().(*Compare_Version); ok {
return x.Version
}
return 0
}
func (m *Compare) GetCreateRevision() int64 {
if x, ok := m.GetTargetUnion().(*Compare_CreateRevision); ok {
return x.CreateRevision
}
return 0
}
func (m *Compare) GetModRevision() int64 {
if x, ok := m.GetTargetUnion().(*Compare_ModRevision); ok {
return x.ModRevision
}
return 0
}
func (m *Compare) GetValue() []byte {
if x, ok := m.GetTargetUnion().(*Compare_Value); ok {
return x.Value
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Compare) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), []interface{}) {
return _Compare_OneofMarshaler, _Compare_OneofUnmarshaler, []interface{}{
(*Compare_Version)(nil),
(*Compare_CreateRevision)(nil),
(*Compare_ModRevision)(nil),
(*Compare_Value)(nil),
}
}
func _Compare_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Compare)
// target_union
switch x := m.TargetUnion.(type) {
case *Compare_Version:
_ = b.EncodeVarint(4<<3 | proto.WireVarint)
_ = b.EncodeVarint(uint64(x.Version))
case *Compare_CreateRevision:
_ = b.EncodeVarint(5<<3 | proto.WireVarint)
_ = b.EncodeVarint(uint64(x.CreateRevision))
case *Compare_ModRevision:
_ = b.EncodeVarint(6<<3 | proto.WireVarint)
_ = b.EncodeVarint(uint64(x.ModRevision))
case *Compare_Value:
_ = b.EncodeVarint(7<<3 | proto.WireBytes)
_ = b.EncodeRawBytes(x.Value)
case nil:
default:
return fmt.Errorf("Compare.TargetUnion has unexpected type %T", x)
}
return nil
}
func _Compare_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Compare)
switch tag {
case 4: // target_union.version
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.TargetUnion = &Compare_Version{int64(x)}
return true, err
case 5: // target_union.create_revision
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.TargetUnion = &Compare_CreateRevision{int64(x)}
return true, err
case 6: // target_union.mod_revision
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.TargetUnion = &Compare_ModRevision{int64(x)}
return true, err
case 7: // target_union.value
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeRawBytes(true)
m.TargetUnion = &Compare_Value{x}
return true, err
default:
return false, nil
}
}
// From google paxosdb paper:
// Our implementation hinges around a powerful primitive which we call MultiOp. All other database
// operations except for iteration are implemented as a single call to MultiOp. A MultiOp is applied atomically
......@@ -356,6 +680,20 @@ func (m *CompactionResponse) GetHeader() *ResponseHeader {
}
func init() {
proto.RegisterType((*ResponseHeader)(nil), "etcdserverpb.ResponseHeader")
proto.RegisterType((*RangeRequest)(nil), "etcdserverpb.RangeRequest")
proto.RegisterType((*RangeResponse)(nil), "etcdserverpb.RangeResponse")
proto.RegisterType((*PutRequest)(nil), "etcdserverpb.PutRequest")
proto.RegisterType((*PutResponse)(nil), "etcdserverpb.PutResponse")
proto.RegisterType((*DeleteRangeRequest)(nil), "etcdserverpb.DeleteRangeRequest")
proto.RegisterType((*DeleteRangeResponse)(nil), "etcdserverpb.DeleteRangeResponse")
proto.RegisterType((*RequestUnion)(nil), "etcdserverpb.RequestUnion")
proto.RegisterType((*ResponseUnion)(nil), "etcdserverpb.ResponseUnion")
proto.RegisterType((*Compare)(nil), "etcdserverpb.Compare")
proto.RegisterType((*TxnRequest)(nil), "etcdserverpb.TxnRequest")
proto.RegisterType((*TxnResponse)(nil), "etcdserverpb.TxnResponse")
proto.RegisterType((*CompactionRequest)(nil), "etcdserverpb.CompactionRequest")
proto.RegisterType((*CompactionResponse)(nil), "etcdserverpb.CompactionResponse")
proto.RegisterEnum("etcdserverpb.Compare_CompareResult", Compare_CompareResult_name, Compare_CompareResult_value)
proto.RegisterEnum("etcdserverpb.Compare_CompareTarget", Compare_CompareTarget_name, Compare_CompareTarget_value)
}
......@@ -465,9 +803,9 @@ func RegisterEtcdServer(s *grpc.Server, srv EtcdServer) {
s.RegisterService(&_Etcd_serviceDesc, srv)
}
func _Etcd_Range_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Etcd_Range_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(RangeRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(EtcdServer).Range(ctx, in)
......@@ -477,9 +815,9 @@ func _Etcd_Range_Handler(srv interface{}, ctx context.Context, codec grpc.Codec,
return out, nil
}
func _Etcd_Put_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Etcd_Put_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(PutRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(EtcdServer).Put(ctx, in)
......@@ -489,9 +827,9 @@ func _Etcd_Put_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, b
return out, nil
}
func _Etcd_DeleteRange_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Etcd_DeleteRange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(DeleteRangeRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(EtcdServer).DeleteRange(ctx, in)
......@@ -501,9 +839,9 @@ func _Etcd_DeleteRange_Handler(srv interface{}, ctx context.Context, codec grpc.
return out, nil
}
func _Etcd_Txn_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Etcd_Txn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(TxnRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(EtcdServer).Txn(ctx, in)
......@@ -513,9 +851,9 @@ func _Etcd_Txn_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, b
return out, nil
}
func _Etcd_Compact_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Etcd_Compact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(CompactionRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(EtcdServer).Compact(ctx, in)
......@@ -830,39 +1168,58 @@ func (m *RequestUnion) MarshalTo(data []byte) (int, error) {
_ = i
var l int
_ = l
if m.Request != nil {
nn4, err := m.Request.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += nn4
}
return i, nil
}
func (m *RequestUnion_RequestRange) MarshalTo(data []byte) (int, error) {
i := 0
if m.RequestRange != nil {
data[i] = 0xa
i++
i = encodeVarintRpc(data, i, uint64(m.RequestRange.Size()))
n4, err := m.RequestRange.MarshalTo(data[i:])
n5, err := m.RequestRange.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n4
i += n5
}
return i, nil
}
func (m *RequestUnion_RequestPut) MarshalTo(data []byte) (int, error) {
i := 0
if m.RequestPut != nil {
data[i] = 0x12
i++
i = encodeVarintRpc(data, i, uint64(m.RequestPut.Size()))
n5, err := m.RequestPut.MarshalTo(data[i:])
n6, err := m.RequestPut.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n5
i += n6
}
return i, nil
}
func (m *RequestUnion_RequestDeleteRange) MarshalTo(data []byte) (int, error) {
i := 0
if m.RequestDeleteRange != nil {
data[i] = 0x1a
i++
i = encodeVarintRpc(data, i, uint64(m.RequestDeleteRange.Size()))
n6, err := m.RequestDeleteRange.MarshalTo(data[i:])
n7, err := m.RequestDeleteRange.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n6
i += n7
}
return i, nil
}
func (m *ResponseUnion) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -878,39 +1235,58 @@ func (m *ResponseUnion) MarshalTo(data []byte) (int, error) {
_ = i
var l int
_ = l
if m.Response != nil {
nn8, err := m.Response.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += nn8
}
return i, nil
}
func (m *ResponseUnion_ResponseRange) MarshalTo(data []byte) (int, error) {
i := 0
if m.ResponseRange != nil {
data[i] = 0xa
i++
i = encodeVarintRpc(data, i, uint64(m.ResponseRange.Size()))
n7, err := m.ResponseRange.MarshalTo(data[i:])
n9, err := m.ResponseRange.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n7
i += n9
}
return i, nil
}
func (m *ResponseUnion_ResponsePut) MarshalTo(data []byte) (int, error) {
i := 0
if m.ResponsePut != nil {
data[i] = 0x12
i++
i = encodeVarintRpc(data, i, uint64(m.ResponsePut.Size()))
n8, err := m.ResponsePut.MarshalTo(data[i:])
n10, err := m.ResponsePut.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n8
i += n10
}
return i, nil
}
func (m *ResponseUnion_ResponseDeleteRange) MarshalTo(data []byte) (int, error) {
i := 0
if m.ResponseDeleteRange != nil {
data[i] = 0x1a
i++
i = encodeVarintRpc(data, i, uint64(m.ResponseDeleteRange.Size()))
n9, err := m.ResponseDeleteRange.MarshalTo(data[i:])
n11, err := m.ResponseDeleteRange.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n9
i += n11
}
return i, nil
}
func (m *Compare) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -944,32 +1320,47 @@ func (m *Compare) MarshalTo(data []byte) (int, error) {
i += copy(data[i:], m.Key)
}
}
if m.Version != 0 {
if m.TargetUnion != nil {
nn12, err := m.TargetUnion.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += nn12
}
return i, nil
}
func (m *Compare_Version) MarshalTo(data []byte) (int, error) {
i := 0
data[i] = 0x20
i++
i = encodeVarintRpc(data, i, uint64(m.Version))
}
if m.CreateRevision != 0 {
return i, nil
}
func (m *Compare_CreateRevision) MarshalTo(data []byte) (int, error) {
i := 0
data[i] = 0x28
i++
i = encodeVarintRpc(data, i, uint64(m.CreateRevision))
}
if m.ModRevision != 0 {
return i, nil
}
func (m *Compare_ModRevision) MarshalTo(data []byte) (int, error) {
i := 0
data[i] = 0x30
i++
i = encodeVarintRpc(data, i, uint64(m.ModRevision))
}
return i, nil
}
func (m *Compare_Value) MarshalTo(data []byte) (int, error) {
i := 0
if m.Value != nil {
if len(m.Value) > 0 {
data[i] = 0x3a
i++
i = encodeVarintRpc(data, i, uint64(len(m.Value)))
i += copy(data[i:], m.Value)
}
}
return i, nil
}
func (m *TxnRequest) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -1043,11 +1434,11 @@ func (m *TxnResponse) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
n10, err := m.Header.MarshalTo(data[i:])
n13, err := m.Header.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n10
i += n13
}
if m.Succeeded {
data[i] = 0x10
......@@ -1116,11 +1507,11 @@ func (m *CompactionResponse) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
n11, err := m.Header.MarshalTo(data[i:])
n14, err := m.Header.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n11
i += n14
}
return i, nil
}
......@@ -1276,39 +1667,75 @@ func (m *DeleteRangeResponse) Size() (n int) {
func (m *RequestUnion) Size() (n int) {
var l int
_ = l
if m.Request != nil {
n += m.Request.Size()
}
return n
}
func (m *RequestUnion_RequestRange) Size() (n int) {
var l int
_ = l
if m.RequestRange != nil {
l = m.RequestRange.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *RequestUnion_RequestPut) Size() (n int) {
var l int
_ = l
if m.RequestPut != nil {
l = m.RequestPut.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *RequestUnion_RequestDeleteRange) Size() (n int) {
var l int
_ = l
if m.RequestDeleteRange != nil {
l = m.RequestDeleteRange.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *ResponseUnion) Size() (n int) {
var l int
_ = l
if m.Response != nil {
n += m.Response.Size()
}
return n
}
func (m *ResponseUnion_ResponseRange) Size() (n int) {
var l int
_ = l
if m.ResponseRange != nil {
l = m.ResponseRange.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *ResponseUnion_ResponsePut) Size() (n int) {
var l int
_ = l
if m.ResponsePut != nil {
l = m.ResponsePut.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *ResponseUnion_ResponseDeleteRange) Size() (n int) {
var l int
_ = l
if m.ResponseDeleteRange != nil {
l = m.ResponseDeleteRange.Size()
n += 1 + l + sovRpc(uint64(l))
}
return n
}
func (m *Compare) Size() (n int) {
var l int
_ = l
......@@ -1324,24 +1751,39 @@ func (m *Compare) Size() (n int) {
n += 1 + l + sovRpc(uint64(l))
}
}
if m.Version != 0 {
n += 1 + sovRpc(uint64(m.Version))
if m.TargetUnion != nil {
n += m.TargetUnion.Size()
}
if m.CreateRevision != 0 {
return n
}
func (m *Compare_Version) Size() (n int) {
var l int
_ = l
n += 1 + sovRpc(uint64(m.Version))
return n
}
func (m *Compare_CreateRevision) Size() (n int) {
var l int
_ = l
n += 1 + sovRpc(uint64(m.CreateRevision))
}
if m.ModRevision != 0 {
return n
}
func (m *Compare_ModRevision) Size() (n int) {
var l int
_ = l
n += 1 + sovRpc(uint64(m.ModRevision))
}
return n
}
func (m *Compare_Value) Size() (n int) {
var l int
_ = l
if m.Value != nil {
l = len(m.Value)
if l > 0 {
n += 1 + l + sovRpc(uint64(l))
}
}
return n
}
func (m *TxnRequest) Size() (n int) {
var l int
_ = l
......@@ -1421,8 +1863,12 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1435,6 +1881,12 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ResponseHeader: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ResponseHeader: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1442,6 +1894,9 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1468,6 +1923,9 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
m.ClusterId = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1484,6 +1942,9 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
m.MemberId = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1500,6 +1961,9 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
m.Revision = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1516,6 +1980,9 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
m.RaftTerm = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1527,15 +1994,7 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -1550,14 +2009,21 @@ func (m *ResponseHeader) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *RangeRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1570,6 +2036,12 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RangeRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RangeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1577,6 +2049,9 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1594,7 +2069,10 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append([]byte{}, data[iNdEx:postIndex]...)
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -1602,6 +2080,9 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1619,7 +2100,10 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RangeEnd = append([]byte{}, data[iNdEx:postIndex]...)
m.RangeEnd = append(m.RangeEnd[:0], data[iNdEx:postIndex]...)
if m.RangeEnd == nil {
m.RangeEnd = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 0 {
......@@ -1627,6 +2111,9 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
m.Limit = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1643,6 +2130,9 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
m.Revision = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1654,15 +2144,7 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -1677,14 +2159,21 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *RangeResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1697,6 +2186,12 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RangeResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RangeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1704,6 +2199,9 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1734,6 +2232,9 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1762,6 +2263,9 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1774,15 +2278,7 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
m.More = bool(v != 0)
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -1797,14 +2293,21 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PutRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1817,6 +2320,12 @@ func (m *PutRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PutRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PutRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1824,6 +2333,9 @@ func (m *PutRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1841,7 +2353,10 @@ func (m *PutRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append([]byte{}, data[iNdEx:postIndex]...)
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -1849,6 +2364,9 @@ func (m *PutRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1866,18 +2384,13 @@ func (m *PutRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Value = append([]byte{}, data[iNdEx:postIndex]...)
m.Value = append(m.Value[:0], data[iNdEx:postIndex]...)
if m.Value == nil {
m.Value = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -1892,14 +2405,21 @@ func (m *PutRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PutResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1912,6 +2432,12 @@ func (m *PutResponse) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PutResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1919,6 +2445,9 @@ func (m *PutResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1944,15 +2473,7 @@ func (m *PutResponse) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -1967,14 +2488,21 @@ func (m *PutResponse) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1987,6 +2515,12 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: DeleteRangeRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: DeleteRangeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -1994,6 +2528,9 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2011,7 +2548,10 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append([]byte{}, data[iNdEx:postIndex]...)
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -2019,6 +2559,9 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2036,18 +2579,13 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RangeEnd = append([]byte{}, data[iNdEx:postIndex]...)
m.RangeEnd = append(m.RangeEnd[:0], data[iNdEx:postIndex]...)
if m.RangeEnd == nil {
m.RangeEnd = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2062,14 +2600,21 @@ func (m *DeleteRangeRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *DeleteRangeResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2082,6 +2627,12 @@ func (m *DeleteRangeResponse) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: DeleteRangeResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: DeleteRangeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2089,6 +2640,9 @@ func (m *DeleteRangeResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2114,15 +2668,7 @@ func (m *DeleteRangeResponse) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2137,14 +2683,21 @@ func (m *DeleteRangeResponse) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *RequestUnion) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2157,6 +2710,12 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RequestUnion: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RequestUnion: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2164,6 +2723,9 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2181,12 +2743,11 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.RequestRange == nil {
m.RequestRange = &RangeRequest{}
}
if err := m.RequestRange.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &RangeRequest{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Request = &RequestUnion_RequestRange{v}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -2194,6 +2755,9 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2211,12 +2775,11 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.RequestPut == nil {
m.RequestPut = &PutRequest{}
}
if err := m.RequestPut.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &PutRequest{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Request = &RequestUnion_RequestPut{v}
iNdEx = postIndex
case 3:
if wireType != 2 {
......@@ -2224,6 +2787,9 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2241,23 +2807,14 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.RequestDeleteRange == nil {
m.RequestDeleteRange = &DeleteRangeRequest{}
}
if err := m.RequestDeleteRange.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &DeleteRangeRequest{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Request = &RequestUnion_RequestDeleteRange{v}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2272,14 +2829,21 @@ func (m *RequestUnion) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ResponseUnion) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2292,6 +2856,12 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ResponseUnion: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ResponseUnion: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2299,6 +2869,9 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2316,12 +2889,11 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ResponseRange == nil {
m.ResponseRange = &RangeResponse{}
}
if err := m.ResponseRange.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &RangeResponse{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Response = &ResponseUnion_ResponseRange{v}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -2329,6 +2901,9 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2346,12 +2921,11 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ResponsePut == nil {
m.ResponsePut = &PutResponse{}
}
if err := m.ResponsePut.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &PutResponse{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Response = &ResponseUnion_ResponsePut{v}
iNdEx = postIndex
case 3:
if wireType != 2 {
......@@ -2359,6 +2933,9 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2376,23 +2953,14 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ResponseDeleteRange == nil {
m.ResponseDeleteRange = &DeleteRangeResponse{}
}
if err := m.ResponseDeleteRange.Unmarshal(data[iNdEx:postIndex]); err != nil {
v := &DeleteRangeResponse{}
if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
m.Response = &ResponseUnion_ResponseDeleteRange{v}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2407,14 +2975,21 @@ func (m *ResponseUnion) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Compare) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2427,6 +3002,12 @@ func (m *Compare) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Compare: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Compare: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -2434,6 +3015,9 @@ func (m *Compare) Unmarshal(data []byte) error {
}
m.Result = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2450,6 +3034,9 @@ func (m *Compare) Unmarshal(data []byte) error {
}
m.Target = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2466,6 +3053,9 @@ func (m *Compare) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2483,62 +3073,80 @@ func (m *Compare) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append([]byte{}, data[iNdEx:postIndex]...)
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
}
m.Version = 0
var v int64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.Version |= (int64(b) & 0x7F) << shift
v |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.TargetUnion = &Compare_Version{v}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CreateRevision", wireType)
}
m.CreateRevision = 0
var v int64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.CreateRevision |= (int64(b) & 0x7F) << shift
v |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.TargetUnion = &Compare_CreateRevision{v}
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ModRevision", wireType)
}
m.ModRevision = 0
var v int64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.ModRevision |= (int64(b) & 0x7F) << shift
v |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.TargetUnion = &Compare_ModRevision{v}
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2556,18 +3164,12 @@ func (m *Compare) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Value = append([]byte{}, data[iNdEx:postIndex]...)
v := make([]byte, postIndex-iNdEx)
copy(v, data[iNdEx:postIndex])
m.TargetUnion = &Compare_Value{v}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2582,14 +3184,21 @@ func (m *Compare) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TxnRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2602,6 +3211,12 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TxnRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TxnRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2609,6 +3224,9 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2637,6 +3255,9 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2665,6 +3286,9 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2688,15 +3312,7 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2711,14 +3327,21 @@ func (m *TxnRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TxnResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2731,6 +3354,12 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TxnResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TxnResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2738,6 +3367,9 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2768,6 +3400,9 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2785,6 +3420,9 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2808,15 +3446,7 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2831,14 +3461,21 @@ func (m *TxnResponse) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *CompactionRequest) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2851,6 +3488,12 @@ func (m *CompactionRequest) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: CompactionRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: CompactionRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -2858,6 +3501,9 @@ func (m *CompactionRequest) Unmarshal(data []byte) error {
}
m.Revision = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2869,15 +3515,7 @@ func (m *CompactionRequest) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2892,14 +3530,21 @@ func (m *CompactionRequest) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *CompactionResponse) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2912,6 +3557,12 @@ func (m *CompactionResponse) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: CompactionResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: CompactionResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -2919,6 +3570,9 @@ func (m *CompactionResponse) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -2944,15 +3598,7 @@ func (m *CompactionResponse) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:])
if err != nil {
return err
......@@ -2967,6 +3613,9 @@ func (m *CompactionResponse) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipRpc(data []byte) (n int, err error) {
......@@ -2975,6 +3624,9 @@ func skipRpc(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRpc
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -2988,7 +3640,10 @@ func skipRpc(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRpc
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -3004,6 +3659,9 @@ func skipRpc(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRpc
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -3024,6 +3682,9 @@ func skipRpc(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRpc
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -3059,4 +3720,5 @@ func skipRpc(data []byte) (n int, err error) {
var (
ErrInvalidLengthRpc = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRpc = fmt.Errorf("proto: integer overflow")
)
......@@ -174,12 +174,17 @@ type EtcdServer struct {
// configuration is considered static for the lifetime of the EtcdServer.
func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
st := store.New(StoreClusterPrefix, StoreKeysPrefix)
var w *wal.WAL
var n raft.Node
var s *raft.MemoryStorage
var id types.ID
var cl *cluster
if terr := fileutil.TouchDirAll(cfg.DataDir); terr != nil {
return nil, fmt.Errorf("cannot access data directory: %v", terr)
}
// Run the migrations.
dataVer, err := version.DetectDataDir(cfg.DataDir)
if err != nil {
......@@ -189,11 +194,6 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
return nil, err
}
err = os.MkdirAll(cfg.MemberDir(), privateDirMode)
if err != nil && err != os.ErrExist {
return nil, err
}
haveWAL := wal.Exist(cfg.WALDir())
ss := snap.New(cfg.SnapDir())
......@@ -255,10 +255,6 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
cfg.PrintWithInitial()
id, n, s, w = startNode(cfg, cl, cl.MemberIDs())
case haveWAL:
if err := fileutil.IsDirWriteable(cfg.DataDir); err != nil {
return nil, fmt.Errorf("cannot write to data directory: %v", err)
}
if err := fileutil.IsDirWriteable(cfg.MemberDir()); err != nil {
return nil, fmt.Errorf("cannot write to member directory: %v", err)
}
......@@ -295,6 +291,10 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
return nil, fmt.Errorf("unsupported bootstrap config")
}
if terr := fileutil.TouchDirAll(cfg.MemberDir()); terr != nil {
return nil, fmt.Errorf("cannot access member directory: %v", terr)
}
sstats := &stats.ServerStats{
Name: cfg.Name,
ID: id.String(),
......
......@@ -19,6 +19,7 @@ import (
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
dstorage "github.com/coreos/etcd/storage"
"github.com/coreos/etcd/storage/storagepb"
"github.com/gogo/protobuf/proto"
"golang.org/x/net/context"
)
......@@ -106,17 +107,24 @@ func doTxn(kv dstorage.KV, rt *pb.TxnRequest) *pb.TxnResponse {
}
func doUnion(kv dstorage.KV, union *pb.RequestUnion) *pb.ResponseUnion {
switch {
case union.RequestRange != nil:
return &pb.ResponseUnion{ResponseRange: doRange(kv, union.RequestRange)}
case union.RequestPut != nil:
return &pb.ResponseUnion{ResponsePut: doPut(kv, union.RequestPut)}
case union.RequestDeleteRange != nil:
return &pb.ResponseUnion{ResponseDeleteRange: doDeleteRange(kv, union.RequestDeleteRange)}
switch tv := union.Request.(type) {
case *pb.RequestUnion_RequestRange:
if tv.RequestRange != nil {
return &pb.ResponseUnion{Response: &pb.ResponseUnion_ResponseRange{ResponseRange: doRange(kv, tv.RequestRange)}}
}
case *pb.RequestUnion_RequestPut:
if tv.RequestPut != nil {
return &pb.ResponseUnion{Response: &pb.ResponseUnion_ResponsePut{ResponsePut: doPut(kv, tv.RequestPut)}}
}
case *pb.RequestUnion_RequestDeleteRange:
if tv.RequestDeleteRange != nil {
return &pb.ResponseUnion{Response: &pb.ResponseUnion_ResponseDeleteRange{ResponseDeleteRange: doDeleteRange(kv, tv.RequestDeleteRange)}}
}
default:
// empty union
return nil
}
return nil
}
func doCompare(kv dstorage.KV, c *pb.Compare) (int64, bool) {
......@@ -124,20 +132,35 @@ func doCompare(kv dstorage.KV, c *pb.Compare) (int64, bool) {
if err != nil {
return rev, false
}
ckv := ckvs[0]
var ckv storagepb.KeyValue
if len(ckvs) != 0 {
ckv = ckvs[0]
}
// -1 is less, 0 is equal, 1 is greater
var result int
switch c.Target {
case pb.Compare_VALUE:
result = bytes.Compare(ckv.Value, c.Value)
tv, _ := c.TargetUnion.(*pb.Compare_Value)
if tv != nil {
result = bytes.Compare(ckv.Value, tv.Value)
}
case pb.Compare_CREATE:
result = compareInt64(ckv.CreateRevision, c.CreateRevision)
tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision)
if tv != nil {
result = compareInt64(ckv.CreateRevision, tv.CreateRevision)
}
case pb.Compare_MOD:
result = compareInt64(ckv.ModRevision, c.ModRevision)
tv, _ := c.TargetUnion.(*pb.Compare_ModRevision)
if tv != nil {
result = compareInt64(ckv.ModRevision, tv.ModRevision)
}
case pb.Compare_VERSION:
result = compareInt64(ckv.Version, c.Version)
tv, _ := c.TargetUnion.(*pb.Compare_Version)
if tv != nil {
result = compareInt64(ckv.Version, tv.Version)
}
}
switch c.Result {
......
......@@ -25,6 +25,8 @@ import (
const (
privateFileMode = 0600
// owner can make/remove files inside the directory
privateDirMode = 0700
)
var (
......@@ -55,3 +57,13 @@ func ReadDir(dirpath string) ([]string, error) {
sort.Strings(names)
return names, nil
}
// TouchDirAll is simliar to os.MkdirAll. It creates directories with 0700 permission if any directory
// does not exists. TouchDirAll also ensures the given directory is writable.
func TouchDirAll(dir string) error {
err := os.MkdirAll(dir, privateDirMode)
if err != nil && err != os.ErrExist {
return err
}
return IsDirWriteable(dir)
}
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ioutil
import (
"io"
"os"
)
// WriteAndSyncFile behaviors just like ioutil.WriteFile in standard library
// but calls Sync before closing the file. WriteAndSyncFile guarantees the data
// is synced if there is no error returned.
func WriteAndSyncFile(filename string, data []byte, perm os.FileMode) error {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
}
n, err := f.Write(data)
if err == nil && n < len(data) {
err = io.ErrShortWrite
}
if err == nil {
err = f.Sync()
}
if err1 := f.Close(); err == nil {
err = err1
}
return err
}
......@@ -21,17 +21,19 @@ import (
"time"
)
type keepAliveConn interface {
SetKeepAlive(bool) error
SetKeepAlivePeriod(d time.Duration) error
}
// NewKeepAliveListener returns a listener that listens on the given address.
// Be careful when wrap around KeepAliveListener with another Listener if TLSInfo is not nil.
// Some pkgs (like go/http) might expect Listener to return TLSConn type to start TLS handshake.
// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
func NewKeepAliveListener(addr string, scheme string, info TLSInfo) (net.Listener, error) {
l, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
func NewKeepAliveListener(l net.Listener, scheme string, info TLSInfo) (net.Listener, error) {
if scheme == "https" {
if info.Empty() {
return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", scheme+"://"+addr)
return nil, fmt.Errorf("cannot listen on TLS for given listener: KeyFile and CertFile are not presented")
}
cfg, err := info.ServerConfig()
if err != nil {
......@@ -53,13 +55,13 @@ func (kln *keepaliveListener) Accept() (net.Conn, error) {
if err != nil {
return nil, err
}
tcpc := c.(*net.TCPConn)
kac := c.(keepAliveConn)
// detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
// default on linux: 30 + 8 * 30
// default on osx: 30 + 8 * 75
tcpc.SetKeepAlive(true)
tcpc.SetKeepAlivePeriod(30 * time.Second)
return tcpc, nil
kac.SetKeepAlive(true)
kac.SetKeepAlivePeriod(30 * time.Second)
return c, nil
}
// A tlsKeepaliveListener implements a network listener (net.Listener) for TLS connections.
......@@ -75,12 +77,12 @@ func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) {
if err != nil {
return
}
tcpc := c.(*net.TCPConn)
kac := c.(keepAliveConn)
// detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
// default on linux: 30 + 8 * 30
// default on osx: 30 + 8 * 75
tcpc.SetKeepAlive(true)
tcpc.SetKeepAlivePeriod(30 * time.Second)
kac.SetKeepAlive(true)
kac.SetKeepAlivePeriod(30 * time.Second)
c = tls.Server(c, l.config)
return
}
......
// Copyright 2013 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 netutil provides network utility functions, complementing the more
// common ones in the net package.
package transport
import (
"errors"
"net"
"sync"
"time"
)
var (
ErrNotTCP = errors.New("only tcp connections have keepalive")
)
// LimitListener returns a Listener that accepts at most n simultaneous
// connections from the provided Listener.
func LimitListener(l net.Listener, n int) net.Listener {
return &limitListener{l, make(chan struct{}, n)}
}
type limitListener struct {
net.Listener
sem chan struct{}
}
func (l *limitListener) acquire() { l.sem <- struct{}{} }
func (l *limitListener) release() { <-l.sem }
func (l *limitListener) Accept() (net.Conn, error) {
l.acquire()
c, err := l.Listener.Accept()
if err != nil {
l.release()
return nil, err
}
return &limitListenerConn{Conn: c, release: l.release}, nil
}
type limitListenerConn struct {
net.Conn
releaseOnce sync.Once
release func()
}
func (l *limitListenerConn) Close() error {
err := l.Conn.Close()
l.releaseOnce.Do(l.release)
return err
}
func (l *limitListenerConn) SetKeepAlive(doKeepAlive bool) error {
tcpc, ok := l.Conn.(*net.TCPConn)
if !ok {
return ErrNotTCP
}
return tcpc.SetKeepAlive(doKeepAlive)
}
func (l *limitListenerConn) SetKeepAlivePeriod(d time.Duration) error {
tcpc, ok := l.Conn.(*net.TCPConn)
if !ok {
return ErrNotTCP
}
return tcpc.SetKeepAlivePeriod(d)
}
......@@ -19,16 +19,19 @@
*/
package raftpb
import proto "github.com/gogo/protobuf/proto"
import math "math"
import (
"fmt"
proto "github.com/gogo/protobuf/proto"
)
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type EntryType int32
......@@ -164,10 +167,10 @@ func (x *ConfChangeType) UnmarshalJSON(data []byte) error {
}
type Entry struct {
Type EntryType `protobuf:"varint,1,opt,enum=raftpb.EntryType" json:"Type"`
Term uint64 `protobuf:"varint,2,opt" json:"Term"`
Index uint64 `protobuf:"varint,3,opt" json:"Index"`
Data []byte `protobuf:"bytes,4,opt" json:"Data,omitempty"`
Type EntryType `protobuf:"varint,1,opt,name=Type,enum=raftpb.EntryType" json:"Type"`
Term uint64 `protobuf:"varint,2,opt,name=Term" json:"Term"`
Index uint64 `protobuf:"varint,3,opt,name=Index" json:"Index"`
Data []byte `protobuf:"bytes,4,opt,name=Data" json:"Data,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
......@@ -236,10 +239,10 @@ func (m *ConfState) String() string { return proto.CompactTextString(m) }
func (*ConfState) ProtoMessage() {}
type ConfChange struct {
ID uint64 `protobuf:"varint,1,opt" json:"ID"`
Type ConfChangeType `protobuf:"varint,2,opt,enum=raftpb.ConfChangeType" json:"Type"`
NodeID uint64 `protobuf:"varint,3,opt" json:"NodeID"`
Context []byte `protobuf:"bytes,4,opt" json:"Context,omitempty"`
ID uint64 `protobuf:"varint,1,opt,name=ID" json:"ID"`
Type ConfChangeType `protobuf:"varint,2,opt,name=Type,enum=raftpb.ConfChangeType" json:"Type"`
NodeID uint64 `protobuf:"varint,3,opt,name=NodeID" json:"NodeID"`
Context []byte `protobuf:"bytes,4,opt,name=Context" json:"Context,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
......@@ -248,6 +251,13 @@ func (m *ConfChange) String() string { return proto.CompactTextString(m) }
func (*ConfChange) ProtoMessage() {}
func init() {
proto.RegisterType((*Entry)(nil), "raftpb.Entry")
proto.RegisterType((*SnapshotMetadata)(nil), "raftpb.SnapshotMetadata")
proto.RegisterType((*Snapshot)(nil), "raftpb.Snapshot")
proto.RegisterType((*Message)(nil), "raftpb.Message")
proto.RegisterType((*HardState)(nil), "raftpb.HardState")
proto.RegisterType((*ConfState)(nil), "raftpb.ConfState")
proto.RegisterType((*ConfChange)(nil), "raftpb.ConfChange")
proto.RegisterEnum("raftpb.EntryType", EntryType_name, EntryType_value)
proto.RegisterEnum("raftpb.MessageType", MessageType_name, MessageType_value)
proto.RegisterEnum("raftpb.ConfChangeType", ConfChangeType_name, ConfChangeType_value)
......@@ -681,8 +691,12 @@ func (m *Entry) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -695,6 +709,12 @@ func (m *Entry) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Entry: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Entry: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -702,6 +722,9 @@ func (m *Entry) Unmarshal(data []byte) error {
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -718,6 +741,9 @@ func (m *Entry) Unmarshal(data []byte) error {
}
m.Term = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -734,6 +760,9 @@ func (m *Entry) Unmarshal(data []byte) error {
}
m.Index = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -750,6 +779,9 @@ func (m *Entry) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -767,18 +799,13 @@ func (m *Entry) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append([]byte{}, data[iNdEx:postIndex]...)
m.Data = append(m.Data[:0], data[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -794,14 +821,21 @@ func (m *Entry) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *SnapshotMetadata) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -814,6 +848,12 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: SnapshotMetadata: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SnapshotMetadata: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -821,6 +861,9 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -848,6 +891,9 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
m.Index = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -864,6 +910,9 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
m.Term = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -875,15 +924,7 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -899,14 +940,21 @@ func (m *SnapshotMetadata) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Snapshot) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -919,6 +967,12 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Snapshot: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -926,6 +980,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -943,7 +1000,10 @@ func (m *Snapshot) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append([]byte{}, data[iNdEx:postIndex]...)
m.Data = append(m.Data[:0], data[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
......@@ -951,6 +1011,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -973,15 +1036,7 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -997,14 +1052,21 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Message) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1017,6 +1079,12 @@ func (m *Message) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Message: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -1024,6 +1092,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1040,6 +1111,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.To = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1056,6 +1130,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.From = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1072,6 +1149,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.Term = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1088,6 +1168,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.LogTerm = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1104,6 +1187,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.Index = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1120,6 +1206,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1148,6 +1237,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.Commit = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1164,6 +1256,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1191,6 +1286,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1208,6 +1306,9 @@ func (m *Message) Unmarshal(data []byte) error {
}
m.RejectHint = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1219,15 +1320,7 @@ func (m *Message) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -1243,14 +1336,21 @@ func (m *Message) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *HardState) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1263,6 +1363,12 @@ func (m *HardState) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: HardState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: HardState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -1270,6 +1376,9 @@ func (m *HardState) Unmarshal(data []byte) error {
}
m.Term = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1286,6 +1395,9 @@ func (m *HardState) Unmarshal(data []byte) error {
}
m.Vote = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1302,6 +1414,9 @@ func (m *HardState) Unmarshal(data []byte) error {
}
m.Commit = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1313,15 +1428,7 @@ func (m *HardState) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -1337,14 +1444,21 @@ func (m *HardState) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ConfState) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1357,6 +1471,12 @@ func (m *ConfState) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ConfState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ConfState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -1364,6 +1484,9 @@ func (m *ConfState) Unmarshal(data []byte) error {
}
var v uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1376,15 +1499,7 @@ func (m *ConfState) Unmarshal(data []byte) error {
}
m.Nodes = append(m.Nodes, v)
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -1400,14 +1515,21 @@ func (m *ConfState) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ConfChange) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1420,6 +1542,12 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ConfChange: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ConfChange: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -1427,6 +1555,9 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
m.ID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1443,6 +1574,9 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1459,6 +1593,9 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
m.NodeID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1475,6 +1612,9 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRaft
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -1492,18 +1632,13 @@ func (m *ConfChange) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Context = append([]byte{}, data[iNdEx:postIndex]...)
m.Context = append(m.Context[:0], data[iNdEx:postIndex]...)
if m.Context == nil {
m.Context = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRaft(data[iNdEx:])
if err != nil {
return err
......@@ -1519,6 +1654,9 @@ func (m *ConfChange) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipRaft(data []byte) (n int, err error) {
......@@ -1527,6 +1665,9 @@ func skipRaft(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaft
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -1540,7 +1681,10 @@ func skipRaft(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaft
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -1556,6 +1700,9 @@ func skipRaft(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaft
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -1576,6 +1723,9 @@ func skipRaft(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRaft
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -1611,4 +1761,5 @@ func skipRaft(data []byte) (n int, err error) {
var (
ErrInvalidLengthRaft = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRaft = fmt.Errorf("proto: integer overflow")
)
......@@ -13,16 +13,19 @@
*/
package snappb
import proto "github.com/gogo/protobuf/proto"
import math "math"
import (
"fmt"
proto "github.com/gogo/protobuf/proto"
)
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type Snapshot struct {
......@@ -35,6 +38,9 @@ func (m *Snapshot) Reset() { *m = Snapshot{} }
func (m *Snapshot) String() string { return proto.CompactTextString(m) }
func (*Snapshot) ProtoMessage() {}
func init() {
proto.RegisterType((*Snapshot)(nil), "snappb.snapshot")
}
func (m *Snapshot) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -123,8 +129,12 @@ func (m *Snapshot) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSnap
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -137,6 +147,12 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: snapshot: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -144,6 +160,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
m.Crc = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSnap
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -160,6 +179,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSnap
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -177,18 +199,13 @@ func (m *Snapshot) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append([]byte{}, data[iNdEx:postIndex]...)
m.Data = append(m.Data[:0], data[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipSnap(data[iNdEx:])
if err != nil {
return err
......@@ -204,6 +221,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipSnap(data []byte) (n int, err error) {
......@@ -212,6 +232,9 @@ func skipSnap(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSnap
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -225,7 +248,10 @@ func skipSnap(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSnap
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -241,6 +267,9 @@ func skipSnap(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSnap
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -261,6 +290,9 @@ func skipSnap(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSnap
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -296,4 +328,5 @@ func skipSnap(data []byte) (n int, err error) {
var (
ErrInvalidLengthSnap = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowSnap = fmt.Errorf("proto: integer overflow")
)
......@@ -14,15 +14,20 @@
*/
package storagepb
import proto "github.com/gogo/protobuf/proto"
import (
"fmt"
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type Event_EventType int32
......@@ -76,6 +81,8 @@ func (m *Event) String() string { return proto.CompactTextString(m) }
func (*Event) ProtoMessage() {}
func init() {
proto.RegisterType((*KeyValue)(nil), "storagepb.KeyValue")
proto.RegisterType((*Event)(nil), "storagepb.Event")
proto.RegisterEnum("storagepb.Event_EventType", Event_EventType_name, Event_EventType_value)
}
func (m *KeyValue) Marshal() (data []byte, err error) {
......@@ -244,8 +251,12 @@ func (m *KeyValue) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -258,6 +269,12 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: KeyValue: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: KeyValue: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
......@@ -265,6 +282,9 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -282,7 +302,10 @@ func (m *KeyValue) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append([]byte{}, data[iNdEx:postIndex]...)
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 0 {
......@@ -290,6 +313,9 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
m.CreateRevision = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -306,6 +332,9 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
m.ModRevision = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -322,6 +351,9 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
m.Version = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -338,6 +370,9 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -355,18 +390,13 @@ func (m *KeyValue) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Value = append([]byte{}, data[iNdEx:postIndex]...)
m.Value = append(m.Value[:0], data[iNdEx:postIndex]...)
if m.Value == nil {
m.Value = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipKv(data[iNdEx:])
if err != nil {
return err
......@@ -381,14 +411,21 @@ func (m *KeyValue) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Event) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -401,6 +438,12 @@ func (m *Event) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Event: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -408,6 +451,9 @@ func (m *Event) Unmarshal(data []byte) error {
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -424,6 +470,9 @@ func (m *Event) Unmarshal(data []byte) error {
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKv
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -449,15 +498,7 @@ func (m *Event) Unmarshal(data []byte) error {
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipKv(data[iNdEx:])
if err != nil {
return err
......@@ -472,6 +513,9 @@ func (m *Event) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipKv(data []byte) (n int, err error) {
......@@ -480,6 +524,9 @@ func skipKv(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKv
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -493,7 +540,10 @@ func skipKv(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKv
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -509,6 +559,9 @@ func skipKv(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKv
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -529,6 +582,9 @@ func skipKv(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKv
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -564,4 +620,5 @@ func skipKv(data []byte) (n int, err error) {
var (
ErrInvalidLengthKv = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowKv = fmt.Errorf("proto: integer overflow")
)
......@@ -27,7 +27,7 @@ import (
var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "2.1.0"
Version = "2.2.2+git"
Version = "2.2.5"
// Git SHA Value will be set during build
GitSHA = "Not provided (use ./build instead of go build)"
......
......@@ -14,16 +14,19 @@
*/
package walpb
import proto "github.com/gogo/protobuf/proto"
import math "math"
import (
"fmt"
// discarding unused import gogoproto "github.com/coreos/etcd/Godeps/_workspace/src/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
import math "math"
import io "io"
import fmt "fmt"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type Record struct {
......@@ -47,6 +50,10 @@ func (m *Snapshot) Reset() { *m = Snapshot{} }
func (m *Snapshot) String() string { return proto.CompactTextString(m) }
func (*Snapshot) ProtoMessage() {}
func init() {
proto.RegisterType((*Record)(nil), "walpb.Record")
proto.RegisterType((*Snapshot)(nil), "walpb.Snapshot")
}
func (m *Record) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
......@@ -177,8 +184,12 @@ func (m *Record) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -191,6 +202,12 @@ func (m *Record) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Record: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Record: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -198,6 +215,9 @@ func (m *Record) Unmarshal(data []byte) error {
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -214,6 +234,9 @@ func (m *Record) Unmarshal(data []byte) error {
}
m.Crc = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -230,6 +253,9 @@ func (m *Record) Unmarshal(data []byte) error {
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -247,18 +273,13 @@ func (m *Record) Unmarshal(data []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append([]byte{}, data[iNdEx:postIndex]...)
m.Data = append(m.Data[:0], data[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRecord(data[iNdEx:])
if err != nil {
return err
......@@ -274,14 +295,21 @@ func (m *Record) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Snapshot) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -294,6 +322,12 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Snapshot: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
......@@ -301,6 +335,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
m.Index = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -317,6 +354,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
m.Term = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
......@@ -328,15 +368,7 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
}
default:
var sizeOfWire int
for {
sizeOfWire++
wire >>= 7
if wire == 0 {
break
}
}
iNdEx -= sizeOfWire
iNdEx = preIndex
skippy, err := skipRecord(data[iNdEx:])
if err != nil {
return err
......@@ -352,6 +384,9 @@ func (m *Snapshot) Unmarshal(data []byte) error {
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipRecord(data []byte) (n int, err error) {
......@@ -360,6 +395,9 @@ func skipRecord(data []byte) (n int, err error) {
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRecord
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -373,7 +411,10 @@ func skipRecord(data []byte) (n int, err error) {
wireType := int(wire & 0x7)
switch wireType {
case 0:
for {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRecord
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -389,6 +430,9 @@ func skipRecord(data []byte) (n int, err error) {
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRecord
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -409,6 +453,9 @@ func skipRecord(data []byte) (n int, err error) {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRecord
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
......@@ -444,4 +491,5 @@ func skipRecord(data []byte) (n int, err error) {
var (
ErrInvalidLengthRecord = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRecord = fmt.Errorf("proto: integer overflow")
)
......@@ -200,3 +200,28 @@ Apache License
See the License for the specific language governing permissions and
limitations under the License.
Third Party Sources Bundled
This project includes code derived from the MIT licensed naegelejd/go-acl
project. Here's a copy of its license:
Copyright (c) 2015 Joseph Naegele
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
......@@ -2,8 +2,6 @@
The API defined here is proposed, experimental, and (for now) subject to change at any time.
**Do not use it.**
If you think you want to use it, or for any other queries, contact <rkt-dev@googlegroups.com> or file an [issue](https://github.com/coreos/rkt/issues/new)
For more information, see:
......
......@@ -51,6 +51,10 @@ 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
// ImageType defines the supported image type.
type ImageType int32
......@@ -77,6 +81,7 @@ var ImageType_value = map[string]int32{
func (x ImageType) String() string {
return proto.EnumName(ImageType_name, int32(x))
}
func (ImageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// AppState defines the possible states of the app.
type AppState int32
......@@ -101,6 +106,7 @@ var AppState_value = map[string]int32{
func (x AppState) String() string {
return proto.EnumName(AppState_name, int32(x))
}
func (AppState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
// PodState defines the possible states of the pod.
// See https://github.com/coreos/rkt/blob/master/Documentation/devel/pod-lifecycle.md for a detailed
......@@ -148,6 +154,7 @@ var PodState_value = map[string]int32{
func (x PodState) String() string {
return proto.EnumName(PodState_name, int32(x))
}
func (PodState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
// EventType defines the type of the events that will be received via ListenEvents().
type EventType int32
......@@ -196,6 +203,7 @@ var EventType_value = map[string]int32{
func (x EventType) String() string {
return proto.EnumName(EventType_name, int32(x))
}
func (EventType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
// ImageFormat defines the format of the image.
type ImageFormat struct {
......@@ -208,6 +216,7 @@ type ImageFormat struct {
func (m *ImageFormat) Reset() { *m = ImageFormat{} }
func (m *ImageFormat) String() string { return proto.CompactTextString(m) }
func (*ImageFormat) ProtoMessage() {}
func (*ImageFormat) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// Image describes the image's information.
type Image struct {
......@@ -235,6 +244,7 @@ type Image struct {
func (m *Image) Reset() { *m = Image{} }
func (m *Image) String() string { return proto.CompactTextString(m) }
func (*Image) ProtoMessage() {}
func (*Image) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Image) GetBaseFormat() *ImageFormat {
if m != nil {
......@@ -263,6 +273,7 @@ type Network struct {
func (m *Network) Reset() { *m = Network{} }
func (m *Network) String() string { return proto.CompactTextString(m) }
func (*Network) ProtoMessage() {}
func (*Network) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
// App describes the information of an app that's running in a pod.
type App struct {
......@@ -283,6 +294,7 @@ type App struct {
func (m *App) Reset() { *m = App{} }
func (m *App) String() string { return proto.CompactTextString(m) }
func (*App) ProtoMessage() {}
func (*App) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *App) GetImage() *Image {
if m != nil {
......@@ -330,6 +342,7 @@ type Pod struct {
func (m *Pod) Reset() { *m = Pod{} }
func (m *Pod) String() string { return proto.CompactTextString(m) }
func (*Pod) ProtoMessage() {}
func (*Pod) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *Pod) GetApps() []*App {
if m != nil {
......@@ -354,7 +367,7 @@ func (m *Pod) GetAnnotations() []*KeyValue {
type KeyValue struct {
// Key part of the key-value pair.
Key string `protobuf:"bytes,1,opt" json:"Key,omitempty"`
Key string `protobuf:"bytes,1,opt,name=Key" json:"Key,omitempty"`
// Value part of the key-value pair.
Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
}
......@@ -362,6 +375,7 @@ type KeyValue struct {
func (m *KeyValue) Reset() { *m = KeyValue{} }
func (m *KeyValue) String() string { return proto.CompactTextString(m) }
func (*KeyValue) ProtoMessage() {}
func (*KeyValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
// PodFilter defines the condition that the returned pods need to satisfy in ListPods().
// The conditions are combined by 'AND', and different filters are combined by 'OR'.
......@@ -383,6 +397,7 @@ type PodFilter struct {
func (m *PodFilter) Reset() { *m = PodFilter{} }
func (m *PodFilter) String() string { return proto.CompactTextString(m) }
func (*PodFilter) ProtoMessage() {}
func (*PodFilter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *PodFilter) GetAnnotations() []*KeyValue {
if m != nil {
......@@ -413,11 +428,14 @@ type ImageFilter struct {
ImportedBefore int64 `protobuf:"varint,7,opt,name=imported_before" json:"imported_before,omitempty"`
// If not empty, the images that have all of the annotations will be returned.
Annotations []*KeyValue `protobuf:"bytes,8,rep,name=annotations" json:"annotations,omitempty"`
// If not empty, the images that have any of the exact full names will be returned.
FullNames []string `protobuf:"bytes,9,rep,name=full_names" json:"full_names,omitempty"`
}
func (m *ImageFilter) Reset() { *m = ImageFilter{} }
func (m *ImageFilter) String() string { return proto.CompactTextString(m) }
func (*ImageFilter) ProtoMessage() {}
func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *ImageFilter) GetLabels() []*KeyValue {
if m != nil {
......@@ -446,6 +464,7 @@ type Info struct {
func (m *Info) Reset() { *m = Info{} }
func (m *Info) String() string { return proto.CompactTextString(m) }
func (*Info) ProtoMessage() {}
func (*Info) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
// Event describes the events that will be received via ListenEvents().
type Event struct {
......@@ -469,6 +488,7 @@ type Event struct {
func (m *Event) Reset() { *m = Event{} }
func (m *Event) String() string { return proto.CompactTextString(m) }
func (*Event) ProtoMessage() {}
func (*Event) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *Event) GetData() []*KeyValue {
if m != nil {
......@@ -498,6 +518,7 @@ type EventFilter struct {
func (m *EventFilter) Reset() { *m = EventFilter{} }
func (m *EventFilter) String() string { return proto.CompactTextString(m) }
func (*EventFilter) ProtoMessage() {}
func (*EventFilter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
// Request for GetInfo().
type GetInfoRequest struct {
......@@ -506,6 +527,7 @@ type GetInfoRequest struct {
func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} }
func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) }
func (*GetInfoRequest) ProtoMessage() {}
func (*GetInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
// Response for GetInfo().
type GetInfoResponse struct {
......@@ -515,6 +537,7 @@ type GetInfoResponse struct {
func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} }
func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) }
func (*GetInfoResponse) ProtoMessage() {}
func (*GetInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *GetInfoResponse) GetInfo() *Info {
if m != nil {
......@@ -532,6 +555,7 @@ type ListPodsRequest struct {
func (m *ListPodsRequest) Reset() { *m = ListPodsRequest{} }
func (m *ListPodsRequest) String() string { return proto.CompactTextString(m) }
func (*ListPodsRequest) ProtoMessage() {}
func (*ListPodsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
func (m *ListPodsRequest) GetFilters() []*PodFilter {
if m != nil {
......@@ -548,6 +572,7 @@ type ListPodsResponse struct {
func (m *ListPodsResponse) Reset() { *m = ListPodsResponse{} }
func (m *ListPodsResponse) String() string { return proto.CompactTextString(m) }
func (*ListPodsResponse) ProtoMessage() {}
func (*ListPodsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func (m *ListPodsResponse) GetPods() []*Pod {
if m != nil {
......@@ -565,6 +590,7 @@ type InspectPodRequest struct {
func (m *InspectPodRequest) Reset() { *m = InspectPodRequest{} }
func (m *InspectPodRequest) String() string { return proto.CompactTextString(m) }
func (*InspectPodRequest) ProtoMessage() {}
func (*InspectPodRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
// Response for InspectPod().
type InspectPodResponse struct {
......@@ -574,6 +600,7 @@ type InspectPodResponse struct {
func (m *InspectPodResponse) Reset() { *m = InspectPodResponse{} }
func (m *InspectPodResponse) String() string { return proto.CompactTextString(m) }
func (*InspectPodResponse) ProtoMessage() {}
func (*InspectPodResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
func (m *InspectPodResponse) GetPod() *Pod {
if m != nil {
......@@ -591,6 +618,7 @@ type ListImagesRequest struct {
func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} }
func (m *ListImagesRequest) String() string { return proto.CompactTextString(m) }
func (*ListImagesRequest) ProtoMessage() {}
func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
func (m *ListImagesRequest) GetFilters() []*ImageFilter {
if m != nil {
......@@ -607,6 +635,7 @@ type ListImagesResponse struct {
func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} }
func (m *ListImagesResponse) String() string { return proto.CompactTextString(m) }
func (*ListImagesResponse) ProtoMessage() {}
func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
func (m *ListImagesResponse) GetImages() []*Image {
if m != nil {
......@@ -623,6 +652,7 @@ type InspectImageRequest struct {
func (m *InspectImageRequest) Reset() { *m = InspectImageRequest{} }
func (m *InspectImageRequest) String() string { return proto.CompactTextString(m) }
func (*InspectImageRequest) ProtoMessage() {}
func (*InspectImageRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
// Response for InspectImage().
type InspectImageResponse struct {
......@@ -632,6 +662,7 @@ type InspectImageResponse struct {
func (m *InspectImageResponse) Reset() { *m = InspectImageResponse{} }
func (m *InspectImageResponse) String() string { return proto.CompactTextString(m) }
func (*InspectImageResponse) ProtoMessage() {}
func (*InspectImageResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
func (m *InspectImageResponse) GetImage() *Image {
if m != nil {
......@@ -648,6 +679,7 @@ type ListenEventsRequest struct {
func (m *ListenEventsRequest) Reset() { *m = ListenEventsRequest{} }
func (m *ListenEventsRequest) String() string { return proto.CompactTextString(m) }
func (*ListenEventsRequest) ProtoMessage() {}
func (*ListenEventsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} }
func (m *ListenEventsRequest) GetFilter() *EventFilter {
if m != nil {
......@@ -665,6 +697,7 @@ type ListenEventsResponse struct {
func (m *ListenEventsResponse) Reset() { *m = ListenEventsResponse{} }
func (m *ListenEventsResponse) String() string { return proto.CompactTextString(m) }
func (*ListenEventsResponse) ProtoMessage() {}
func (*ListenEventsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} }
func (m *ListenEventsResponse) GetEvents() []*Event {
if m != nil {
......@@ -697,6 +730,7 @@ type GetLogsRequest struct {
func (m *GetLogsRequest) Reset() { *m = GetLogsRequest{} }
func (m *GetLogsRequest) String() string { return proto.CompactTextString(m) }
func (*GetLogsRequest) ProtoMessage() {}
func (*GetLogsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} }
// Response for GetLogs().
type GetLogsResponse struct {
......@@ -707,8 +741,34 @@ type GetLogsResponse struct {
func (m *GetLogsResponse) Reset() { *m = GetLogsResponse{} }
func (m *GetLogsResponse) String() string { return proto.CompactTextString(m) }
func (*GetLogsResponse) ProtoMessage() {}
func (*GetLogsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} }
func init() {
proto.RegisterType((*ImageFormat)(nil), "v1alpha.ImageFormat")
proto.RegisterType((*Image)(nil), "v1alpha.Image")
proto.RegisterType((*Network)(nil), "v1alpha.Network")
proto.RegisterType((*App)(nil), "v1alpha.App")
proto.RegisterType((*Pod)(nil), "v1alpha.Pod")
proto.RegisterType((*KeyValue)(nil), "v1alpha.KeyValue")
proto.RegisterType((*PodFilter)(nil), "v1alpha.PodFilter")
proto.RegisterType((*ImageFilter)(nil), "v1alpha.ImageFilter")
proto.RegisterType((*Info)(nil), "v1alpha.Info")
proto.RegisterType((*Event)(nil), "v1alpha.Event")
proto.RegisterType((*EventFilter)(nil), "v1alpha.EventFilter")
proto.RegisterType((*GetInfoRequest)(nil), "v1alpha.GetInfoRequest")
proto.RegisterType((*GetInfoResponse)(nil), "v1alpha.GetInfoResponse")
proto.RegisterType((*ListPodsRequest)(nil), "v1alpha.ListPodsRequest")
proto.RegisterType((*ListPodsResponse)(nil), "v1alpha.ListPodsResponse")
proto.RegisterType((*InspectPodRequest)(nil), "v1alpha.InspectPodRequest")
proto.RegisterType((*InspectPodResponse)(nil), "v1alpha.InspectPodResponse")
proto.RegisterType((*ListImagesRequest)(nil), "v1alpha.ListImagesRequest")
proto.RegisterType((*ListImagesResponse)(nil), "v1alpha.ListImagesResponse")
proto.RegisterType((*InspectImageRequest)(nil), "v1alpha.InspectImageRequest")
proto.RegisterType((*InspectImageResponse)(nil), "v1alpha.InspectImageResponse")
proto.RegisterType((*ListenEventsRequest)(nil), "v1alpha.ListenEventsRequest")
proto.RegisterType((*ListenEventsResponse)(nil), "v1alpha.ListenEventsResponse")
proto.RegisterType((*GetLogsRequest)(nil), "v1alpha.GetLogsRequest")
proto.RegisterType((*GetLogsResponse)(nil), "v1alpha.GetLogsResponse")
proto.RegisterEnum("v1alpha.ImageType", ImageType_name, ImageType_value)
proto.RegisterEnum("v1alpha.AppState", AppState_name, AppState_value)
proto.RegisterEnum("v1alpha.PodState", PodState_name, PodState_value)
......@@ -890,9 +950,9 @@ func RegisterPublicAPIServer(s *grpc.Server, srv PublicAPIServer) {
s.RegisterService(&_PublicAPI_serviceDesc, srv)
}
func _PublicAPI_GetInfo_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _PublicAPI_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(GetInfoRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(PublicAPIServer).GetInfo(ctx, in)
......@@ -902,9 +962,9 @@ func _PublicAPI_GetInfo_Handler(srv interface{}, ctx context.Context, codec grpc
return out, nil
}
func _PublicAPI_ListPods_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _PublicAPI_ListPods_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(ListPodsRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(PublicAPIServer).ListPods(ctx, in)
......@@ -914,9 +974,9 @@ func _PublicAPI_ListPods_Handler(srv interface{}, ctx context.Context, codec grp
return out, nil
}
func _PublicAPI_InspectPod_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _PublicAPI_InspectPod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(InspectPodRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(PublicAPIServer).InspectPod(ctx, in)
......@@ -926,9 +986,9 @@ func _PublicAPI_InspectPod_Handler(srv interface{}, ctx context.Context, codec g
return out, nil
}
func _PublicAPI_ListImages_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _PublicAPI_ListImages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(ListImagesRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(PublicAPIServer).ListImages(ctx, in)
......@@ -938,9 +998,9 @@ func _PublicAPI_ListImages_Handler(srv interface{}, ctx context.Context, codec g
return out, nil
}
func _PublicAPI_InspectImage_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _PublicAPI_InspectImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(InspectImageRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(PublicAPIServer).InspectImage(ctx, in)
......@@ -1030,3 +1090,90 @@ var _PublicAPI_serviceDesc = grpc.ServiceDesc{
},
},
}
var fileDescriptor0 = []byte{
// 1318 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x57, 0x4d, 0x72, 0xdb, 0x46,
0x13, 0x35, 0x08, 0x82, 0x3f, 0x4d, 0x9a, 0x02, 0x47, 0xb2, 0x45, 0xd3, 0x7f, 0x32, 0xbe, 0x2f,
0x2e, 0x47, 0x0b, 0x25, 0x91, 0x1d, 0x6f, 0x52, 0x95, 0x32, 0x25, 0x41, 0x2a, 0xc6, 0x12, 0xc9,
0xa2, 0x69, 0x55, 0xbc, 0x42, 0x41, 0xe2, 0xd0, 0x41, 0x89, 0x04, 0x10, 0x02, 0x92, 0xad, 0x2c,
0x73, 0x81, 0x5c, 0x21, 0xb7, 0x48, 0x55, 0x36, 0xb9, 0x41, 0x6e, 0x91, 0x7b, 0xa4, 0x67, 0x30,
0x00, 0x06, 0x20, 0xb8, 0xc8, 0x8e, 0xe8, 0xee, 0x79, 0xfd, 0xba, 0x7b, 0xfa, 0x01, 0x84, 0xba,
0xed, 0x3b, 0x7b, 0xfe, 0xd2, 0x0b, 0x3d, 0x52, 0xbd, 0xf9, 0xc6, 0x9e, 0xfb, 0x3f, 0xd9, 0xc6,
0x1b, 0x68, 0xf4, 0x17, 0xf6, 0x47, 0x7a, 0xec, 0x2d, 0x17, 0x76, 0x48, 0x76, 0xa0, 0x1c, 0xde,
0xfa, 0xb4, 0xa3, 0xec, 0x28, 0x2f, 0x5a, 0xfb, 0x64, 0x4f, 0x84, 0xed, 0xf1, 0x98, 0x09, 0x7a,
0xc8, 0x06, 0x54, 0x6f, 0xe8, 0x32, 0x70, 0x3c, 0xb7, 0x53, 0xc2, 0xa0, 0xba, 0xf1, 0x97, 0x02,
0x1a, 0x77, 0x93, 0x2f, 0xa1, 0x71, 0x61, 0x07, 0xd4, 0x9a, 0x71, 0x2c, 0x8e, 0xd1, 0xd8, 0xdf,
0xca, 0x62, 0x88, 0x3c, 0x00, 0x25, 0x67, 0x1a, 0x01, 0x90, 0x26, 0x94, 0x5d, 0x7b, 0x41, 0x3b,
0x2a, 0x7f, 0x92, 0xf0, 0xcb, 0xdc, 0xd0, 0x01, 0xdd, 0x59, 0xf8, 0xde, 0x32, 0xb4, 0x42, 0x67,
0x41, 0x83, 0xd0, 0x5e, 0xf8, 0x1d, 0x0d, 0x3d, 0x2a, 0xd1, 0xa1, 0xb6, 0xb0, 0x5d, 0x67, 0x86,
0xc6, 0x4e, 0x05, 0x2d, 0x4d, 0x06, 0x15, 0x38, 0xbf, 0xd0, 0x4e, 0x95, 0xfb, 0x9f, 0x43, 0xc3,
0x76, 0x5d, 0x2f, 0xb4, 0x43, 0x44, 0x0b, 0x3a, 0xb5, 0x1d, 0x15, 0xf9, 0xb4, 0x13, 0x3e, 0x6f,
0xe9, 0xed, 0xb9, 0x3d, 0xbf, 0xa6, 0xc6, 0x4b, 0xa8, 0x0e, 0x68, 0xf8, 0xc9, 0x5b, 0x5e, 0x25,
0x5c, 0x94, 0x98, 0x99, 0xe3, 0xdf, 0xbc, 0x4a, 0x79, 0xe2, 0xd3, 0xeb, 0x88, 0xa7, 0xf1, 0x9b,
0x02, 0x6a, 0xcf, 0xf7, 0x73, 0x27, 0x1e, 0x83, 0xe6, 0xb0, 0x32, 0xf9, 0x91, 0xc6, 0x7e, 0x2b,
0x5b, 0x3c, 0xb6, 0x57, 0xc3, 0x02, 0xc2, 0xa8, 0xd6, 0x96, 0xc4, 0x05, 0x91, 0xde, 0x31, 0x07,
0x69, 0x43, 0x9d, 0x7e, 0x76, 0x42, 0xeb, 0xd2, 0x9b, 0x52, 0xde, 0x80, 0x76, 0xbe, 0x0c, 0x6d,
0x5d, 0x19, 0x7f, 0x22, 0xa3, 0x91, 0x37, 0x15, 0xbd, 0x8d, 0xf8, 0x34, 0x40, 0xf5, 0x45, 0xa3,
0xdb, 0xeb, 0xb3, 0xe3, 0xa9, 0x28, 0x7b, 0x17, 0xca, 0xb6, 0xef, 0x07, 0x98, 0x98, 0xe5, 0x68,
0xca, 0xf4, 0x88, 0x01, 0x35, 0x37, 0xea, 0x52, 0xcc, 0x41, 0x4f, 0xfc, 0x71, 0xfb, 0x56, 0x27,
0x92, 0x23, 0x5f, 0x5d, 0x47, 0xfe, 0x39, 0xd4, 0xe2, 0xdf, 0x8c, 0x34, 0xfe, 0x16, 0x15, 0xdc,
0x05, 0xed, 0x86, 0x59, 0xc5, 0x6d, 0xfb, 0x5d, 0x81, 0x3a, 0xd2, 0x3d, 0x76, 0xe6, 0x21, 0x5d,
0xb2, 0x48, 0x67, 0x1a, 0x60, 0xa4, 0x8a, 0x91, 0xcf, 0xa0, 0xc2, 0xcb, 0x0b, 0x30, 0x54, 0x2d,
0xae, 0xaf, 0xcd, 0x76, 0xc0, 0xb7, 0xd8, 0xc0, 0x02, 0xec, 0x02, 0x3b, 0x85, 0x26, 0x3e, 0x31,
0x8b, 0x01, 0x95, 0xb9, 0xe9, 0x1e, 0xdc, 0x15, 0x95, 0x8a, 0x48, 0x8d, 0x9b, 0x73, 0xa5, 0x54,
0xd6, 0x95, 0xf2, 0xb7, 0x12, 0xef, 0x54, 0x01, 0x49, 0xec, 0x90, 0xbf, 0xa4, 0x33, 0xe7, 0xb3,
0xa0, 0x59, 0x27, 0x38, 0x2f, 0xbe, 0x35, 0x32, 0x29, 0x8c, 0xba, 0xa2, 0xb7, 0xc8, 0x20, 0xe1,
0x84, 0xc5, 0xcd, 0xed, 0x0b, 0x3a, 0x5f, 0x3f, 0x7f, 0x72, 0x1f, 0x5a, 0xd1, 0xa2, 0xd0, 0xa9,
0x65, 0xcf, 0x30, 0x33, 0x1f, 0x81, 0x4a, 0xb6, 0x61, 0x23, 0xb1, 0x5f, 0x50, 0x5c, 0xce, 0xff,
0xba, 0x1f, 0xc7, 0x50, 0xee, 0xbb, 0x33, 0x8f, 0x6c, 0x42, 0x63, 0x79, 0x15, 0x5a, 0xf1, 0x7a,
0x46, 0xf3, 0xd9, 0x82, 0x26, 0xb6, 0xf4, 0xd2, 0xca, 0x88, 0x02, 0x0b, 0x45, 0xb1, 0x49, 0x8c,
0xd1, 0xca, 0x2c, 0x41, 0x33, 0x6f, 0xa8, 0xbb, 0x5e, 0x65, 0xb8, 0x97, 0xab, 0x4c, 0x4e, 0x1f,
0x66, 0x4b, 0x6f, 0x21, 0xf4, 0x01, 0x9f, 0x98, 0x0e, 0xf0, 0xdd, 0x50, 0xc9, 0x53, 0x28, 0x4f,
0xed, 0xd0, 0x5e, 0xbf, 0x14, 0x21, 0x34, 0x38, 0xaa, 0x98, 0xc5, 0x33, 0xd0, 0x58, 0xe6, 0x68,
0x1a, 0xc5, 0xa9, 0xc5, 0xb8, 0xa2, 0xe1, 0xe0, 0xed, 0x93, 0xe7, 0x82, 0xbc, 0x02, 0xc7, 0xbd,
0xa4, 0x96, 0x44, 0x01, 0x6d, 0xd7, 0x6e, 0xe8, 0xcc, 0x23, 0x1b, 0x57, 0x26, 0x43, 0x87, 0xd6,
0x09, 0x0d, 0x59, 0xd3, 0xc6, 0xf4, 0xe7, 0x6b, 0xdc, 0x06, 0x63, 0x0f, 0x36, 0x12, 0x4b, 0xe0,
0x63, 0xbb, 0x29, 0x79, 0x88, 0x7a, 0x82, 0xcf, 0x42, 0x27, 0xef, 0xa6, 0x52, 0x81, 0x46, 0xec,
0xf9, 0xc6, 0xa9, 0x13, 0x84, 0x78, 0x73, 0x03, 0x01, 0x41, 0xfe, 0x07, 0xd5, 0x19, 0xaf, 0x22,
0x62, 0xdf, 0x90, 0xd8, 0xa7, 0x1b, 0xd1, 0x82, 0xca, 0x94, 0x86, 0xb6, 0x33, 0xe7, 0xcd, 0xab,
0x61, 0x5e, 0x3d, 0xc5, 0x11, 0x89, 0x71, 0xcb, 0x7d, 0x6f, 0x1a, 0xa3, 0x34, 0x65, 0x14, 0xe3,
0x29, 0xb4, 0xfb, 0x6e, 0xe0, 0xd3, 0x4b, 0x76, 0x24, 0xce, 0x2c, 0x29, 0x8a, 0xf1, 0x15, 0x10,
0x39, 0x40, 0x40, 0x3e, 0x40, 0x9d, 0xf1, 0xa6, 0xa2, 0x94, 0x2c, 0xe2, 0x0f, 0xd0, 0x66, 0x0c,
0xf8, 0x46, 0x24, 0xb5, 0x7c, 0x91, 0xaf, 0x25, 0xff, 0x9a, 0x28, 0xae, 0xe6, 0x15, 0x10, 0x19,
0x4b, 0x24, 0x7f, 0x02, 0x15, 0xbe, 0xc2, 0x31, 0x56, 0x4e, 0x75, 0x8d, 0x67, 0xb0, 0x29, 0x28,
0xf3, 0xe7, 0xa2, 0xaa, 0xbe, 0x85, 0xad, 0x6c, 0x88, 0x80, 0x4e, 0xf4, 0x5c, 0x29, 0xd2, 0x73,
0xe3, 0x3b, 0xd8, 0x64, 0x7c, 0xa8, 0xcb, 0xaf, 0x4f, 0x52, 0xdd, 0xff, 0xa1, 0x12, 0x55, 0xb7,
0xf2, 0x0e, 0x94, 0xee, 0xa2, 0xf1, 0x1a, 0xb6, 0xb2, 0x87, 0xd3, 0x72, 0x28, 0xb7, 0xac, 0x94,
0xc3, 0x03, 0x8d, 0x5b, 0x7e, 0xb9, 0x4e, 0xbd, 0x8f, 0x49, 0x3e, 0x6c, 0x13, 0x76, 0xdf, 0x4a,
0x54, 0x1f, 0xe5, 0x23, 0x96, 0x39, 0xb1, 0x43, 0x78, 0x8f, 0xe7, 0x8e, 0xcb, 0xef, 0xb1, 0xf2,
0x42, 0x63, 0x07, 0x66, 0xde, 0x7c, 0xee, 0x7d, 0xe2, 0x77, 0xb8, 0x96, 0xbb, 0xd7, 0x5a, 0xc1,
0xbd, 0xe6, 0x52, 0x62, 0xec, 0xf0, 0x5b, 0x1c, 0xa5, 0x16, 0x6c, 0x13, 0x64, 0xae, 0x6f, 0xbb,
0x14, 0xea, 0xe9, 0xb7, 0x42, 0x07, 0xbb, 0x7a, 0xd6, 0x3b, 0x31, 0xad, 0xc9, 0x87, 0x91, 0x69,
0xbd, 0x1f, 0x1c, 0x99, 0xc7, 0xfd, 0x81, 0x79, 0xa4, 0xdf, 0x41, 0x7d, 0xd8, 0x90, 0x3c, 0xbd,
0xd1, 0xe8, 0x50, 0x57, 0x50, 0x77, 0xdb, 0x92, 0xf1, 0x68, 0x78, 0xf8, 0xd6, 0x1c, 0xeb, 0x25,
0x24, 0xd2, 0x92, 0xcc, 0xc3, 0xc3, 0xbe, 0xae, 0xee, 0x8e, 0xa0, 0x96, 0xbc, 0x32, 0xb7, 0x61,
0x13, 0x01, 0xac, 0x77, 0x93, 0xde, 0x24, 0x9b, 0x04, 0xf1, 0x52, 0xc7, 0xf8, 0xfd, 0x60, 0xd0,
0x1f, 0x9c, 0x60, 0x9a, 0x2d, 0xd0, 0x53, 0xb3, 0xf9, 0x63, 0x7f, 0x82, 0xc1, 0xa5, 0xdd, 0x7f,
0x14, 0xa8, 0x25, 0xef, 0x09, 0x84, 0x1c, 0x0d, 0x8f, 0x0a, 0x20, 0xf1, 0x6c, 0xea, 0x30, 0xcf,
0x0e, 0xc6, 0x1f, 0x86, 0x88, 0x98, 0x09, 0x1f, 0x8d, 0xcd, 0x51, 0x6f, 0xcc, 0x52, 0x95, 0x50,
0x92, 0x49, 0xde, 0x81, 0x30, 0x2a, 0x63, 0x96, 0xda, 0x63, 0x66, 0x65, 0xbc, 0x6d, 0x0f, 0x52,
0x73, 0xef, 0x60, 0x38, 0x46, 0x6a, 0xf1, 0x31, 0x5d, 0xcb, 0x25, 0x8f, 0x88, 0x57, 0xb2, 0x39,
0x8e, 0xcc, 0x53, 0x73, 0xc2, 0xc0, 0xaa, 0xd9, 0x1c, 0x27, 0xbd, 0xf1, 0x01, 0xb6, 0x50, 0xaf,
0xed, 0xfe, 0x51, 0x82, 0x7a, 0x2a, 0x76, 0x38, 0x21, 0xf3, 0xdc, 0x1c, 0x4c, 0x56, 0x27, 0xf4,
0x10, 0xb6, 0x25, 0x0f, 0x43, 0x4a, 0xf8, 0x2b, 0xf8, 0x2d, 0xf0, 0xa4, 0xd8, 0x19, 0xb3, 0xc6,
0xda, 0xbb, 0x70, 0x3f, 0x17, 0x83, 0x54, 0xb8, 0x4f, 0x45, 0xb9, 0xb8, 0x97, 0xf3, 0x89, 0x72,
0xca, 0xb8, 0x3b, 0x3b, 0x39, 0x97, 0xe0, 0x6e, 0x1d, 0x0e, 0x4f, 0x4f, 0xcd, 0x43, 0x16, 0xa5,
0xe5, 0xc0, 0xc5, 0x38, 0xc7, 0x51, 0x43, 0xb2, 0xe0, 0xcc, 0x27, 0xc0, 0xab, 0xac, 0xc1, 0x92,
0x2b, 0xba, 0x55, 0xfd, 0xb3, 0x51, 0x44, 0xb9, 0x46, 0x1e, 0x41, 0x67, 0xc5, 0x3d, 0x36, 0xcf,
0x86, 0xe7, 0xe8, 0xad, 0xef, 0xff, 0x5a, 0xc6, 0x4f, 0x8f, 0xeb, 0x8b, 0xb9, 0x73, 0xd9, 0x1b,
0xf5, 0xc9, 0xf7, 0x50, 0x15, 0x82, 0x4e, 0xb6, 0x93, 0x05, 0xcd, 0x8a, 0x7e, 0xb7, 0xb3, 0xea,
0x88, 0xb6, 0xc6, 0xb8, 0x43, 0x7a, 0x50, 0x8b, 0x85, 0x99, 0xa4, 0x71, 0x39, 0xcd, 0xef, 0x3e,
0x28, 0xf0, 0x24, 0x10, 0x27, 0x00, 0xa9, 0x14, 0x93, 0xae, 0xf4, 0x02, 0xc9, 0x09, 0x78, 0xf7,
0x61, 0xa1, 0x4f, 0x06, 0x4a, 0x65, 0x55, 0x02, 0x5a, 0xd1, 0x6d, 0x09, 0x68, 0x55, 0x87, 0x11,
0xe8, 0x0c, 0x9a, 0xb2, 0x8c, 0x92, 0x47, 0xf9, 0xbc, 0xb2, 0x00, 0x77, 0x1f, 0xaf, 0xf1, 0x26,
0x70, 0x43, 0x68, 0xca, 0x0a, 0x29, 0xc1, 0x15, 0xa8, 0xae, 0x04, 0x57, 0x24, 0xab, 0xc6, 0x9d,
0xaf, 0x15, 0xf2, 0x86, 0x0f, 0x8d, 0xe9, 0x57, 0x76, 0x68, 0x92, 0x98, 0x66, 0x87, 0x26, 0x4b,
0x1d, 0x43, 0xb8, 0xa8, 0xf0, 0xff, 0x4f, 0x2f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x84, 0xa0,
0x2b, 0xe3, 0x4c, 0x0d, 0x00, 0x00,
}
......@@ -21,8 +21,6 @@
// The API defined here is proposed, experimental, //
// and (for now) subject to change at any time. //
// //
// Do not use it. //
// //
// If you think you want to use it, or for any other //
// queries, contact <rkt-dev@googlegroups.com> //
// or file an issue on github.com/coreos/rkt //
......@@ -234,6 +232,9 @@ message ImageFilter {
// If not empty, the images that have all of the annotations will be returned.
repeated KeyValue annotations = 8;
// If not empty, the images that have any of the exact full names will be returned.
repeated string full_names = 9;
}
// Info describes the information of rkt on the machine.
......
......@@ -20,8 +20,6 @@ import (
"fmt"
"os"
// Note that if your project uses Godep to manage dependencies, then
// you need to change following the import paths.
"github.com/coreos/rkt/api/v1alpha"
"golang.org/x/net/context"
"google.golang.org/grpc"
......
......@@ -230,6 +230,14 @@ var E_GogoprotoImport = &proto.ExtensionDesc{
Tag: "varint,63027,opt,name=gogoproto_import",
}
var E_ProtosizerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63028,
Name: "gogoproto.protosizer_all",
Tag: "varint,63028,opt,name=protosizer_all",
}
var E_GoprotoGetters = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
......@@ -382,6 +390,14 @@ var E_GoprotoUnrecognized = &proto.ExtensionDesc{
Tag: "varint,64026,opt,name=goproto_unrecognized",
}
var E_Protosizer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64028,
Name: "gogoproto.protosizer",
Tag: "varint,64028,opt,name=protosizer",
}
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
......@@ -481,6 +497,7 @@ func init() {
proto.RegisterExtension(E_GoprotoExtensionsMapAll)
proto.RegisterExtension(E_GoprotoUnrecognizedAll)
proto.RegisterExtension(E_GogoprotoImport)
proto.RegisterExtension(E_ProtosizerAll)
proto.RegisterExtension(E_GoprotoGetters)
proto.RegisterExtension(E_GoprotoStringer)
proto.RegisterExtension(E_VerboseEqual)
......@@ -500,6 +517,7 @@ func init() {
proto.RegisterExtension(E_UnsafeUnmarshaler)
proto.RegisterExtension(E_GoprotoExtensionsMap)
proto.RegisterExtension(E_GoprotoUnrecognized)
proto.RegisterExtension(E_Protosizer)
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
......
......@@ -67,6 +67,8 @@ extend google.protobuf.FileOptions {
optional bool goproto_extensions_map_all = 63025;
optional bool goproto_unrecognized_all = 63026;
optional bool gogoproto_import = 63027;
optional bool protosizer_all = 63028;
}
extend google.protobuf.MessageOptions {
......@@ -93,6 +95,8 @@ extend google.protobuf.MessageOptions {
optional bool goproto_extensions_map = 64025;
optional bool goproto_unrecognized = 64026;
optional bool protosizer = 64028;
}
extend google.protobuf.FieldOptions {
......
......@@ -213,6 +213,10 @@ func IsSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf
return proto.GetBoolExtension(message.Options, E_Sizer, proto.GetBoolExtension(file.Options, E_SizerAll, false))
}
func IsProtoSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Protosizer, proto.GetBoolExtension(file.Options, E_ProtosizerAll, false))
}
func IsGoEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_GoprotoEnumStringer, proto.GetBoolExtension(file.Options, E_GoprotoEnumStringerAll, true))
}
......
......@@ -81,6 +81,7 @@ var overwriters []map[string]gogoproto.EnableFunc = []map[string]gogoproto.Enabl
},
{
"size": gogoproto.IsSizer,
"protosizer": gogoproto.IsProtoSizer,
},
{
"unmarshaler": gogoproto.IsUnmarshaler,
......
......@@ -303,12 +303,12 @@ func wireToType(wire string) int {
panic("unreachable")
}
func (p *marshalto) mapField(numGen NumGen, fieldTyp descriptor.FieldDescriptorProto_Type, varName string) {
func (p *marshalto) mapField(numGen NumGen, fieldTyp descriptor.FieldDescriptorProto_Type, varName string, protoSizer bool) {
switch fieldTyp {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
p.callFixed64(p.mathPkg.Use(), `.Float64bits(`, varName, `)`)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(`, varName, `))`)
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
p.callFixed32(p.mathPkg.Use(), `.Float32bits(`, varName, `)`)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(`, varName, `))`)
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_INT32,
......@@ -341,7 +341,11 @@ func (p *marshalto) mapField(numGen NumGen, fieldTyp descriptor.FieldDescriptorP
case descriptor.FieldDescriptorProto_TYPE_SINT64:
p.callVarint(`(uint64(`, varName, `) << 1) ^ uint64((`, varName, ` >> 63))`)
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
if protoSizer {
p.callVarint(varName, `.ProtoSize()`)
} else {
p.callVarint(varName, `.Size()`)
}
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(data[i:])`)
p.P(`if err != nil {`)
p.In()
......@@ -371,6 +375,8 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
required := field.IsRequired()
protoSizer := gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto)
if required && nullable {
p.P(`if m.`, fieldname, `== nil {`)
p.In()
......@@ -397,13 +403,13 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
}
switch *field.Type {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
if !p.unsafe {
if !p.unsafe || gogoproto.IsCastType(field) {
if packed {
p.encodeKey(fieldNumber, wireType)
p.callVarint(`len(m.`, fieldname, `) * 8`)
p.P(`for _, num := range m.`, fieldname, ` {`)
p.In()
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(num)`)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
p.encodeFixed64("f" + numGen.Current())
p.Out()
p.P(`}`)
......@@ -411,7 +417,7 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`for _, num := range m.`, fieldname, ` {`)
p.In()
p.encodeKey(fieldNumber, wireType)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(num)`)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
p.encodeFixed64("f" + numGen.Current())
p.Out()
p.P(`}`)
......@@ -419,15 +425,15 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.encodeKey(fieldNumber, wireType)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(m.`+fieldname, `)`)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
p.Out()
p.P(`}`)
} else if !nullable {
p.encodeKey(fieldNumber, wireType)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(m.`+fieldname, `)`)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
} else {
p.encodeKey(fieldNumber, wireType)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(*m.`+fieldname, `)`)
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(*m.`+fieldname, `))`)
}
} else {
if packed {
......@@ -461,13 +467,13 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
}
}
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
if !p.unsafe {
if !p.unsafe || gogoproto.IsCastType(field) {
if packed {
p.encodeKey(fieldNumber, wireType)
p.callVarint(`len(m.`, fieldname, `) * 4`)
p.P(`for _, num := range m.`, fieldname, ` {`)
p.In()
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(num)`)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
p.encodeFixed32("f" + numGen.Current())
p.Out()
p.P(`}`)
......@@ -475,7 +481,7 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`for _, num := range m.`, fieldname, ` {`)
p.In()
p.encodeKey(fieldNumber, wireType)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(num)`)
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
p.encodeFixed32("f" + numGen.Current())
p.Out()
p.P(`}`)
......@@ -483,15 +489,15 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.encodeKey(fieldNumber, wireType)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(m.`+fieldname, `)`)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
p.Out()
p.P(`}`)
} else if !nullable {
p.encodeKey(fieldNumber, wireType)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(m.`+fieldname, `)`)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
} else {
p.encodeKey(fieldNumber, wireType)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(*m.`+fieldname, `)`)
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(*m.`+fieldname, `))`)
}
} else {
if packed {
......@@ -896,22 +902,30 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
} else if !nullable {
accessor = `(&v)`
}
if protoSizer {
p.P(`msgSize := `, accessor, `.ProtoSize()`)
} else {
p.P(`msgSize := `, accessor, `.Size()`)
}
sum = append(sum, `msgSize + sov`+p.localName+`(uint64(msgSize))`)
}
p.P(`mapSize := `, strings.Join(sum, " + "))
p.callVarint("mapSize")
p.encodeKey(1, wireToType(keywire))
p.mapField(numGen, m.KeyField.GetType(), "k")
p.mapField(numGen, m.KeyField.GetType(), "k", protoSizer)
p.encodeKey(2, wireToType(valuewire))
p.mapField(numGen, m.ValueField.GetType(), accessor)
p.mapField(numGen, m.ValueField.GetType(), accessor, protoSizer)
p.Out()
p.P(`}`)
} else if repeated {
p.P(`for _, msg := range m.`, fieldname, ` {`)
p.In()
p.encodeKey(fieldNumber, wireType)
if protoSizer {
p.callVarint("msg.ProtoSize()")
} else {
p.callVarint("msg.Size()")
}
p.P(`n, err := msg.MarshalTo(data[i:])`)
p.P(`if err != nil {`)
p.In()
......@@ -923,7 +937,11 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`}`)
} else {
p.encodeKey(fieldNumber, wireType)
if protoSizer {
p.callVarint(`m.`, fieldname, `.ProtoSize()`)
} else {
p.callVarint(`m.`, fieldname, `.Size()`)
}
p.P(`n`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(data[i:])`)
p.P(`if err != nil {`)
p.In()
......@@ -960,7 +978,11 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`for _, msg := range m.`, fieldname, ` {`)
p.In()
p.encodeKey(fieldNumber, wireType)
if protoSizer {
p.callVarint(`msg.ProtoSize()`)
} else {
p.callVarint(`msg.Size()`)
}
p.P(`n, err := msg.MarshalTo(data[i:])`)
p.P(`if err != nil {`)
p.In()
......@@ -972,7 +994,11 @@ func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.Fi
p.P(`}`)
} else {
p.encodeKey(fieldNumber, wireType)
if protoSizer {
p.callVarint(`m.`, fieldname, `.ProtoSize()`)
} else {
p.callVarint(`m.`, fieldname, `.Size()`)
}
p.P(`n`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(data[i:])`)
p.P(`if err != nil {`)
p.In()
......@@ -1126,7 +1152,11 @@ func (p *marshalto) Generate(file *generator.FileDescriptor) {
p.P(`func (m *`, ccTypeName, `) Marshal() (data []byte, err error) {`)
p.In()
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`size := m.ProtoSize()`)
} else {
p.P(`size := m.Size()`)
}
p.P(`data = make([]byte, size)`)
p.P(`n, err := m.MarshalTo(data)`)
p.P(`if err != nil {`)
......
......@@ -290,7 +290,7 @@ func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generato
} else if field.IsMessage() || p.IsGroup(field) {
funcCall := getFuncCall(goTypName)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(p.varGen.Next(), ` := r.Intn(5)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
......@@ -346,7 +346,7 @@ func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generato
}
} else if field.IsBytes() {
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
......@@ -387,7 +387,7 @@ func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generato
} else {
typName := generator.GoTypeToName(goTyp)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
......
......@@ -25,7 +25,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The size plugin generates a Size method for each message.
The size plugin generates a Size or ProtoSize method for each message.
This is useful with the MarshalTo method generated by the marshalto plugin and the
gogoproto.marshaler and gogoproto.marshaler_all extensions.
......@@ -33,6 +33,8 @@ It is enabled by the following extensions:
- sizer
- sizer_all
- protosizer
- protosizer_all
The size plugin also generates a test given it is enabled using one of the following extensions:
......@@ -195,7 +197,7 @@ func (p *size) sizeZigZag() {
}`)
}
func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
fieldname := p.GetOneOfFieldName(message, field)
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
......@@ -393,17 +395,17 @@ func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, messag
p.P(`if v != nil {`)
p.In()
if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((`, valuegoTyp, `)(v)).Size()`)
p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
} else {
p.P(`l = v.Size()`)
p.P(`l = v.`, sizeName, `()`)
}
p.Out()
p.P(`}`)
} else {
if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((*`, valuegoTyp, `)(&v)).Size()`)
p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
} else {
p.P(`l = v.Size()`)
p.P(`l = v.`, sizeName, `()`)
}
}
sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
......@@ -415,12 +417,12 @@ func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, messag
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
p.P(`l=e.Size()`)
p.P(`l=e.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=m.`, fieldname, `.Size()`)
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
case descriptor.FieldDescriptorProto_TYPE_BYTES:
......@@ -447,12 +449,12 @@ func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, messag
if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
p.P(`l=e.Size()`)
p.P(`l=e.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=m.`, fieldname, `.Size()`)
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
}
......@@ -501,7 +503,12 @@ func (p *size) Generate(file *generator.FileDescriptor) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
if !gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
......@@ -509,7 +516,7 @@ func (p *size) Generate(file *generator.FileDescriptor) {
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (m *`, ccTypeName, `) Size() (n int) {`)
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`var l int`)
p.P(`_ = l`)
......@@ -518,7 +525,7 @@ func (p *size) Generate(file *generator.FileDescriptor) {
oneof := field.OneofIndex != nil
if !oneof {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.generateField(proto3, file, message, field)
p.generateField(proto3, file, message, field, sizeName)
} else {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
......@@ -528,7 +535,7 @@ func (p *size) Generate(file *generator.FileDescriptor) {
}
p.P(`if m.`, fieldname, ` != nil {`)
p.In()
p.P(`n+=m.`, fieldname, `.Size()`)
p.P(`n+=m.`, fieldname, `.`, sizeName, `()`)
p.Out()
p.P(`}`)
}
......@@ -564,12 +571,12 @@ func (p *size) Generate(file *generator.FileDescriptor) {
continue
}
ccTypeName := p.OneOfTypeName(message, f)
p.P(`func (m *`, ccTypeName, `) Size() (n int) {`)
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`var l int`)
p.P(`_ = l`)
vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly(f)
p.generateField(false, file, message, f)
p.generateField(false, file, message, f, sizeName)
p.P(`return n`)
p.Out()
p.P(`}`)
......
......@@ -51,7 +51,12 @@ func (p *test) Generate(imports generator.PluginImports, file *generator.FileDes
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
......@@ -60,7 +65,7 @@ func (p *test) Generate(imports generator.PluginImports, file *generator.FileDes
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Size(t *`, testingPkg.Use(), `.T) {`)
p.P(`func Test`, ccTypeName, sizeName, `(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
......@@ -72,7 +77,7 @@ func (p *test) Generate(imports generator.PluginImports, file *generator.FileDes
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`size := p.Size()`)
p.P(`size := p.`, sizeName, `()`)
p.P(`if len(data) != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(data))`)
......@@ -96,7 +101,7 @@ func (p *test) Generate(imports generator.PluginImports, file *generator.FileDes
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Benchmark`, ccTypeName, `Size(b *`, testingPkg.Use(), `.B) {`)
p.P(`func Benchmark`, ccTypeName, sizeName, `(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
......@@ -109,7 +114,7 @@ func (p *test) Generate(imports generator.PluginImports, file *generator.FileDes
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`total += pops[i%1000].Size()`)
p.P(`total += pops[i%1000].`, sizeName, `()`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
......
......@@ -341,7 +341,11 @@ func (p *testProto) Generate(imports generator.PluginImports, file *generator.Fi
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`size := p.ProtoSize()`)
} else {
p.P(`size := p.Size()`)
}
p.P(`data := make([]byte, size)`)
p.P(`for i := range data {`)
p.In()
......
......@@ -419,7 +419,7 @@ func (p *unmarshal) noStarOrSliceType(msg *generator.Descriptor, field *descript
return typ
}
func (p *unmarshal) field(file *descriptor.FileDescriptorProto, msg *generator.Descriptor, field *descriptor.FieldDescriptorProto, fieldname string, proto3 bool) {
func (p *unmarshal) field(file *generator.FileDescriptor, msg *generator.Descriptor, field *descriptor.FieldDescriptorProto, fieldname string, proto3 bool) {
repeated := field.IsRepeated()
nullable := gogoproto.IsNullable(field)
typ := p.noStarOrSliceType(msg, field)
......@@ -676,7 +676,7 @@ func (p *unmarshal) field(file *descriptor.FileDescriptorProto, msg *generator.D
p.Out()
p.P(`}`)
p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
} else if generator.IsMap(file, field) {
} else if generator.IsMap(file.FileDescriptorProto, field) {
m := p.GoMapType(nil, field)
keygoTyp, _ := p.GoType(nil, m.KeyField)
......@@ -773,7 +773,12 @@ func (p *unmarshal) field(file *descriptor.FileDescriptorProto, msg *generator.D
p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, make([]byte, postIndex-iNdEx))`)
p.P(`copy(m.`, fieldname, `[len(m.`, fieldname, `)-1], data[iNdEx:postIndex])`)
} else {
p.P(`m.`, fieldname, ` = append([]byte{}`, `, data[iNdEx:postIndex]...)`)
p.P(`m.`, fieldname, ` = append(m.`, fieldname, `[:0] , data[iNdEx:postIndex]...)`)
p.P(`if m.`, fieldname, ` == nil {`)
p.In()
p.P(`m.`, fieldname, ` = []byte{}`)
p.Out()
p.P(`}`)
}
} else {
_, ctyp, err := generator.GetCustomType(field)
......@@ -1061,13 +1066,13 @@ func (p *unmarshal) Generate(file *generator.FileDescriptor) {
p.P(`}`)
p.P(`for iNdEx < postIndex {`)
p.In()
p.field(file.FileDescriptorProto, message, field, fieldname, false)
p.field(file, message, field, fieldname, false)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if wireType == `, strconv.Itoa(wireType), `{`)
p.In()
p.field(file.FileDescriptorProto, message, field, fieldname, false)
p.field(file, message, field, fieldname, false)
p.Out()
p.P(`} else {`)
p.In()
......@@ -1080,7 +1085,7 @@ func (p *unmarshal) Generate(file *generator.FileDescriptor) {
p.P(`return ` + fmtPkg.Use() + `.Errorf("proto: wrong wireType = %d for field ` + errFieldname + `", wireType)`)
p.Out()
p.P(`}`)
p.field(file.FileDescriptorProto, message, field, fieldname, proto3)
p.field(file, message, field, fieldname, proto3)
}
if field.IsRequired() {
......
......@@ -601,7 +601,7 @@ func (g *Generator) CommandLineParameters(parameter string) {
if pluginList == "none" {
pluginList = ""
}
gogoPluginNames := []string{"unmarshal", "unsafeunmarshaler", "union", "stringer", "size", "populate", "marshalto", "unsafemarshaler", "gostring", "face", "equal", "enumstringer", "embedcheck", "description", "defaultcheck", "oneofcheck"}
gogoPluginNames := []string{"unmarshal", "unsafeunmarshaler", "union", "stringer", "size", "protosizer", "populate", "marshalto", "unsafemarshaler", "gostring", "face", "equal", "enumstringer", "embedcheck", "description", "defaultcheck", "oneofcheck"}
pluginList = strings.Join(append(gogoPluginNames, pluginList), "+")
if pluginList != "" {
// Amend the set of plugins.
......@@ -1857,11 +1857,11 @@ var methodNames = [...]string{
"ExtensionRangeArray",
"ExtensionMap",
"Descriptor",
"Size",
"MarshalTo",
"Equal",
"VerboseEqual",
"GoString",
"ProtoSize",
}
// Generate the type and default constant definitions for this Descriptor.
......@@ -1875,6 +1875,9 @@ func (g *Generator) generateMessage(message *Descriptor) {
for _, n := range methodNames {
usedNames[n] = true
}
if !gogoproto.IsProtoSizer(message.file, message.DescriptorProto) {
usedNames["Size"] = true
}
fieldNames := make(map[*descriptor.FieldDescriptorProto]string)
fieldGetterNames := make(map[*descriptor.FieldDescriptorProto]string)
fieldTypes := make(map[*descriptor.FieldDescriptorProto]string)
......@@ -2210,6 +2213,9 @@ func (g *Generator) generateMessage(message *Descriptor) {
if gogoproto.IsSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
g.P(`Size() int`)
}
if gogoproto.IsProtoSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
g.P(`ProtoSize() int`)
}
g.Out()
g.P("}")
}
......
......@@ -181,6 +181,11 @@ func (g *Generator) GetFieldName(message *Descriptor, field *descriptor.FieldDes
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
......@@ -198,6 +203,11 @@ func (g *Generator) GetOneOfFieldName(message *Descriptor, field *descriptor.Fie
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
......
......@@ -39,5 +39,5 @@ test: install generate-test-pbs
generate-test-pbs:
make install
make -C testdata
make -C proto3_proto
protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto
make
......@@ -29,8 +29,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Protocol buffer deep copy.
// TODO: MessageSet and RawMessage.
// Protocol buffer deep copy and merge.
// TODO: RawMessage.
package proto
......@@ -75,12 +75,13 @@ func Merge(dst, src Message) {
}
func mergeStruct(out, in reflect.Value) {
sprop := GetProperties(in.Type())
for i := 0; i < in.NumField(); i++ {
f := in.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
mergeAny(out.Field(i), in.Field(i))
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
}
if emIn, ok := in.Addr().Interface().(extendableProto); ok {
......@@ -98,7 +99,10 @@ func mergeStruct(out, in reflect.Value) {
}
}
func mergeAny(out, in reflect.Value) {
// mergeAny performs a merge between two values of the same type.
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
// prop is set if this is a struct field (it may be nil).
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
if in.Type() == protoMessageType {
if !in.IsNil() {
if out.IsNil() {
......@@ -112,7 +116,21 @@ func mergeAny(out, in reflect.Value) {
switch in.Kind() {
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
reflect.String, reflect.Uint32, reflect.Uint64:
if !viaPtr && isProto3Zero(in) {
return
}
out.Set(in)
case reflect.Interface:
// Probably a oneof field; copy non-nil values.
if in.IsNil() {
return
}
// Allocate destination if it is not set, or set to a different type.
// Otherwise we will merge as normal.
if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
}
mergeAny(out.Elem(), in.Elem(), false, nil)
case reflect.Map:
if in.Len() == 0 {
return
......@@ -127,7 +145,7 @@ func mergeAny(out, in reflect.Value) {
switch elemKind {
case reflect.Ptr:
val = reflect.New(in.Type().Elem().Elem())
mergeAny(val, in.MapIndex(key))
mergeAny(val, in.MapIndex(key), false, nil)
case reflect.Slice:
val = in.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
......@@ -143,13 +161,21 @@ func mergeAny(out, in reflect.Value) {
if out.IsNil() {
out.Set(reflect.New(in.Elem().Type()))
}
mergeAny(out.Elem(), in.Elem())
mergeAny(out.Elem(), in.Elem(), true, nil)
case reflect.Slice:
if in.IsNil() {
return
}
if in.Type().Elem().Kind() == reflect.Uint8 {
// []byte is a scalar bytes field, not a repeated field.
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value, and should not
// be merged.
if prop != nil && prop.proto3 && in.Len() == 0 {
return
}
// Make a deep copy.
// Append to []byte{} instead of []byte(nil) so that we never end up
// with a nil result.
......@@ -167,7 +193,7 @@ func mergeAny(out, in reflect.Value) {
default:
for i := 0; i < n; i++ {
x := reflect.Indirect(reflect.New(in.Type().Elem()))
mergeAny(x, in.Index(i))
mergeAny(x, in.Index(i), false, nil)
out.Set(reflect.Append(out, x))
}
}
......@@ -184,7 +210,7 @@ func mergeExtension(out, in map[int32]Extension) {
eOut := Extension{desc: eIn.desc}
if eIn.value != nil {
v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
mergeAny(v, reflect.ValueOf(eIn.value))
mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
eOut.value = v.Interface()
}
if eIn.enc != nil {
......
......@@ -46,6 +46,10 @@ import (
// errOverflow is returned when an integer is too large to be represented.
var errOverflow = errors.New("proto: integer overflow")
// ErrInternalBadWireType is returned by generated code when an incorrect
// wire type is encountered. It does not get returned to user code.
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
// The fundamental decoders that interpret bytes on the wire.
// Those that take integer types all return uint64 and are
// therefore of type valueDecoder.
......@@ -314,6 +318,24 @@ func UnmarshalMerge(buf []byte, pb Message) error {
return NewBuffer(buf).Unmarshal(pb)
}
// DecodeMessage reads a count-delimited message from the Buffer.
func (p *Buffer) DecodeMessage(pb Message) error {
enc, err := p.DecodeRawBytes(false)
if err != nil {
return err
}
return NewBuffer(enc).Unmarshal(pb)
}
// DecodeGroup reads a tag-delimited group from the Buffer.
func (p *Buffer) DecodeGroup(pb Message) error {
typ, base, err := getbase(pb)
if err != nil {
return err
}
return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
}
// Unmarshal parses the protocol buffer representation in the
// Buffer and places the decoded result in pb. If the struct
// underlying pb does not match the data in the buffer, the results can be
......@@ -377,6 +399,20 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group
continue
}
}
// Maybe it's a oneof?
if prop.oneofUnmarshaler != nil {
m := structPointer_Interface(base, st).(Message)
// First return value indicates whether tag is a oneof field.
ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
if err == ErrInternalBadWireType {
// Map the error to something more descriptive.
// Do the formatting here to save generated code space.
err = fmt.Errorf("bad wiretype for oneof field in %T", m)
}
if ok {
continue
}
}
err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
continue
}
......@@ -518,9 +554,7 @@ func (o *Buffer) dec_string(p *Properties, base structPointer) error {
if err != nil {
return err
}
sp := new(string)
*sp = s
*structPointer_String(base, p.field) = sp
*structPointer_String(base, p.field) = &s
return nil
}
......@@ -563,9 +597,13 @@ func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error
return err
}
nb := int(nn) // number of bytes of encoded bools
fin := o.index + nb
if fin < o.index {
return errOverflow
}
y := *v
for i := 0; i < nb; i++ {
for o.index < fin {
u, err := p.valDec(o)
if err != nil {
return err
......@@ -677,7 +715,7 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
oi := o.index // index at the end of this map entry
o.index -= len(raw) // move buffer back to start of map entry
mptr := structPointer_Map(base, p.field, p.mtype) // *map[K]V
mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
if mptr.Elem().IsNil() {
mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
}
......@@ -729,8 +767,14 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
return fmt.Errorf("proto: bad map data tag %d", raw[0])
}
}
keyelem, valelem := keyptr.Elem(), valptr.Elem()
if !keyelem.IsValid() || !valelem.IsValid() {
// We did not decode the key or the value in the map entry.
// Either way, it's an invalid map entry.
return fmt.Errorf("proto: bad map data: missing key/val")
}
v.SetMapIndex(keyptr.Elem(), valptr.Elem())
v.SetMapIndex(keyelem, valelem)
return nil
}
......
......@@ -60,9 +60,9 @@ func (e *RequiredNotSetError) Error() string {
}
var (
// ErrRepeatedHasNil is the error returned if Marshal is called with
// errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element.
ErrRepeatedHasNil = errors.New("proto: repeated field has nil element")
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
// ErrNil is the error returned if Marshal is called with nil.
ErrNil = errors.New("proto: Marshal called with nil")
......@@ -105,6 +105,11 @@ func (p *Buffer) EncodeVarint(x uint64) error {
return nil
}
// SizeVarint returns the varint encoding size of an integer.
func SizeVarint(x uint64) int {
return sizeVarint(x)
}
func sizeVarint(x uint64) (n int) {
for {
n++
......@@ -228,6 +233,20 @@ func Marshal(pb Message) ([]byte, error) {
return p.buf, err
}
// EncodeMessage writes the protocol buffer to the Buffer,
// prefixed by a varint-encoded length.
func (p *Buffer) EncodeMessage(pb Message) error {
t, base, err := getbase(pb)
if structPointer_IsNil(base) {
return ErrNil
}
if err == nil {
var state errorState
err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
}
return err
}
// Marshal takes the protocol buffer
// and encodes it into the wire format, writing the result to the
// Buffer.
......@@ -318,7 +337,7 @@ func size_bool(p *Properties, base structPointer) int {
func size_proto3_bool(p *Properties, base structPointer) int {
v := *structPointer_BoolVal(base, p.field)
if !v {
if !v && !p.oneof {
return 0
}
return len(p.tagcode) + 1 // each bool takes exactly one byte
......@@ -361,7 +380,7 @@ func size_int32(p *Properties, base structPointer) (n int) {
func size_proto3_int32(p *Properties, base structPointer) (n int) {
v := structPointer_Word32Val(base, p.field)
x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
if x == 0 {
if x == 0 && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -407,7 +426,7 @@ func size_uint32(p *Properties, base structPointer) (n int) {
func size_proto3_uint32(p *Properties, base structPointer) (n int) {
v := structPointer_Word32Val(base, p.field)
x := word32Val_Get(v)
if x == 0 {
if x == 0 && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -452,7 +471,7 @@ func size_int64(p *Properties, base structPointer) (n int) {
func size_proto3_int64(p *Properties, base structPointer) (n int) {
v := structPointer_Word64Val(base, p.field)
x := word64Val_Get(v)
if x == 0 {
if x == 0 && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -495,7 +514,7 @@ func size_string(p *Properties, base structPointer) (n int) {
func size_proto3_string(p *Properties, base structPointer) (n int) {
v := *structPointer_StringVal(base, p.field)
if v == "" {
if v == "" && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -529,7 +548,7 @@ func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
return state.err
}
o.buf = append(o.buf, p.tagcode...)
......@@ -667,7 +686,7 @@ func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error
func size_slice_byte(p *Properties, base structPointer) (n int) {
s := *structPointer_Bytes(base, p.field)
if s == nil {
if s == nil && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -677,7 +696,7 @@ func size_slice_byte(p *Properties, base structPointer) (n int) {
func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
s := *structPointer_Bytes(base, p.field)
if len(s) == 0 {
if len(s) == 0 && !p.oneof {
return 0
}
n += len(p.tagcode)
......@@ -939,7 +958,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
for i := 0; i < l; i++ {
structp := s.Index(i)
if structPointer_IsNil(structp) {
return ErrRepeatedHasNil
return errRepeatedHasNil
}
// Can the object marshal itself?
......@@ -958,7 +977,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
err := o.enc_len_struct(p.sprop, structp, &state)
if err != nil && !state.shouldContinue(err, nil) {
if err == ErrNil {
return ErrRepeatedHasNil
return errRepeatedHasNil
}
return err
}
......@@ -1001,7 +1020,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
for i := 0; i < l; i++ {
b := s.Index(i)
if structPointer_IsNil(b) {
return ErrRepeatedHasNil
return errRepeatedHasNil
}
o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
......@@ -1010,7 +1029,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
if err != nil && !state.shouldContinue(err, nil) {
if err == ErrNil {
return ErrRepeatedHasNil
return errRepeatedHasNil
}
return err
}
......@@ -1084,7 +1103,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
repeated MapFieldEntry map_field = N;
*/
v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
if v.Len() == 0 {
return nil
}
......@@ -1101,11 +1120,15 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
return nil
}
keys := v.MapKeys()
sort.Sort(mapKeys(keys))
for _, key := range keys {
// Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
for _, key := range v.MapKeys() {
val := v.MapIndex(key)
// The only illegal map entry values are nil message pointers.
if val.Kind() == reflect.Ptr && val.IsNil() {
return errors.New("proto: map has nil element")
}
keycopy.Set(key)
valcopy.Set(val)
......@@ -1118,7 +1141,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
}
func size_new_map(p *Properties, base structPointer) int {
v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
......@@ -1128,10 +1151,12 @@ func size_new_map(p *Properties, base structPointer) int {
keycopy.Set(key)
valcopy.Set(val)
// Tag codes are two bytes per map entry.
n += 2
n += p.mkeyprop.size(p.mkeyprop, keybase)
n += p.mvalprop.size(p.mvalprop, valbase)
// Tag codes for key and val are the responsibility of the sub-sizer.
keysize := p.mkeyprop.size(p.mkeyprop, keybase)
valsize := p.mvalprop.size(p.mvalprop, valbase)
entry := keysize + valsize
// Add on tag code and length of map entry itself.
n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
}
return n
}
......@@ -1184,6 +1209,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
if p.Required && state.err == nil {
state.err = &RequiredNotSetError{p.Name}
}
} else if err == errRepeatedHasNil {
// Give more context to nil values in repeated fields.
return errors.New("repeated field " + p.OrigName + " has nil element")
} else if !state.shouldContinue(err, p) {
return err
}
......@@ -1191,6 +1219,14 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
}
}
// Do oneof fields.
if prop.oneofMarshaler != nil {
m := structPointer_Interface(base, prop.stype).(Message)
if err := prop.oneofMarshaler(m, o); err != nil {
return err
}
}
// Add unrecognized fields at the end.
if prop.unrecField.IsValid() {
v := *structPointer_Bytes(base, prop.unrecField)
......@@ -1216,6 +1252,12 @@ func size_struct(prop *StructProperties, base structPointer) (n int) {
n += len(v)
}
// Factor in any oneof fields.
if prop.oneofSizer != nil {
m := structPointer_Interface(base, prop.stype).(Message)
n += prop.oneofSizer(m)
}
return
}
......
......@@ -30,7 +30,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Protocol buffer comparison.
// TODO: MessageSet.
package proto
......@@ -51,7 +50,9 @@ Equality is defined in this way:
are equal, and extensions sets are equal.
- Two set scalar fields are equal iff their values are equal.
If the fields are of a floating-point type, remember that
NaN != x for all x, including NaN.
NaN != x for all x, including NaN. If the message is defined
in a proto3 .proto file, fields are not "set"; specifically,
zero length proto3 "bytes" fields are equal (nil == {}).
- Two repeated fields are equal iff their lengths are the same,
and their corresponding elements are equal (a "bytes" field,
although represented by []byte, is not a repeated field)
......@@ -89,6 +90,7 @@ func Equal(a, b Message) bool {
// v1 and v2 are known to have the same type.
func equalStruct(v1, v2 reflect.Value) bool {
sprop := GetProperties(v1.Type())
for i := 0; i < v1.NumField(); i++ {
f := v1.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
......@@ -114,7 +116,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
}
f1, f2 = f1.Elem(), f2.Elem()
}
if !equalAny(f1, f2) {
if !equalAny(f1, f2, sprop.Prop[i]) {
return false
}
}
......@@ -141,7 +143,8 @@ func equalStruct(v1, v2 reflect.Value) bool {
}
// v1 and v2 are known to have the same type.
func equalAny(v1, v2 reflect.Value) bool {
// prop may be nil.
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
if v1.Type() == protoMessageType {
m1, _ := v1.Interface().(Message)
m2, _ := v2.Interface().(Message)
......@@ -154,6 +157,17 @@ func equalAny(v1, v2 reflect.Value) bool {
return v1.Float() == v2.Float()
case reflect.Int32, reflect.Int64:
return v1.Int() == v2.Int()
case reflect.Interface:
// Probably a oneof field; compare the inner values.
n1, n2 := v1.IsNil(), v2.IsNil()
if n1 || n2 {
return n1 == n2
}
e1, e2 := v1.Elem(), v2.Elem()
if e1.Type() != e2.Type() {
return false
}
return equalAny(e1, e2, nil)
case reflect.Map:
if v1.Len() != v2.Len() {
return false
......@@ -164,16 +178,22 @@ func equalAny(v1, v2 reflect.Value) bool {
// This key was not found in the second map.
return false
}
if !equalAny(v1.MapIndex(key), val2) {
if !equalAny(v1.MapIndex(key), val2, nil) {
return false
}
}
return true
case reflect.Ptr:
return equalAny(v1.Elem(), v2.Elem())
return equalAny(v1.Elem(), v2.Elem(), prop)
case reflect.Slice:
if v1.Type().Elem().Kind() == reflect.Uint8 {
// short circuit: []byte
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value.
if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
return true
}
if v1.IsNil() != v2.IsNil() {
return false
}
......@@ -184,7 +204,7 @@ func equalAny(v1, v2 reflect.Value) bool {
return false
}
for i := 0; i < v1.Len(); i++ {
if !equalAny(v1.Index(i), v2.Index(i)) {
if !equalAny(v1.Index(i), v2.Index(i), prop) {
return false
}
}
......@@ -219,7 +239,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
if m1 != nil && m2 != nil {
// Both are unencoded.
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
return false
}
continue
......@@ -247,7 +267,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
return false
}
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
return false
}
}
......
......@@ -37,6 +37,7 @@ package proto
import (
"errors"
"fmt"
"reflect"
"strconv"
"sync"
......@@ -221,7 +222,7 @@ func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
}
// GetExtension parses and returns the given extension of pb.
// If the extension is not present it returns ErrMissingExtension.
// If the extension is not present and has no default value it returns ErrMissingExtension.
func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
if err := checkExtensionTypes(pb, extension); err != nil {
return nil, err
......@@ -230,8 +231,11 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
emap := pb.ExtensionMap()
e, ok := emap[extension.Field]
if !ok {
return nil, ErrMissingExtension
// defaultExtensionValue returns the default value or
// ErrMissingExtension if there is no default.
return defaultExtensionValue(extension)
}
if e.value != nil {
// Already decoded. Check the descriptor, though.
if e.desc != extension {
......@@ -257,12 +261,46 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
return e.value, nil
}
// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
sf, _, err := fieldDefault(t, props)
if err != nil {
return nil, err
}
if sf == nil || sf.value == nil {
// There is no default value.
return nil, ErrMissingExtension
}
if t.Kind() != reflect.Ptr {
// We do not need to return a Ptr, we can directly return sf.value.
return sf.value, nil
}
// We need to return an interface{} that is a pointer to sf.value.
value := reflect.New(t).Elem()
value.Set(reflect.New(value.Type().Elem()))
if sf.kind == reflect.Int32 {
// We may have an int32 or an enum, but the underlying data is int32.
// Since we can't set an int32 into a non int32 reflect.value directly
// set it as a int32.
value.Elem().SetInt(int64(sf.value.(int32)))
} else {
value.Elem().Set(reflect.ValueOf(sf.value))
}
return value.Interface(), nil
}
// decodeExtension decodes an extension encoded in b.
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
o := NewBuffer(b)
t := reflect.TypeOf(extension.ExtensionType)
rep := extension.repeated()
props := extensionProperties(extension)
......@@ -284,7 +322,7 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
return nil, err
}
if !rep || o.index >= len(o.buf) {
if o.index >= len(o.buf) {
break
}
}
......@@ -321,6 +359,14 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
if typ != reflect.TypeOf(value) {
return errors.New("proto: bad extension value type")
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension
// from an ErrNil due to a missing field. Extensions are
// always optional, so the encoder would just swallow the error
// and drop all the extensions from the encoded message.
if reflect.ValueOf(value).IsNil() {
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
}
pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
return nil
......
......@@ -30,12 +30,12 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Package proto converts data structures to and from the wire format of
protocol buffers. It works in concert with the Go source code generated
for .proto files by the protocol compiler.
Package proto converts data structures to and from the wire format of
protocol buffers. It works in concert with the Go source code generated
for .proto files by the protocol compiler.
A summary of the properties of the protocol buffer interface
for a protocol buffer variable v:
A summary of the properties of the protocol buffer interface
for a protocol buffer variable v:
- Names are turned from camel_case to CamelCase for export.
- There are no methods on v to set fields; just treat
......@@ -50,31 +50,38 @@
That is, optional or required field int32 f becomes F *int32.
- Repeated fields are slices.
- Helper functions are available to aid the setting of fields.
Helpers for getting values are superseded by the
GetFoo methods and their use is deprecated.
msg.Foo = proto.String("hello") // set field
- Constants are defined to hold the default values of all fields that
have them. They have the form Default_StructName_FieldName.
Because the getter methods handle defaulted values,
direct use of these constants should be rare.
- Enums are given type names and maps from names to values.
Enum values are prefixed with the enum's type name. Enum types have
a String method, and a Enum method to assist in message construction.
- Nested groups and enums have type names prefixed with the name of
Enum values are prefixed by the enclosing message's name, or by the
enum's type name if it is a top-level enum. Enum types have a String
method, and a Enum method to assist in message construction.
- Nested messages, groups and enums have type names prefixed with the name of
the surrounding message type.
- Extensions are given descriptor names that start with E_,
followed by an underscore-delimited list of the nested messages
that contain it (if any) followed by the CamelCased name of the
extension field itself. HasExtension, ClearExtension, GetExtension
and SetExtension are functions for manipulating extensions.
- Oneof field sets are given a single field in their message,
with distinguished wrapper types for each possible field value.
- Marshal and Unmarshal are functions to encode and decode the wire format.
The simplest way to describe this is to see an example.
Given file test.proto, containing
When the .proto file specifies `syntax="proto3"`, there are some differences:
- Non-repeated fields of non-message type are values instead of pointers.
- Getters are only generated for message and oneof fields.
- Enum types do not get an Enum method.
The simplest way to describe this is to see an example.
Given file test.proto, containing
package example;
enum FOO { X = 17; };
enum FOO { X = 17; }
message Test {
required string label = 1;
......@@ -83,13 +90,18 @@
optional group OptionalGroup = 4 {
required string RequiredField = 5;
}
oneof union {
int32 number = 6;
string name = 7;
}
}
The resulting file, test.pb.go, is:
The resulting file, test.pb.go, is:
package example
import "github.com/golang/protobuf/proto"
import proto "github.com/golang/protobuf/proto"
import math "math"
type FOO int32
const (
......@@ -110,49 +122,96 @@
func (x FOO) String() string {
return proto.EnumName(FOO_name, int32(x))
}
func (x *FOO) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(FOO_value, data)
if err != nil {
return err
}
*x = FOO(value)
return nil
}
type Test struct {
Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
// Types that are valid to be assigned to Union:
// *Test_Number
// *Test_Name
Union isTest_Union `protobuf_oneof:"union"`
XXX_unrecognized []byte `json:"-"`
}
func (this *Test) Reset() { *this = Test{} }
func (this *Test) String() string { return proto.CompactTextString(this) }
func (m *Test) Reset() { *m = Test{} }
func (m *Test) String() string { return proto.CompactTextString(m) }
func (*Test) ProtoMessage() {}
type isTest_Union interface {
isTest_Union()
}
type Test_Number struct {
Number int32 `protobuf:"varint,6,opt,name=number"`
}
type Test_Name struct {
Name string `protobuf:"bytes,7,opt,name=name"`
}
func (*Test_Number) isTest_Union() {}
func (*Test_Name) isTest_Union() {}
func (m *Test) GetUnion() isTest_Union {
if m != nil {
return m.Union
}
return nil
}
const Default_Test_Type int32 = 77
func (this *Test) GetLabel() string {
if this != nil && this.Label != nil {
return *this.Label
func (m *Test) GetLabel() string {
if m != nil && m.Label != nil {
return *m.Label
}
return ""
}
func (this *Test) GetType() int32 {
if this != nil && this.Type != nil {
return *this.Type
func (m *Test) GetType() int32 {
if m != nil && m.Type != nil {
return *m.Type
}
return Default_Test_Type
}
func (this *Test) GetOptionalgroup() *Test_OptionalGroup {
if this != nil {
return this.Optionalgroup
func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
if m != nil {
return m.Optionalgroup
}
return nil
}
type Test_OptionalGroup struct {
RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (this *Test_OptionalGroup) Reset() { *this = Test_OptionalGroup{} }
func (this *Test_OptionalGroup) String() string { return proto.CompactTextString(this) }
func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
func (this *Test_OptionalGroup) GetRequiredField() string {
if this != nil && this.RequiredField != nil {
return *this.RequiredField
func (m *Test_OptionalGroup) GetRequiredField() string {
if m != nil && m.RequiredField != nil {
return *m.RequiredField
}
return ""
}
func (m *Test) GetNumber() int32 {
if x, ok := m.GetUnion().(*Test_Number); ok {
return x.Number
}
return 0
}
func (m *Test) GetName() string {
if x, ok := m.GetUnion().(*Test_Name); ok {
return x.Name
}
return ""
}
......@@ -161,7 +220,7 @@
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
}
To create and play with a Test object:
To create and play with a Test object:
package main
......@@ -169,22 +228,24 @@
"log"
"github.com/golang/protobuf/proto"
"./example.pb"
pb "./example.pb"
)
func main() {
test := &example.Test{
test := &pb.Test{
Label: proto.String("hello"),
Type: proto.Int32(17),
Optionalgroup: &example.Test_OptionalGroup{
Reps: []int64{1, 2, 3},
Optionalgroup: &pb.Test_OptionalGroup{
RequiredField: proto.String("good bye"),
},
Union: &pb.Test_Name{"fred"},
}
data, err := proto.Marshal(test)
if err != nil {
log.Fatal("marshaling error: ", err)
}
newTest := new(example.Test)
newTest := &pb.Test{}
err = proto.Unmarshal(data, newTest)
if err != nil {
log.Fatal("unmarshaling error: ", err)
......@@ -193,6 +254,11 @@
if test.GetLabel() != newTest.GetLabel() {
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
}
// Use a type switch to determine which oneof was set.
switch u := test.Union.(type) {
case *pb.Test_Number: // u.Number contains the number.
case *pb.Test_Name: // u.Name contains the string.
}
// etc.
}
*/
......@@ -203,6 +269,7 @@ import (
"fmt"
"log"
"reflect"
"sort"
"strconv"
"sync"
)
......@@ -377,13 +444,13 @@ func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32,
// DebugPrint dumps the encoded data in b in a debugging format with a header
// including the string s. Used in testing but made available for general debugging.
func (o *Buffer) DebugPrint(s string, b []byte) {
func (p *Buffer) DebugPrint(s string, b []byte) {
var u uint64
obuf := o.buf
index := o.index
o.buf = b
o.index = 0
obuf := p.buf
index := p.index
p.buf = b
p.index = 0
depth := 0
fmt.Printf("\n--- %s ---\n", s)
......@@ -394,12 +461,12 @@ out:
fmt.Print(" ")
}
index := o.index
if index == len(o.buf) {
index := p.index
if index == len(p.buf) {
break
}
op, err := o.DecodeVarint()
op, err := p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: fetching op err %v\n", index, err)
break out
......@@ -416,7 +483,7 @@ out:
case WireBytes:
var r []byte
r, err = o.DecodeRawBytes(false)
r, err = p.DecodeRawBytes(false)
if err != nil {
break out
}
......@@ -437,7 +504,7 @@ out:
fmt.Printf("\n")
case WireFixed32:
u, err = o.DecodeFixed32()
u, err = p.DecodeFixed32()
if err != nil {
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
break out
......@@ -445,16 +512,15 @@ out:
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
case WireFixed64:
u, err = o.DecodeFixed64()
u, err = p.DecodeFixed64()
if err != nil {
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
break
case WireVarint:
u, err = o.DecodeVarint()
u, err = p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
break out
......@@ -462,30 +528,22 @@ out:
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
case WireStartGroup:
if err != nil {
fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d start\n", index, tag)
depth++
case WireEndGroup:
depth--
if err != nil {
fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d end\n", index, tag)
}
}
if depth != 0 {
fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
}
fmt.Printf("\n")
o.buf = obuf
o.index = index
p.buf = obuf
p.index = index
}
// SetDefaults sets unset protocol buffer fields to their default values.
......@@ -599,13 +657,15 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
for _, ni := range dm.nested {
f := v.Field(ni)
// f is *T or []*T or map[T]*T
switch f.Kind() {
case reflect.Ptr:
if f.IsNil() {
continue
}
// f is *T or []*T
if f.Kind() == reflect.Ptr {
setDefaults(f, recur, zeros)
} else {
case reflect.Slice:
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
if e.IsNil() {
......@@ -613,6 +673,15 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
}
setDefaults(e, recur, zeros)
}
case reflect.Map:
for _, k := range f.MapKeys() {
e := f.MapIndex(k)
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
}
}
}
}
......@@ -638,10 +707,6 @@ type scalarField struct {
value interface{} // the proto-declared default value, or nil
}
func ptrToStruct(t reflect.Type) bool {
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}
// t is a struct type.
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
sprop := GetProperties(t)
......@@ -653,21 +718,62 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
}
ft := t.Field(fi).Type
// nested messages
if ptrToStruct(ft) || (ft.Kind() == reflect.Slice && ptrToStruct(ft.Elem())) {
sf, nested, err := fieldDefault(ft, prop)
switch {
case err != nil:
log.Print(err)
case nested:
dm.nested = append(dm.nested, fi)
continue
case sf != nil:
sf.index = fi
dm.scalars = append(dm.scalars, *sf)
}
}
return dm
}
// fieldDefault returns the scalarField for field type ft.
// sf will be nil if the field can not have a default.
// nestedMessage will be true if this is a nested message.
// Note that sf.index is not set on return.
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
var canHaveDefault bool
switch ft.Kind() {
case reflect.Ptr:
if ft.Elem().Kind() == reflect.Struct {
nestedMessage = true
} else {
canHaveDefault = true // proto2 scalar field
}
case reflect.Slice:
switch ft.Elem().Kind() {
case reflect.Ptr:
nestedMessage = true // repeated message
case reflect.Uint8:
canHaveDefault = true // bytes field
}
sf := scalarField{
index: fi,
kind: ft.Elem().Kind(),
case reflect.Map:
if ft.Elem().Kind() == reflect.Ptr {
nestedMessage = true // map with message values
}
}
if !canHaveDefault {
if nestedMessage {
return nil, true, nil
}
return nil, false, nil
}
// We now know that ft is a pointer or slice.
sf = &scalarField{kind: ft.Elem().Kind()}
// scalar fields without defaults
if !prop.HasDefault {
dm.scalars = append(dm.scalars, sf)
continue
return sf, false, nil
}
// a scalar field: either *T or []byte
......@@ -675,36 +781,31 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
case reflect.Bool:
x, err := strconv.ParseBool(prop.Default)
if err != nil {
log.Printf("proto: bad default bool %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Float32:
x, err := strconv.ParseFloat(prop.Default, 32)
if err != nil {
log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
}
sf.value = float32(x)
case reflect.Float64:
x, err := strconv.ParseFloat(prop.Default, 64)
if err != nil {
log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Int32:
x, err := strconv.ParseInt(prop.Default, 10, 32)
if err != nil {
log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
}
sf.value = int32(x)
case reflect.Int64:
x, err := strconv.ParseInt(prop.Default, 10, 64)
if err != nil {
log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.String:
......@@ -715,26 +816,20 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
case reflect.Uint32:
x, err := strconv.ParseUint(prop.Default, 10, 32)
if err != nil {
log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
}
sf.value = uint32(x)
case reflect.Uint64:
x, err := strconv.ParseUint(prop.Default, 10, 64)
if err != nil {
log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
continue
return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
}
sf.value = x
default:
log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
continue
}
dm.scalars = append(dm.scalars, sf)
return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
}
return dm
return sf, false, nil
}
// Map fields may have key types of non-float scalars, strings and enums.
......@@ -742,10 +837,58 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
// If this turns out to be inefficient we can always consider other options,
// such as doing a Schwartzian transform.
type mapKeys []reflect.Value
func mapKeys(vs []reflect.Value) sort.Interface {
s := mapKeySorter{
vs: vs,
// default Less function: textual comparison
less: func(a, b reflect.Value) bool {
return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
},
}
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
// numeric keys are sorted numerically.
if len(vs) == 0 {
return s
}
switch vs[0].Kind() {
case reflect.Int32, reflect.Int64:
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
}
return s
}
type mapKeySorter struct {
vs []reflect.Value
less func(a, b reflect.Value) bool
}
func (s mapKeys) Len() int { return len(s) }
func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s mapKeys) Less(i, j int) bool {
return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
func (s mapKeySorter) Len() int { return len(s.vs) }
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
func (s mapKeySorter) Less(i, j int) bool {
return s.less(s.vs[i], s.vs[j])
}
// isProto3Zero reports whether v is a zero proto3 value.
func isProto3Zero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return !v.Bool()
case reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint32, reflect.Uint64:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.String:
return v.String() == ""
}
return false
}
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion1 = true
......@@ -44,11 +44,11 @@ import (
"sort"
)
// ErrNoMessageTypeId occurs when a protocol buffer does not have a message type ID.
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
// A message type ID is required for storing a protocol buffer in a message set.
var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
// The first two types (_MessageSet_Item and MessageSet)
// The first two types (_MessageSet_Item and messageSet)
// model what the protocol compiler produces for the following protocol message:
// message MessageSet {
// repeated group Item = 1 {
......@@ -58,27 +58,20 @@ var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
// }
// That is the MessageSet wire format. We can't use a proto to generate these
// because that would introduce a circular dependency between it and this package.
//
// When a proto1 proto has a field that looks like:
// optional message<MessageSet> info = 3;
// the protocol compiler produces a field in the generated struct that looks like:
// Info *_proto_.MessageSet `protobuf:"bytes,3,opt,name=info"`
// The package is automatically inserted so there is no need for that proto file to
// import this package.
type _MessageSet_Item struct {
TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
Message []byte `protobuf:"bytes,3,req,name=message"`
}
type MessageSet struct {
type messageSet struct {
Item []*_MessageSet_Item `protobuf:"group,1,rep"`
XXX_unrecognized []byte
// TODO: caching?
}
// Make sure MessageSet is a Message.
var _ Message = (*MessageSet)(nil)
// Make sure messageSet is a Message.
var _ Message = (*messageSet)(nil)
// messageTypeIder is an interface satisfied by a protocol buffer type
// that may be stored in a MessageSet.
......@@ -86,7 +79,7 @@ type messageTypeIder interface {
MessageTypeId() int32
}
func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
mti, ok := pb.(messageTypeIder)
if !ok {
return nil
......@@ -100,24 +93,24 @@ func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
return nil
}
func (ms *MessageSet) Has(pb Message) bool {
func (ms *messageSet) Has(pb Message) bool {
if ms.find(pb) != nil {
return true
}
return false
}
func (ms *MessageSet) Unmarshal(pb Message) error {
func (ms *messageSet) Unmarshal(pb Message) error {
if item := ms.find(pb); item != nil {
return Unmarshal(item.Message, pb)
}
if _, ok := pb.(messageTypeIder); !ok {
return ErrNoMessageTypeId
return errNoMessageTypeID
}
return nil // TODO: return error instead?
}
func (ms *MessageSet) Marshal(pb Message) error {
func (ms *messageSet) Marshal(pb Message) error {
msg, err := Marshal(pb)
if err != nil {
return err
......@@ -130,7 +123,7 @@ func (ms *MessageSet) Marshal(pb Message) error {
mti, ok := pb.(messageTypeIder)
if !ok {
return ErrNoMessageTypeId
return errNoMessageTypeID
}
mtid := mti.MessageTypeId()
......@@ -141,9 +134,9 @@ func (ms *MessageSet) Marshal(pb Message) error {
return nil
}
func (ms *MessageSet) Reset() { *ms = MessageSet{} }
func (ms *MessageSet) String() string { return CompactTextString(ms) }
func (*MessageSet) ProtoMessage() {}
func (ms *messageSet) Reset() { *ms = messageSet{} }
func (ms *messageSet) String() string { return CompactTextString(ms) }
func (*messageSet) ProtoMessage() {}
// Support for the message_set_wire_format message option.
......@@ -169,7 +162,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
}
sort.Ints(ids)
ms := &MessageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
for _, id := range ids {
e := m[int32(id)]
// Remove the wire type and field number varint, as well as the length varint.
......@@ -186,7 +179,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
ms := new(MessageSet)
ms := new(messageSet)
if err := Unmarshal(buf, ms); err != nil {
return err
}
......
......@@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build appengine,!appenginevm
// +build appengine
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
......@@ -144,8 +144,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
return structPointer_ifield(p, f).(*map[int32]Extension)
}
// Map returns the reflect.Value for the address of a map field in the struct.
func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
// NewAt returns the reflect.Value for a pointer to a field in the struct.
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
return structPointer_field(p, f).Addr()
}
......
......@@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !appengine appenginevm
// +build !appengine
// This file contains the implementation of the proto field accesses using package unsafe.
......@@ -130,8 +130,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// Map returns the reflect.Value for the address of a map field in the struct.
func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
// NewAt returns the reflect.Value for a pointer to a field in the struct.
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
}
......
......@@ -37,6 +37,7 @@ package proto
import (
"fmt"
"log"
"os"
"reflect"
"sort"
......@@ -84,6 +85,15 @@ type decoder func(p *Buffer, prop *Properties, base structPointer) error
// A valueDecoder decodes a single integer in a particular encoding.
type valueDecoder func(o *Buffer) (x uint64, err error)
// A oneofMarshaler does the marshaling for all oneof fields in a message.
type oneofMarshaler func(Message, *Buffer) error
// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
// A oneofSizer does the sizing for all oneof fields in a message.
type oneofSizer func(Message) int
// tagMap is an optimization over map[int]int for typical protocol buffer
// use-cases. Encoded protocol buffers are often in tag order with small tag
// numbers.
......@@ -132,6 +142,22 @@ type StructProperties struct {
order []int // list of struct field numbers in tag order
unrecField field // field id of the XXX_unrecognized []byte field
extendable bool // is this an extendable proto
oneofMarshaler oneofMarshaler
oneofUnmarshaler oneofUnmarshaler
oneofSizer oneofSizer
stype reflect.Type
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the original name of a field.
OneofTypes map[string]*OneofProperties
}
// OneofProperties represents information about a specific field in a oneof.
type OneofProperties struct {
Type reflect.Type // pointer to generated struct type for this oneof field
Field int // struct field number of the containing oneof in the message
Prop *Properties
}
// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
......@@ -156,6 +182,7 @@ type Properties struct {
Packed bool // relevant for repeated primitives only
Enum string // set for enum types only
proto3 bool // whether this is known to be a proto3 field; set for []byte only
oneof bool // whether this is a oneof field
Default string // default value
HasDefault bool // whether an explicit default was provided
......@@ -208,6 +235,9 @@ func (p *Properties) String() string {
if p.proto3 {
s += ",proto3"
}
if p.oneof {
s += ",oneof"
}
if len(p.Enum) > 0 {
s += ",enum=" + p.Enum
}
......@@ -284,6 +314,8 @@ func (p *Properties) Parse(s string) {
p.Enum = f[5:]
case f == "proto3":
p.proto3 = true
case f == "oneof":
p.oneof = true
case strings.HasPrefix(f, "def="):
p.HasDefault = true
p.Default = f[4:] // rest of string
......@@ -440,7 +472,12 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
p.enc = (*Buffer).enc_slice_byte
p.dec = (*Buffer).dec_slice_byte
p.size = size_slice_byte
if p.proto3 {
// This is a []byte, which is either a bytes field,
// or the value of a map field. In the latter case,
// we always encode an empty []byte, so we should not
// use the proto3 enc/size funcs.
// f == nil iff this is the key/value of a map field.
if p.proto3 && f != nil {
p.enc = (*Buffer).enc_proto3_slice_byte
p.size = size_proto3_slice_byte
}
......@@ -595,7 +632,7 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
}
var (
mutex sync.Mutex
propertiesMu sync.RWMutex
propertiesMap = make(map[reflect.Type]*StructProperties)
)
......@@ -605,13 +642,26 @@ func GetProperties(t reflect.Type) *StructProperties {
if t.Kind() != reflect.Struct {
panic("proto: type must have kind struct")
}
mutex.Lock()
sprop := getPropertiesLocked(t)
mutex.Unlock()
// Most calls to GetProperties in a long-running program will be
// retrieving details for types we have seen before.
propertiesMu.RLock()
sprop, ok := propertiesMap[t]
propertiesMu.RUnlock()
if ok {
if collectStats {
stats.Chit++
}
return sprop
}
propertiesMu.Lock()
sprop = getPropertiesLocked(t)
propertiesMu.Unlock()
return sprop
}
// getPropertiesLocked requires that mutex is held.
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
if collectStats {
......@@ -647,6 +697,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
if f.Name == "XXX_unrecognized" { // special case
prop.unrecField = toField(&f)
}
oneof := f.Tag.Get("protobuf_oneof") != "" // special case
prop.Prop[i] = p
prop.order[i] = i
if debug {
......@@ -656,7 +707,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
}
print("\n")
}
if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
}
}
......@@ -664,6 +715,41 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
// Re-order prop.order.
sort.Sort(prop)
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
var oots []interface{}
prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
prop.stype = t
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
oop := &OneofProperties{
Type: reflect.ValueOf(oot).Type(), // *T
Prop: new(Properties),
}
sft := oop.Type.Elem().Field(0)
oop.Prop.Name = sft.Name
oop.Prop.Parse(sft.Tag.Get("protobuf"))
// There will be exactly one interface field that
// this new value is assignable to.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Type.Kind() != reflect.Interface {
continue
}
if !oop.Type.AssignableTo(f.Type) {
continue
}
oop.Field = i
break
}
prop.OneofTypes[oop.Prop.OrigName] = oop
}
}
// build required counts
// build tags
reqCount := 0
......@@ -722,3 +808,35 @@ func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[
}
enumValueMaps[typeName] = valueMap
}
// EnumValueMap returns the mapping from names to integers of the
// enum type enumType, or a nil if not found.
func EnumValueMap(enumType string) map[string]int32 {
return enumValueMaps[enumType]
}
// A registry of all linked message types.
// The string is a fully-qualified proto name ("pkg.Message").
var (
protoTypes = make(map[string]reflect.Type)
revProtoTypes = make(map[reflect.Type]string)
)
// RegisterType is called from generated code and maps from the fully qualified
// proto name to the type (pointer to struct) of the protocol buffer.
func RegisterType(x Message, name string) {
if _, ok := protoTypes[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
protoTypes[name] = t
revProtoTypes[t] = name
}
// MessageName returns the fully-qualified proto name for the given message type.
func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
// MessageType returns the message type (pointer to struct) for a named message.
func MessageType(name string) reflect.Type { return protoTypes[name] }
# 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.
include ../../Make.protobuf
all: regenerate
regenerate:
rm -f proto3.pb.go
make proto3.pb.go
# The following rules are just aids to development. Not needed for typical testing.
diff: regenerate
git diff proto3.pb.go
// 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 testdata "github.com/golang/protobuf/proto/testdata"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
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))
}
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:"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:"result_count,omitempty"`
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman" 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:"proto2_field,omitempty"`
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
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
}
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() {}
type MessageWithMap struct {
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" 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 (m *MessageWithMap) GetByteMapping() map[bool][]byte {
if m != nil {
return m.ByteMapping
}
return nil
}
func init() {
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
}
......@@ -31,6 +31,8 @@
syntax = "proto3";
import "testdata/test.proto";
package proto3_proto;
message Message {
......@@ -51,8 +53,16 @@ message Message {
repeated uint64 key = 5;
Nested nested = 6;
map<string, Nested> terrain = 10;
testdata.SubDefaults proto2_field = 11;
map<string, testdata.SubDefaults> proto2_value = 13;
}
message Nested {
string bunny = 1;
}
message MessageWithMap {
map<bool, bytes> byte_mapping = 1;
}
......@@ -37,11 +37,11 @@ import (
"bufio"
"bytes"
"encoding"
"errors"
"fmt"
"io"
"log"
"math"
"os"
"reflect"
"sort"
"strings"
......@@ -170,20 +170,12 @@ func writeName(w *textWriter, props *Properties) error {
return nil
}
var (
messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
)
// raw is the interface satisfied by RawMessage.
type raw interface {
Bytes() []byte
}
func writeStruct(w *textWriter, sv reflect.Value) error {
if sv.Type() == messageSetType {
return writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
}
st := sv.Type()
sprops := GetProperties(st)
for i := 0; i < sv.NumField(); i++ {
......@@ -246,7 +238,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
}
if fv.Kind() == reflect.Map {
// Map fields are rendered as a repeated struct with key/value fields.
keys := fv.MapKeys() // TODO: should we sort these for deterministic output?
keys := fv.MapKeys()
sort.Sort(mapKeys(keys))
for _, key := range keys {
val := fv.MapIndex(key)
......@@ -283,6 +275,8 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
if err := w.WriteByte('\n'); err != nil {
return err
}
// nil values aren't legal, but we can avoid panicking because of them.
if val.Kind() != reflect.Ptr || !val.IsNil() {
// value
if _, err := w.WriteString("value:"); err != nil {
return err
......@@ -298,6 +292,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
if err := w.WriteByte('\n'); err != nil {
return err
}
}
// close struct
w.unindent()
if err := w.WriteByte('>'); err != nil {
......@@ -315,26 +310,34 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
}
if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
// proto3 non-repeated scalar field; skip if zero value
switch fv.Kind() {
case reflect.Bool:
if !fv.Bool() {
if isProto3Zero(fv) {
continue
}
case reflect.Int32, reflect.Int64:
if fv.Int() == 0 {
continue
}
case reflect.Uint32, reflect.Uint64:
if fv.Uint() == 0 {
continue
}
case reflect.Float32, reflect.Float64:
if fv.Float() == 0 {
if fv.Kind() == reflect.Interface {
// Check if it is a oneof.
if st.Field(i).Tag.Get("protobuf_oneof") != "" {
// fv is nil, or holds a pointer to generated struct.
// That generated struct has exactly one field,
// which has a protobuf struct tag.
if fv.IsNil() {
continue
}
case reflect.String:
if fv.String() == "" {
continue
inner := fv.Elem().Elem() // interface -> *T -> T
tag := inner.Type().Field(0).Tag.Get("protobuf")
props = new(Properties) // Overwrite the outer props var, but not its pointee.
props.Parse(tag)
// Write the value in the oneof, not the oneof itself.
fv = inner.Field(0)
// Special case to cope with malformed messages gracefully:
// If the value in the oneof is a nil pointer, don't panic
// in writeAny.
if fv.Kind() == reflect.Ptr && fv.IsNil() {
// Use errors.New so writeAny won't render quotes.
msg := errors.New("/* nil */")
fv = reflect.ValueOf(&msg).Elem()
}
}
}
......@@ -514,44 +517,6 @@ func writeString(w *textWriter, s string) error {
return w.WriteByte('"')
}
func writeMessageSet(w *textWriter, ms *MessageSet) error {
for _, item := range ms.Item {
id := *item.TypeId
if msd, ok := messageSetMap[id]; ok {
// Known message set type.
if _, err := fmt.Fprintf(w, "[%s]: <\n", msd.name); err != nil {
return err
}
w.indent()
pb := reflect.New(msd.t.Elem())
if err := Unmarshal(item.Message, pb.Interface().(Message)); err != nil {
if _, err := fmt.Fprintf(w, "/* bad message: %v */\n", err); err != nil {
return err
}
} else {
if err := writeStruct(w, pb.Elem()); err != nil {
return err
}
}
} else {
// Unknown type.
if _, err := fmt.Fprintf(w, "[%d]: <\n", id); err != nil {
return err
}
w.indent()
if err := writeUnknownStruct(w, item.Message); err != nil {
return err
}
}
w.unindent()
if _, err := w.Write(gtNewline); err != nil {
return err
}
}
return nil
}
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
if !w.compact {
if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
......@@ -666,10 +631,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
pb, err := GetExtension(ep, desc)
if err != nil {
if _, err := fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err); err != nil {
return err
}
continue
return fmt.Errorf("failed getting extension: %v", err)
}
// Repeated extensions will appear as a slice.
......
......@@ -119,6 +119,14 @@ func isWhitespace(c byte) bool {
return false
}
func isQuote(c byte) bool {
switch c {
case '"', '\'':
return true
}
return false
}
func (p *textParser) skipWhitespace() {
i := 0
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
......@@ -174,7 +182,7 @@ func (p *textParser) advance() {
}
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
if err != nil {
p.errorf("invalid quoted string %v", p.s[0:i+1])
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
return
}
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
......@@ -333,13 +341,13 @@ func (p *textParser) next() *token {
p.advance()
if p.done {
p.cur.value = ""
} else if len(p.cur.value) > 0 && p.cur.value[0] == '"' {
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
// Look for multiple quoted strings separated by whitespace,
// and concatenate them.
cat := p.cur
for {
p.skipWhitespace()
if p.done || p.s[0] != '"' {
if p.done || !isQuote(p.s[0]) {
break
}
p.advance()
......@@ -385,8 +393,7 @@ func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSet
}
// Returns the index in the struct for the named field, as well as the parsed tag properties.
func structFieldByName(st reflect.Type, name string) (int, *Properties, bool) {
sprops := GetProperties(st)
func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
i, ok := sprops.decoderOrigNames[name]
if ok {
return i, sprops.Prop[i], true
......@@ -438,7 +445,8 @@ func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseEr
func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
st := sv.Type()
reqCount := GetProperties(st).reqCount
sprops := GetProperties(st)
reqCount := sprops.reqCount
var reqFieldErr error
fieldSet := make(map[string]bool)
// A struct is a sequence of "name: value", terminated by one of
......@@ -520,16 +528,29 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
sl = reflect.Append(sl, ext)
SetExtension(ep, desc, sl.Interface())
}
} else {
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
continue
}
// This is a normal, non-extension field.
name := tok.value
fi, props, ok := structFieldByName(st, name)
if !ok {
var dst reflect.Value
fi, props, ok := structFieldByName(sprops, name)
if ok {
dst = sv.Field(fi)
} else if oop, ok := sprops.OneofTypes[name]; ok {
// It is a oneof.
props = oop.Prop
nv := reflect.New(oop.Type.Elem())
dst = nv.Elem().Field(0)
sv.Field(oop.Field).Set(nv)
}
if !dst.IsValid() {
return p.errorf("unknown field name %q in %v", name, st)
}
dst := sv.Field(fi)
if dst.Kind() == reflect.Map {
// Consume any colon.
if err := p.checkForColon(props, dst.Type()); err != nil {
......@@ -567,15 +588,21 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
if err := p.readAny(key, props.mkeyprop); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
if err := p.consumeToken("value"); err != nil {
return err
}
if err := p.consumeToken(":"); err != nil {
if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
return err
}
if err := p.readAny(val, props.mvalprop); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
if err := p.consumeToken(terminator); err != nil {
return err
}
......@@ -589,7 +616,7 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
return p.errorf("non-repeated field %q was repeated", name)
}
if err := p.checkForColon(props, st.Field(fi).Type); err != nil {
if err := p.checkForColon(props, dst.Type()); err != nil {
return err
}
......@@ -603,16 +630,11 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
} else if props.Required {
reqCount--
}
}
// For backward compatibility, permit a semicolon or comma after a field.
tok = p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ";" && tok.value != "," {
p.back()
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
}
if reqCount > 0 {
......@@ -621,6 +643,19 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
return reqFieldErr
}
// consumeOptionalSeparator consumes an optional semicolon or comma.
// It is used in readStruct to provide backward compatibility.
func (p *textParser) consumeOptionalSeparator() error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ";" && tok.value != "," {
p.back()
}
return nil
}
func (p *textParser) readAny(v reflect.Value, props *Properties) error {
tok := p.next()
if tok.err != nil {
......@@ -645,18 +680,32 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
fv.Set(reflect.ValueOf(bytes))
return nil
}
// Repeated field. May already exist.
flen := fv.Len()
if flen == fv.Cap() {
nav := reflect.MakeSlice(at, flen, 2*flen+1)
reflect.Copy(nav, fv)
fv.Set(nav)
// Repeated field.
if tok.value == "[" {
// Repeated field with list notation, like [1,2,3].
for {
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
err := p.readAny(fv.Index(fv.Len()-1), props)
if err != nil {
return err
}
fv.SetLen(flen + 1)
// Read one.
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == "]" {
break
}
if tok.value != "," {
return p.errorf("Expected ']' or ',' found %q", tok.value)
}
}
return nil
}
// One value of the repeated field.
p.back()
return p.readAny(fv.Index(flen), props)
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
return p.readAny(fv.Index(fv.Len()-1), props)
case reflect.Bool:
// Either "true", "false", 1 or 0.
switch tok.value {
......
......@@ -10,8 +10,11 @@ Status:
* The client work has just started but shares a lot of code
is coming along much quicker.
Docs are at https://godoc.org/github.com/bradfitz/http2
Docs are at https://godoc.org/golang.org/x/net/http2
Demo test server at https://http2.golang.org/
Help & bug reports welcome.
Help & bug reports welcome!
Contributing: https://golang.org/doc/contribute.html
Bugs: https://github.com/golang/go/issues/new?title=x/net/http2:+
......@@ -20,6 +20,7 @@ type buffer struct {
var (
errReadEmpty = errors.New("read from empty buffer")
errWriteClosed = errors.New("write on closed buffer")
errWriteFull = errors.New("write on full buffer")
)
......@@ -45,7 +46,7 @@ func (b *buffer) Len() int {
// It is an error to write more data than the buffer can hold.
func (b *buffer) Write(p []byte) (n int, err error) {
if b.closed {
return 0, errors.New("closed")
return 0, errWriteClosed
}
// Slide existing data to beginning.
......
......@@ -85,8 +85,8 @@ const (
// Continuation Frame
FlagContinuationEndHeaders Flags = 0x4
FlagPushPromiseEndHeaders = 0x4
FlagPushPromisePadded = 0x8
FlagPushPromiseEndHeaders Flags = 0x4
FlagPushPromisePadded Flags = 0x8
)
var flagName = map[FrameType]map[Flags]string{
......
......@@ -14,16 +14,20 @@ import (
"bytes"
"errors"
"fmt"
"os"
"runtime"
"strconv"
"sync"
)
var DebugGoroutines = false
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
type goroutineLock uint64
func newGoroutineLock() goroutineLock {
if !DebugGoroutines {
return 0
}
return goroutineLock(curGoroutineID())
}
......
......@@ -31,7 +31,7 @@ import (
"camlistore.org/pkg/googlestorage"
"camlistore.org/pkg/singleflight"
"github.com/bradfitz/http2"
"golang.org/x/net/http2"
)
var (
......@@ -51,7 +51,7 @@ func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
<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/bradfitz/http2">https://github.com/bradfitz/http2</a>.</p>
<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>`)
}
......@@ -73,12 +73,12 @@ href="https://http2.github.io/">HTTP/2</a> demo & interop server.</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 currently at <a
href="https://github.com/bradfitz/http2">github.com/bradfitz/http2</a>
href="https://golang.org/x/net/http2">github.com/bradfitz/http2</a>
but will move to the Go standard library at some point in the future
(enabled by default, without users needing to change their code).</p>
<p>Contact info: <i>bradfitz@golang.org</i>, or <a
href="https://github.com/bradfitz/http2/issues">file a bug</a>.</p>
href="https://golang.org/x/net/http2/issues">file a bug</a>.</p>
<h2>Handlers for testing</h2>
<ul>
......@@ -287,7 +287,7 @@ func newGopherTilesHandler() http.Handler {
return
}
}
io.WriteString(w, "<html><body>")
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
......@@ -305,7 +305,16 @@ func newGopherTilesHandler() http.Handler {
}
io.WriteString(w, "<br/>\n")
}
io.WriteString(w, "<hr><a href='/'>&lt;&lt Back to Go HTTP/2 demo server</a></body></html>")
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='/'>&lt;&lt Back to Go HTTP/2 demo server</a></body></html>`)
})
}
......
......@@ -20,8 +20,9 @@ import (
"strings"
"time"
"code.google.com/p/goauth2/oauth"
compute "code.google.com/p/google-api-go-client/compute/v1"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
compute "google.golang.org/api/compute/v1"
)
var (
......@@ -44,19 +45,18 @@ func readFile(v string) string {
return strings.TrimSpace(string(slurp))
}
var config = &oauth.Config{
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"),
ClientID: readFile("client-id.dat"),
ClientSecret: readFile("client-secret.dat"),
Scope: strings.Join([]string{
Endpoint: google.Endpoint,
Scopes: []string{
compute.DevstorageFull_controlScope,
compute.ComputeScope,
"https://www.googleapis.com/auth/sqlservice",
"https://www.googleapis.com/auth/sqlservice.admin",
}, " "),
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token",
},
RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
}
......@@ -88,31 +88,32 @@ func main() {
prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
tr := &oauth.Transport{
Config: config,
}
tokenCache := oauth.CacheFile("token.dat")
token, err := tokenCache.Token()
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", string(tokenCache), err)
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 = tr.Exchange(authCode)
token, err = config.Exchange(oauth2.NoContext, authCode)
if err != nil {
log.Fatalf("Error exchanging auth code for a token: %v", err)
}
tokenCache.PutToken(token)
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)
tr.Token = token
oauthClient := &http.Client{Transport: tr}
if *writeObject != "" {
writeCloudStorageObject(oauthClient)
return
......@@ -277,3 +278,25 @@ func writeCloudStorageObject(httpClient *http.Client) {
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)
}
# 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.
// 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.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE
/*
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")
)
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()
os.Exit(1)
}
// 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()
}
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 {
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)
}
......@@ -13,7 +13,7 @@
// ConfigureServer. That ConfigureServer call will likely be automatic
// or available via an empty import in the future.
//
// This package currently targets draft-14. See http://http2.github.io/
// See http://http2.github.io/
package http2
import (
......
......@@ -55,7 +55,7 @@ import (
"sync"
"time"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/http2/hpack"
)
const (
......@@ -631,6 +631,9 @@ func (sc *serverConn) serve() {
case wm := <-sc.wantWriteFrameCh:
sc.writeFrame(wm)
case <-sc.wroteFrameCh:
if sc.writingFrame != true {
panic("internal error: expected to be already writing a frame")
}
sc.writingFrame = false
sc.scheduleFrameWrite()
case fg, ok := <-sc.readFrameCh:
......@@ -752,6 +755,7 @@ func (sc *serverConn) startFrameWrite(wm frameWriteMsg) {
if sc.writingFrame {
panic("internal error: can only be writing one frame at a time")
}
sc.writingFrame = true
st := wm.stream
if st != nil {
......@@ -768,7 +772,6 @@ func (sc *serverConn) startFrameWrite(wm frameWriteMsg) {
}
}
sc.writingFrame = true
sc.needsFrameFlush = true
if endsStream(wm.write) {
if st == nil {
......
......@@ -19,7 +19,7 @@ import (
"strings"
"sync"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/http2/hpack"
)
type Transport struct {
......@@ -186,7 +186,7 @@ func (t *Transport) newClientConn(host, port, key string) (*clientConn, error) {
NextProtos: []string{NextProtoTLS},
InsecureSkipVerify: t.InsecureTLSDial,
}
tconn, err := tls.Dial("tcp", host+":"+port, cfg)
tconn, err := tls.Dial("tcp", net.JoinHostPort(host, port), cfg)
if err != nil {
return nil, err
}
......
......@@ -13,7 +13,7 @@ import (
"net/http"
"time"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/http2/hpack"
)
// writeFramer is implemented by any type that is used to write frames.
......
language: go
before_install:
- go get github.com/axw/gocov/gocov
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
install:
- mkdir -p "$GOPATH/src/google.golang.org"
- mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/google.golang.org/grpc"
script:
- make test testrace
- make coverage
# Authentication
As outlined <a href="https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md">here</a> gRPC supports 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.
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
......
......@@ -45,3 +45,6 @@ testrace: testdeps
clean:
go clean google.golang.org/grpc/...
coverage: testdeps
./coverage.sh --coveralls
......@@ -2,12 +2,12 @@
[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc)
The Go implementation of [gRPC](https://github.com/grpc/grpc)
The Go implementation of [gRPC](http://www.grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start](http://www.grpc.io/docs/) guide.
Installation
------------
To install this package, you need to install Go 1.4 and setup your Go workspace on your computer. The simplest way to install the library is to run:
To install this package, you need to install Go 1.4 or above and setup your Go workspace on your computer. The simplest way to install the library is to run:
```
$ go get google.golang.org/grpc
......@@ -18,11 +18,15 @@ Prerequisites
This requires Go 1.4 or above.
Constraints
-----------
The grpc package should only depend on standard Go packages and a small number of exceptions. If your contribution introduces new dependencies which are NOT in the [list](http://godoc.org/google.golang.org/grpc?imports), you need a discussion with gRPC-Go authors and consultants.
Documentation
-------------
You can find more detailed documentation and examples in the [examples directory](examples/).
See [API documentation](https://godoc.org/google.golang.org/grpc) for package and API descriptions and find examples in the [examples directory](examples/).
Status
------
Alpha - ready for early adopters.
Beta release
......@@ -92,13 +92,6 @@ func closeLoopUnary() {
func closeLoopStream() {
s, conn, tc := buildConnection()
stream, err := tc.StreamingCall(context.Background())
if err != nil {
grpclog.Fatalf("%v.StreamingCall(_) = _, %v", tc, err)
}
for i := 0; i < 100; i++ {
streamCaller(tc, stream)
}
ch := make(chan int, *maxConcurrentRPCs*4)
var (
mu sync.Mutex
......@@ -108,7 +101,15 @@ func closeLoopStream() {
// Distribute RPCs over maxConcurrentCalls workers.
for i := 0; i < *maxConcurrentRPCs; i++ {
go func() {
for _ = range ch {
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)
......
......@@ -27,6 +27,8 @@ It has these top-level messages:
package grpc_testing
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
......@@ -34,11 +36,13 @@ import (
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// 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
......@@ -65,6 +69,7 @@ var PayloadType_value = map[string]int32{
func (x PayloadType) String() string {
return proto.EnumName(PayloadType_name, int32(x))
}
func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type ClientType int32
......@@ -85,6 +90,7 @@ var ClientType_value = map[string]int32{
func (x ClientType) String() string {
return proto.EnumName(ClientType_name, int32(x))
}
func (ClientType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type ServerType int32
......@@ -105,6 +111,7 @@ var ServerType_value = map[string]int32{
func (x ServerType) String() string {
return proto.EnumName(ServerType_name, int32(x))
}
func (ServerType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type RpcType int32
......@@ -125,6 +132,7 @@ var RpcType_value = map[string]int32{
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
......@@ -134,6 +142,7 @@ type StatsRequest struct {
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
......@@ -147,6 +156,7 @@ type ServerStats struct {
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.
......@@ -158,6 +168,7 @@ type Payload struct {
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"`
......@@ -171,6 +182,7 @@ type HistogramData struct {
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"`
......@@ -187,6 +199,7 @@ type ClientConfig struct {
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 {
......@@ -195,30 +208,129 @@ 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 {
Setup *ClientConfig `protobuf:"bytes,1,opt,name=setup" json:"setup,omitempty"`
Mark *Mark `protobuf:"bytes,2,opt,name=mark" json:"mark,omitempty"`
// 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} }
func (m *ClientArgs) GetSetup() *ClientConfig {
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.Setup
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 m != nil {
return m.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"`
......@@ -229,6 +341,7 @@ type ClientStats struct {
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 {
......@@ -244,6 +357,7 @@ type ClientStatus struct {
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 {
......@@ -261,30 +375,129 @@ type ServerConfig struct {
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 {
Setup *ServerConfig `protobuf:"bytes,1,opt,name=setup" json:"setup,omitempty"`
Mark *Mark `protobuf:"bytes,2,opt,name=mark" json:"mark,omitempty"`
// 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} }
func (m *ServerArgs) GetSetup() *ServerConfig {
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.Setup
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 m != nil {
return m.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"`
......@@ -293,6 +506,7 @@ type ServerStatus struct {
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 {
......@@ -315,6 +529,7 @@ type SimpleRequest struct {
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 {
......@@ -330,6 +545,7 @@ type SimpleResponse struct {
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 {
......@@ -339,12 +555,30 @@ func (m *SimpleResponse) GetPayload() *Payload {
}
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 {
......@@ -419,9 +653,9 @@ func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
s.RegisterService(&_TestService_serviceDesc, srv)
}
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(SimpleRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
......@@ -639,3 +873,69 @@ var _Worker_serviceDesc = grpc.ServiceDesc{
},
},
}
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,
}
......@@ -17,7 +17,7 @@ enum PayloadType {
message StatsRequest {
// run number
optional int32 test_num = 1;
int32 test_num = 1;
}
message ServerStats {
......
......@@ -34,13 +34,13 @@
package grpc
import (
"bytes"
"io"
"time"
"golang.org/x/net/context"
"golang.org/x/net/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/transport"
)
......@@ -48,7 +48,7 @@ import (
// On error, it returns the error and indicates whether the call should be retried.
//
// TODO(zhaoq): Check whether the received message sequence is valid.
func recvResponse(codec Codec, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error {
func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error {
// Try to acquire header metadata from the server if there is any.
var err error
c.headerMD, err = stream.Header()
......@@ -57,7 +57,7 @@ func recvResponse(codec Codec, t transport.ClientTransport, c *callInfo, stream
}
p := &parser{s: stream}
for {
if err = recv(p, codec, reply); err != nil {
if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil {
if err == io.EOF {
break
}
......@@ -69,7 +69,7 @@ func recvResponse(codec Codec, t transport.ClientTransport, c *callInfo, stream
}
// sendRequest writes out various information of an RPC such as Context and Message.
func sendRequest(ctx context.Context, codec Codec, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) {
func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) {
stream, err := t.NewStream(ctx, callHdr)
if err != nil {
return nil, err
......@@ -81,8 +81,11 @@ func sendRequest(ctx context.Context, codec Codec, callHdr *transport.CallHdr, t
}
}
}()
// TODO(zhaoq): Support compression.
outBuf, err := encode(codec, args, compressionNone)
var cbuf *bytes.Buffer
if compressor != nil {
cbuf = new(bytes.Buffer)
}
outBuf, err := encode(codec, args, compressor, cbuf)
if err != nil {
return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err)
}
......@@ -94,14 +97,6 @@ func sendRequest(ctx context.Context, codec Codec, callHdr *transport.CallHdr, t
return stream, nil
}
// callInfo contains all related configuration and information about an RPC.
type callInfo struct {
failFast bool
headerMD metadata.MD
trailerMD metadata.MD
traceInfo traceInfo // in trace.go
}
// Invoke is called by the generated code. It sends the RPC request on the
// wire and returns after response is received.
func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) {
......@@ -116,7 +111,6 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
o.after(&c)
}
}()
if EnableTracing {
c.traceInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
defer c.traceInfo.tr.Finish()
......@@ -133,16 +127,11 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
}
}()
}
callHdr := &transport.CallHdr{
Host: cc.authority,
Method: method,
}
topts := &transport.Options{
Last: true,
Delay: false,
}
var (
ts int // track the transport sequence number
lastErr error // record the error that happened
)
for {
......@@ -155,7 +144,14 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
if lastErr != nil && c.failFast {
return toRPCErr(lastErr)
}
t, ts, err = cc.wait(ctx, ts)
callHdr := &transport.CallHdr{
Host: cc.authority,
Method: method,
}
if cc.dopts.cp != nil {
callHdr.SendCompress = cc.dopts.cp.Type()
}
t, err = cc.dopts.picker.Pick(ctx)
if err != nil {
if lastErr != nil {
// This was a retry; return the error from the last attempt.
......@@ -166,7 +162,7 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
if c.traceInfo.tr != nil {
c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)
}
stream, err = sendRequest(ctx, cc.dopts.codec, callHdr, t, args, topts)
stream, err = sendRequest(ctx, cc.dopts.codec, cc.dopts.cp, callHdr, t, args, topts)
if err != nil {
if _, ok := err.(transport.ConnectionError); ok {
lastErr = err
......@@ -178,7 +174,7 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
return toRPCErr(err)
}
// Receive the response
lastErr = recvResponse(cc.dopts.codec, t, &c, stream, reply)
lastErr = recvResponse(cc.dopts, t, &c, stream, reply)
if _, ok := lastErr.(transport.ConnectionError); ok {
continue
}
......
......@@ -42,6 +42,7 @@ import (
"time"
"golang.org/x/net/context"
"golang.org/x/net/trace"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/transport"
......@@ -72,6 +73,9 @@ var (
// values passed to Dial.
type dialOptions struct {
codec Codec
cp Compressor
dc Decompressor
picker Picker
block bool
insecure bool
copts transport.ConnectOptions
......@@ -87,6 +91,29 @@ func WithCodec(c Codec) DialOption {
}
}
// WithCompressor returns a DialOption which sets a CompressorGenerator for generating message
// compressor.
func WithCompressor(cp Compressor) DialOption {
return func(o *dialOptions) {
o.cp = cp
}
}
// WithDecompressor returns a DialOption which sets a DecompressorGenerator for generating
// message decompressor.
func WithDecompressor(dc Decompressor) DialOption {
return func(o *dialOptions) {
o.dc = dc
}
}
// WithPicker returns a DialOption which sets a picker for connection selection.
func WithPicker(p Picker) DialOption {
return func(o *dialOptions) {
o.picker = p
}
}
// WithBlock returns a DialOption which makes caller of Dial blocks until the underlying
// connection is up. Without this, Dial returns immediately and connecting the server
// happens in background.
......@@ -96,6 +123,8 @@ func WithBlock() DialOption {
}
}
// WithInsecure returns a DialOption which disables transport security for this ClientConn.
// Note that transport security is required unless WithInsecure is set.
func WithInsecure() DialOption {
return func(o *dialOptions) {
o.insecure = true
......@@ -141,62 +170,29 @@ func WithUserAgent(s string) DialOption {
// Dial creates a client connection the given target.
func Dial(target string, opts ...DialOption) (*ClientConn, error) {
if target == "" {
return nil, ErrUnspecTarget
}
cc := &ClientConn{
target: target,
shutdownChan: make(chan struct{}),
}
for _, opt := range opts {
opt(&cc.dopts)
}
if !cc.dopts.insecure {
var ok bool
for _, c := range cc.dopts.copts.AuthOptions {
if _, ok := c.(credentials.TransportAuthenticator); !ok {
continue
}
ok = true
}
if !ok {
return nil, ErrNoTransportSecurity
if cc.dopts.codec == nil {
// Set the default codec.
cc.dopts.codec = protoCodec{}
}
} else {
for _, c := range cc.dopts.copts.AuthOptions {
if c.RequireTransportSecurity() {
return nil, ErrCredentialsMisuse
if cc.dopts.picker == nil {
cc.dopts.picker = &unicastPicker{
target: target,
}
}
if err := cc.dopts.picker.Init(cc); err != nil {
return nil, err
}
colonPos := strings.LastIndex(target, ":")
if colonPos == -1 {
colonPos = len(target)
}
cc.authority = target[:colonPos]
if cc.dopts.codec == nil {
// Set the default codec.
cc.dopts.codec = protoCodec{}
}
cc.stateCV = sync.NewCond(&cc.mu)
if cc.dopts.block {
if err := cc.resetTransport(false); err != nil {
cc.Close()
return nil, err
}
// Start to monitor the error status of transport.
go cc.transportMonitor()
} else {
// Start a goroutine connecting to the server asynchronously.
go func() {
if err := cc.resetTransport(false); err != nil {
grpclog.Printf("Failed to dial %s: %v; please retry.", target, err)
cc.Close()
return
}
go cc.transportMonitor()
}()
}
return cc, nil
}
......@@ -212,7 +208,7 @@ const (
Ready
// TransientFailure indicates the ClientConn has seen a failure but expects to recover.
TransientFailure
// Shutdown indicates the ClientConn has stated shutting down.
// Shutdown indicates the ClientConn has started shutting down.
Shutdown
)
......@@ -238,7 +234,33 @@ type ClientConn struct {
target string
authority string
dopts dialOptions
}
// State returns the connectivity state of cc.
// This is EXPERIMENTAL API.
func (cc *ClientConn) State() (ConnectivityState, error) {
return cc.dopts.picker.State()
}
// WaitForStateChange blocks until the state changes to something other than the sourceState.
// It returns the new state or error.
// This is EXPERIMENTAL API.
func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
return cc.dopts.picker.WaitForStateChange(ctx, sourceState)
}
// Close starts to tear down the ClientConn.
func (cc *ClientConn) Close() error {
return cc.dopts.picker.Close()
}
// Conn is a client connection to a single destination.
type Conn struct {
target string
dopts dialOptions
resetChan chan int
shutdownChan chan struct{}
events trace.EventLog
mu sync.Mutex
state ConnectivityState
......@@ -246,39 +268,100 @@ type ClientConn struct {
// ready is closed and becomes nil when a new transport is up or failed
// due to timeout.
ready chan struct{}
// Every time a new transport is created, this is incremented by 1. Used
// to avoid trying to recreate a transport while the new one is already
// under construction.
transportSeq int
transport transport.ClientTransport
}
// State returns the connectivity state of the ClientConn
func (cc *ClientConn) State() ConnectivityState {
// NewConn creates a Conn.
func NewConn(cc *ClientConn) (*Conn, error) {
if cc.target == "" {
return nil, ErrUnspecTarget
}
c := &Conn{
target: cc.target,
dopts: cc.dopts,
resetChan: make(chan int, 1),
shutdownChan: make(chan struct{}),
}
if EnableTracing {
c.events = trace.NewEventLog("grpc.ClientConn", c.target)
}
if !c.dopts.insecure {
var ok bool
for _, cd := range c.dopts.copts.AuthOptions {
if _, ok := cd.(credentials.TransportAuthenticator); !ok {
continue
}
ok = true
}
if !ok {
return nil, ErrNoTransportSecurity
}
} else {
for _, cd := range c.dopts.copts.AuthOptions {
if cd.RequireTransportSecurity() {
return nil, ErrCredentialsMisuse
}
}
}
c.stateCV = sync.NewCond(&c.mu)
if c.dopts.block {
if err := c.resetTransport(false); err != nil {
c.Close()
return nil, err
}
// Start to monitor the error status of transport.
go c.transportMonitor()
} else {
// Start a goroutine connecting to the server asynchronously.
go func() {
if err := c.resetTransport(false); err != nil {
grpclog.Printf("Failed to dial %s: %v; please retry.", c.target, err)
c.Close()
return
}
c.transportMonitor()
}()
}
return c, nil
}
// printf records an event in cc's event log, unless cc has been closed.
// REQUIRES cc.mu is held.
func (cc *Conn) printf(format string, a ...interface{}) {
if cc.events != nil {
cc.events.Printf(format, a...)
}
}
// errorf records an error in cc's event log, unless cc has been closed.
// REQUIRES cc.mu is held.
func (cc *Conn) errorf(format string, a ...interface{}) {
if cc.events != nil {
cc.events.Errorf(format, a...)
}
}
// State returns the connectivity state of the Conn
func (cc *Conn) State() ConnectivityState {
cc.mu.Lock()
defer cc.mu.Unlock()
return cc.state
}
// WaitForStateChange blocks until the state changes to something other than the sourceState
// or timeout fires. It returns false if timeout fires and true otherwise.
func (cc *ClientConn) WaitForStateChange(timeout time.Duration, sourceState ConnectivityState) bool {
start := time.Now()
// WaitForStateChange blocks until the state changes to something other than the sourceState.
func (cc *Conn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
cc.mu.Lock()
defer cc.mu.Unlock()
if sourceState != cc.state {
return true
}
expired := timeout <= time.Since(start)
if expired {
return false
return cc.state, nil
}
done := make(chan struct{})
var err error
go func() {
select {
case <-time.After(timeout - time.Since(start)):
case <-ctx.Done():
cc.mu.Lock()
expired = true
err = ctx.Err()
cc.stateCV.Broadcast()
cc.mu.Unlock()
case <-done:
......@@ -287,31 +370,38 @@ func (cc *ClientConn) WaitForStateChange(timeout time.Duration, sourceState Conn
defer close(done)
for sourceState == cc.state {
cc.stateCV.Wait()
if expired {
return false
if err != nil {
return cc.state, err
}
}
return true
return cc.state, nil
}
// NotifyReset tries to signal the underlying transport needs to be reset due to
// for example a name resolution change in flight.
func (cc *Conn) NotifyReset() {
select {
case cc.resetChan <- 0:
default:
}
}
func (cc *ClientConn) resetTransport(closeTransport bool) error {
func (cc *Conn) resetTransport(closeTransport bool) error {
var retries int
start := time.Now()
for {
cc.mu.Lock()
cc.state = Connecting
cc.stateCV.Broadcast()
t := cc.transport
ts := cc.transportSeq
// Avoid wait() picking up a dying transport unnecessarily.
cc.transportSeq = 0
cc.printf("connecting")
if cc.state == Shutdown {
// cc.Close() has been invoked.
cc.mu.Unlock()
return ErrClientConnClosing
}
cc.state = Connecting
cc.stateCV.Broadcast()
cc.mu.Unlock()
if closeTransport {
t.Close()
cc.transport.Close()
}
// Adjust timeout for the current try.
copts := cc.dopts.copts
......@@ -335,11 +425,25 @@ func (cc *ClientConn) resetTransport(closeTransport bool) error {
copts.Timeout = timeout
}
connectTime := time.Now()
newTransport, err := transport.NewClientTransport(cc.target, &copts)
addr, err := cc.dopts.picker.PickAddr()
var newTransport transport.ClientTransport
if err == nil {
newTransport, err = transport.NewClientTransport(addr, &copts)
}
if err != nil {
cc.mu.Lock()
if cc.state == Shutdown {
// cc.Close() has been invoked.
cc.mu.Unlock()
return ErrClientConnClosing
}
cc.errorf("transient failure: %v", err)
cc.state = TransientFailure
cc.stateCV.Broadcast()
if cc.ready != nil {
close(cc.ready)
cc.ready = nil
}
cc.mu.Unlock()
sleepTime -= time.Since(connectTime)
if sleepTime < 0 {
......@@ -347,16 +451,20 @@ func (cc *ClientConn) resetTransport(closeTransport bool) error {
}
// Fail early before falling into sleep.
if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) {
cc.mu.Lock()
cc.errorf("connection timeout")
cc.mu.Unlock()
cc.Close()
return ErrClientConnTimeout
}
closeTransport = false
time.Sleep(sleepTime)
retries++
grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
grpclog.Printf("grpc: Conn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
continue
}
cc.mu.Lock()
cc.printf("ready")
if cc.state == Shutdown {
// cc.Close() has been invoked.
cc.mu.Unlock()
......@@ -366,7 +474,6 @@ func (cc *ClientConn) resetTransport(closeTransport bool) error {
cc.state = Ready
cc.stateCV.Broadcast()
cc.transport = newTransport
cc.transportSeq = ts + 1
if cc.ready != nil {
close(cc.ready)
cc.ready = nil
......@@ -376,44 +483,64 @@ func (cc *ClientConn) resetTransport(closeTransport bool) error {
}
}
func (cc *Conn) reconnect() bool {
cc.mu.Lock()
if cc.state == Shutdown {
// cc.Close() has been invoked.
cc.mu.Unlock()
return false
}
cc.state = TransientFailure
cc.stateCV.Broadcast()
cc.mu.Unlock()
if err := cc.resetTransport(true); err != nil {
// The ClientConn is closing.
cc.mu.Lock()
cc.printf("transport exiting: %v", err)
cc.mu.Unlock()
grpclog.Printf("grpc: Conn.transportMonitor exits due to: %v", err)
return false
}
return true
}
// Run in a goroutine to track the error in transport and create the
// new transport if an error happens. It returns when the channel is closing.
func (cc *ClientConn) transportMonitor() {
func (cc *Conn) transportMonitor() {
for {
select {
// shutdownChan is needed to detect the teardown when
// the ClientConn is idle (i.e., no RPC in flight).
case <-cc.shutdownChan:
return
case <-cc.resetChan:
if !cc.reconnect() {
return
}
case <-cc.transport.Error():
cc.mu.Lock()
cc.state = TransientFailure
cc.stateCV.Broadcast()
cc.mu.Unlock()
if err := cc.resetTransport(true); err != nil {
// The ClientConn is closing.
grpclog.Printf("grpc: ClientConn.transportMonitor exits due to: %v", err)
if !cc.reconnect() {
return
}
continue
// Tries to drain reset signal if there is any since it is out-dated.
select {
case <-cc.resetChan:
default:
}
}
}
}
// When wait returns, either the new transport is up or ClientConn is
// closing. Used to avoid working on a dying transport. It updates and
// returns the transport and its version when there is no error.
func (cc *ClientConn) wait(ctx context.Context, ts int) (transport.ClientTransport, int, error) {
// Wait blocks until i) the new transport is up or ii) ctx is done or iii) cc is closed.
func (cc *Conn) Wait(ctx context.Context) (transport.ClientTransport, error) {
for {
cc.mu.Lock()
switch {
case cc.state == Shutdown:
cc.mu.Unlock()
return nil, 0, ErrClientConnClosing
case ts < cc.transportSeq:
// Worked on a dying transport. Try the new one immediately.
defer cc.mu.Unlock()
return cc.transport, cc.transportSeq, nil
return nil, ErrClientConnClosing
case cc.state == Ready:
cc.mu.Unlock()
return cc.transport, nil
default:
ready := cc.ready
if ready == nil {
......@@ -423,7 +550,7 @@ func (cc *ClientConn) wait(ctx context.Context, ts int) (transport.ClientTranspo
cc.mu.Unlock()
select {
case <-ctx.Done():
return nil, 0, transport.ContextErr(ctx.Err())
return nil, transport.ContextErr(ctx.Err())
// Wait until the new transport is ready or failed.
case <-ready:
}
......@@ -431,12 +558,12 @@ func (cc *ClientConn) wait(ctx context.Context, ts int) (transport.ClientTranspo
}
}
// Close starts to tear down the ClientConn. Returns ErrClientConnClosing if
// Close starts to tear down the Conn. Returns ErrClientConnClosing if
// it has been closed (mostly due to dial time-out).
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
// some edge cases (e.g., the caller opens and closes many ClientConn's in a
// tight loop.
func (cc *ClientConn) Close() error {
func (cc *Conn) Close() error {
cc.mu.Lock()
defer cc.mu.Unlock()
if cc.state == Shutdown {
......@@ -444,6 +571,10 @@ func (cc *ClientConn) Close() error {
}
cc.state = Shutdown
cc.stateCV.Broadcast()
if cc.events != nil {
cc.events.Finish()
cc.events = nil
}
if cc.ready != nil {
close(cc.ready)
cc.ready = nil
......
#!/bin/bash
set -e
workdir=.cover
profile="$workdir/cover.out"
mode=set
end2endtest="google.golang.org/grpc/test"
generate_cover_data() {
rm -rf "$workdir"
mkdir "$workdir"
for pkg in "$@"; do
if [ $pkg == "google.golang.org/grpc" -o $pkg == "google.golang.org/grpc/transport" -o $pkg == "google.golang.org/grpc/metadata" -o $pkg == "google.golang.org/grpc/credentials" ]
then
f="$workdir/$(echo $pkg | tr / -)"
go test -covermode="$mode" -coverprofile="$f.cover" "$pkg"
go test -covermode="$mode" -coverpkg "$pkg" -coverprofile="$f.e2e.cover" "$end2endtest"
fi
done
echo "mode: $mode" >"$profile"
grep -h -v "^mode:" "$workdir"/*.cover >>"$profile"
}
show_cover_report() {
go tool cover -${1}="$profile"
}
push_to_coveralls() {
goveralls -coverprofile="$profile"
}
generate_cover_data $(go list ./...)
show_cover_report func
case "$1" in
"")
;;
--html)
show_cover_report html ;;
--coveralls)
push_to_coveralls ;;
*)
echo >&2 "error: invalid option: $1" ;;
esac
rm -rf "$workdir"
......@@ -87,19 +87,6 @@ type AuthInfo interface {
AuthType() string
}
type authInfoKey struct{}
// NewContext creates a new context with authInfo attached.
func NewContext(ctx context.Context, authInfo AuthInfo) context.Context {
return context.WithValue(ctx, authInfoKey{}, authInfo)
}
// FromContext returns the authInfo in ctx if it exists.
func FromContext(ctx context.Context) (authInfo AuthInfo, ok bool) {
authInfo, ok = ctx.Value(authInfoKey{}).(AuthInfo)
return
}
// TransportAuthenticator defines the common interface for all the live gRPC wire
// protocols and supported transport security protocols (e.g., TLS, SSL).
type TransportAuthenticator interface {
......@@ -119,7 +106,7 @@ type TransportAuthenticator interface {
// TLSInfo contains the auth information for a TLS authenticated connection.
// It implements the AuthInfo interface.
type TLSInfo struct {
state tls.ConnectionState
State tls.ConnectionState
}
func (t TLSInfo) AuthType() string {
......
......@@ -3,14 +3,15 @@ gRPC in 3 minutes (Go)
BACKGROUND
-------------
For this sample, we've already generated the server and client stubs from [helloworld.proto](examples/helloworld/proto/helloworld.proto).
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)
```sh
```
$ go help gopath
$ # ensure the PATH contains $GOPATH/bin
$ export PATH=$PATH:$GOPATH/bin
......@@ -19,35 +20,38 @@ $ export PATH=$PATH:$GOPATH/bin
INSTALL
-------
```sh
$ go get -u github.com/grpc/grpc-go/examples/greeter_client
$ go get -u github.com/grpc/grpc-go/examples/greeter_server
```
$ 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
```sh
```
$ greeter_server &
```
- Run the client
```sh
```
$ greeter_client
```
OPTIONAL - Rebuilding the generated code
----------------------------------------
1 First [install protoc](https://github.com/google/protobuf/blob/master/INSTALL.txt)
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.
```sh
```
$ go get -a github.com/golang/protobuf/protoc-gen-go
$
$ # from this dir; invoke protoc
$ protoc -I ./helloworld/proto/ ./helloworld/proto/helloworld.proto --go_out=plugins=grpc:helloworld
$ protoc -I ./helloworld/helloworld/ ./helloworld/helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
```
......@@ -33,7 +33,7 @@ You also should have the relevant tools installed to generate the server and cli
## Defining the service
Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) 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).
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:
......@@ -227,7 +227,7 @@ func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) e
}
```
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 `Read()` 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.
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()`.
......
......@@ -46,7 +46,7 @@ const (
port = ":50051"
)
// server is used to implement hellowrld.GreeterServer.
// server is used to implement helloworld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
......
......@@ -15,6 +15,8 @@ It has these top-level messages:
package helloworld
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
......@@ -22,11 +24,13 @@ import (
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// 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 {
......@@ -36,6 +40,7 @@ type HelloRequest struct {
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 {
......@@ -45,10 +50,17 @@ type HelloReply struct {
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 {
......@@ -84,9 +96,9 @@ func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv)
}
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(HelloRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(GreeterServer).SayHello(ctx, in)
......@@ -107,3 +119,19 @@ var _Greeter_serviceDesc = grpc.ServiceDesc{
},
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,
}
......@@ -29,7 +29,9 @@
syntax = "proto3";
option java_package = "io.grpc.examples";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
......
......@@ -2,7 +2,7 @@
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 [Getting Started Guide for Go] (examples/gotutorial.md) for more information.
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.
......
......@@ -3,7 +3,7 @@
// DO NOT EDIT!
/*
Package proto is a generated protocol buffer package.
Package routeguide is a generated protocol buffer package.
It is generated from these files:
route_guide.proto
......@@ -17,7 +17,9 @@ It has these top-level messages:
*/
package routeguide
import proto1 "github.com/golang/protobuf/proto"
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
......@@ -25,11 +27,13 @@ import (
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto1.Marshal
// 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).
......@@ -41,8 +45,9 @@ type Point struct {
}
func (m *Point) Reset() { *m = Point{} }
func (m *Point) String() string { return proto1.CompactTextString(m) }
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".
......@@ -54,8 +59,9 @@ type Rectangle struct {
}
func (m *Rectangle) Reset() { *m = Rectangle{} }
func (m *Rectangle) String() string { return proto1.CompactTextString(m) }
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 {
......@@ -82,8 +88,9 @@ type Feature struct {
}
func (m *Feature) Reset() { *m = Feature{} }
func (m *Feature) String() string { return proto1.CompactTextString(m) }
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 {
......@@ -101,8 +108,9 @@ type RouteNote struct {
}
func (m *RouteNote) Reset() { *m = RouteNote{} }
func (m *RouteNote) String() string { return proto1.CompactTextString(m) }
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 {
......@@ -128,12 +136,22 @@ type RouteSummary struct {
}
func (m *RouteSummary) Reset() { *m = RouteSummary{} }
func (m *RouteSummary) String() string { return proto1.CompactTextString(m) }
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 {
......@@ -141,8 +159,8 @@ type RouteGuideClient interface {
//
// Obtains the feature at a given position.
//
// If no feature is found for the given point, a feature with an empty name
// should be returned.
// 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.
//
......@@ -173,7 +191,7 @@ func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient {
func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {
out := new(Feature)
err := grpc.Invoke(ctx, "/proto.RouteGuide/GetFeature", in, out, c.cc, opts...)
err := grpc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
......@@ -181,7 +199,7 @@ func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...gr
}
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, "/proto.RouteGuide/ListFeatures", opts...)
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[0], c.cc, "/routeguide.RouteGuide/ListFeatures", opts...)
if err != nil {
return nil, err
}
......@@ -213,7 +231,7 @@ func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {
}
func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) {
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/proto.RouteGuide/RecordRoute", opts...)
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/routeguide.RouteGuide/RecordRoute", opts...)
if err != nil {
return nil, err
}
......@@ -247,7 +265,7 @@ func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) {
}
func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) {
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/proto.RouteGuide/RouteChat", opts...)
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/routeguide.RouteGuide/RouteChat", opts...)
if err != nil {
return nil, err
}
......@@ -284,8 +302,8 @@ type RouteGuideServer interface {
//
// Obtains the feature at a given position.
//
// If no feature is found for the given point, a feature with an empty name
// should be returned.
// 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.
//
......@@ -310,9 +328,9 @@ func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) {
s.RegisterService(&_RouteGuide_serviceDesc, srv)
}
func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(Point)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(RouteGuideServer).GetFeature(ctx, in)
......@@ -396,7 +414,7 @@ func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) {
}
var _RouteGuide_serviceDesc = grpc.ServiceDesc{
ServiceName: "proto.RouteGuide",
ServiceName: "routeguide.RouteGuide",
HandlerType: (*RouteGuideServer)(nil),
Methods: []grpc.MethodDesc{
{
......@@ -423,3 +441,33 @@ var _RouteGuide_serviceDesc = grpc.ServiceDesc{
},
},
}
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,
}
......@@ -29,6 +29,11 @@
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.
......@@ -37,8 +42,8 @@ service RouteGuide {
//
// Obtains the feature at a given position.
//
// If no feature is found for the given point, a feature with an empty name
// should be returned.
// 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.
......
......@@ -42,6 +42,8 @@ import (
)
// Use golang's standard logger by default.
// Access is not mutex-protected: do not modify except in init()
// functions.
var logger Logger = log.New(os.Stderr, "", log.LstdFlags)
// Logger mimics golang's standard Logger as an interface.
......@@ -54,7 +56,8 @@ type Logger interface {
Println(args ...interface{})
}
// SetLogger sets the logger that is used in grpc.
// SetLogger sets the logger that is used in grpc. Call only from
// init() functions.
func SetLogger(l Logger) {
logger = l
}
......
......@@ -15,6 +15,8 @@ It has these top-level messages:
package grpc_health_v1alpha
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
......@@ -23,6 +25,12 @@ import (
// 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
......@@ -46,14 +54,18 @@ var HealthCheckResponse_ServingStatus_value = map[string]int32{
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,2,opt,name=service" json:"service,omitempty"`
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.v1alpha.HealthCheckResponse_ServingStatus" json:"status,omitempty"`
......@@ -62,8 +74,11 @@ type HealthCheckResponse struct {
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.v1alpha.HealthCheckRequest")
proto.RegisterType((*HealthCheckResponse)(nil), "grpc.health.v1alpha.HealthCheckResponse")
proto.RegisterEnum("grpc.health.v1alpha.HealthCheckResponse_ServingStatus", HealthCheckResponse_ServingStatus_name, HealthCheckResponse_ServingStatus_value)
}
......@@ -71,59 +86,77 @@ func init() {
var _ context.Context
var _ grpc.ClientConn
// Client API for HealthCheck service
// Client API for Health service
type HealthCheckClient interface {
type HealthClient interface {
Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
}
type healthCheckClient struct {
type healthClient struct {
cc *grpc.ClientConn
}
func NewHealthCheckClient(cc *grpc.ClientConn) HealthCheckClient {
return &healthCheckClient{cc}
func NewHealthClient(cc *grpc.ClientConn) HealthClient {
return &healthClient{cc}
}
func (c *healthCheckClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
func (c *healthClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
out := new(HealthCheckResponse)
err := grpc.Invoke(ctx, "/grpc.health.v1alpha.HealthCheck/Check", in, out, c.cc, opts...)
err := grpc.Invoke(ctx, "/grpc.health.v1alpha.Health/Check", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for HealthCheck service
// Server API for Health service
type HealthCheckServer interface {
type HealthServer interface {
Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
}
func RegisterHealthCheckServer(s *grpc.Server, srv HealthCheckServer) {
s.RegisterService(&_HealthCheck_serviceDesc, srv)
func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
s.RegisterService(&_Health_serviceDesc, srv)
}
func _HealthCheck_Check_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _Health_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(HealthCheckRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(HealthCheckServer).Check(ctx, in)
out, err := srv.(HealthServer).Check(ctx, in)
if err != nil {
return nil, err
}
return out, nil
}
var _HealthCheck_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpc.health.v1alpha.HealthCheck",
HandlerType: (*HealthCheckServer)(nil),
var _Health_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpc.health.v1alpha.Health",
HandlerType: (*HealthServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Check",
Handler: _HealthCheck_Check_Handler,
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,
}
......@@ -3,7 +3,7 @@ syntax = "proto3";
package grpc.health.v1alpha;
message HealthCheckRequest {
string service = 2;
string service = 1;
}
message HealthCheckResponse {
......@@ -15,6 +15,6 @@ message HealthCheckResponse {
ServingStatus status = 1;
}
service HealthCheck{
service Health{
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}
......@@ -35,29 +35,20 @@ package main
import (
"flag"
"io"
"io/ioutil"
"net"
"strconv"
"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/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"
"google.golang.org/grpc/metadata"
)
var (
useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP")
caFile = flag.String("tls_ca_file", "testdata/ca.pem", "The file containning the CA root cert file")
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")
......@@ -72,7 +63,7 @@ var (
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;
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;
......@@ -80,411 +71,11 @@ var (
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.`)
)
var (
reqSizes = []int{27182, 8, 1828, 45904}
respSizes = []int{31415, 9, 2653, 58979}
largeReqSize = 271828
largeRespSize = 314159
)
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.Enum(),
Body: body,
}
}
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")
}
func doLargeUnaryCall(tc testpb.TestServiceClient) {
pl := newPayload(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")
}
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 := newPayload(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")
}
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")
}
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 := newPayload(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")
}
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")
}
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 := newPayload(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")
}
func doComputeEngineCreds(tc testpb.TestServiceClient) {
pl := newPayload(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 != *defaultServiceAccount {
grpclog.Fatalf("Got user name %q, want %q.", user, *defaultServiceAccount)
}
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() []byte {
jsonKey, err := ioutil.ReadFile(*serviceAccountKeyFile)
if err != nil {
grpclog.Fatalf("Failed to read the service account key file: %v", err)
}
return jsonKey
}
func doServiceAccountCreds(tc testpb.TestServiceClient) {
pl := newPayload(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()
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")
}
func doJWTTokenCreds(tc testpb.TestServiceClient) {
pl := newPayload(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()
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")
}
func getToken() *oauth2.Token {
jsonKey := getServiceAccountJSONKey()
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
}
func doOauth2TokenCreds(tc testpb.TestServiceClient) {
pl := newPayload(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()
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")
}
func doPerRPCCreds(tc testpb.TestServiceClient) {
jsonKey := getServiceAccountJSONKey()
pl := newPayload(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()
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"},
}
// The test CA root cert file
testCAFile = "testdata/ca.pem"
)
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")
}
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 := newPayload(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")
}
func main() {
flag.Parse()
serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
......@@ -495,9 +86,9 @@ func main() {
sn = *tlsServerName
}
var creds credentials.TransportAuthenticator
if *caFile != "" {
if *testCA {
var err error
creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
creds, err = credentials.NewClientTLSFromFile(testCAFile, sn)
if err != nil {
grpclog.Fatalf("Failed to create TLS credentials %v", err)
}
......@@ -520,7 +111,7 @@ func main() {
}
opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
} else if *testCase == "oauth2_auth_token" {
opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(getToken())))
opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope))))
}
} else {
opts = append(opts, grpc.WithInsecure())
......@@ -533,48 +124,48 @@ func main() {
tc := testpb.NewTestServiceClient(conn)
switch *testCase {
case "empty_unary":
doEmptyUnaryCall(tc)
interop.DoEmptyUnaryCall(tc)
case "large_unary":
doLargeUnaryCall(tc)
interop.DoLargeUnaryCall(tc)
case "client_streaming":
doClientStreaming(tc)
interop.DoClientStreaming(tc)
case "server_streaming":
doServerStreaming(tc)
interop.DoServerStreaming(tc)
case "ping_pong":
doPingPong(tc)
interop.DoPingPong(tc)
case "empty_stream":
doEmptyStream(tc)
interop.DoEmptyStream(tc)
case "timeout_on_sleeping_server":
doTimeoutOnSleepingServer(tc)
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.")
}
doComputeEngineCreds(tc)
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.")
}
doServiceAccountCreds(tc)
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.")
}
doJWTTokenCreds(tc)
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.")
}
doPerRPCCreds(tc)
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.")
}
doOauth2TokenCreds(tc)
interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope)
case "cancel_after_begin":
doCancelAfterBegin(tc)
interop.DoCancelAfterBegin(tc)
case "cancel_after_first_response":
doCancelAfterFirstResponse(tc)
interop.DoCancelAfterFirstResponse(tc)
default:
grpclog.Fatal("Unsupported test case: ", *testCase)
}
......
......@@ -22,6 +22,7 @@ It has these top-level messages:
package grpc_testing
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
......@@ -30,13 +31,14 @@ import (
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// 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
......@@ -76,6 +78,7 @@ func (x *PayloadType) UnmarshalJSON(data []byte) error {
*x = PayloadType(value)
return nil
}
func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Empty struct {
XXX_unrecognized []byte `json:"-"`
......@@ -84,6 +87,7 @@ type Empty struct {
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 {
......@@ -97,6 +101,7 @@ type Payload struct {
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 {
......@@ -132,6 +137,7 @@ type SimpleRequest struct {
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 {
......@@ -183,6 +189,7 @@ type SimpleResponse struct {
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 {
......@@ -215,6 +222,7 @@ type StreamingInputCallRequest struct {
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 {
......@@ -233,6 +241,7 @@ type StreamingInputCallResponse struct {
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 {
......@@ -255,6 +264,7 @@ type ResponseParameters struct {
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 {
......@@ -287,6 +297,7 @@ type StreamingOutputCallRequest struct {
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 {
......@@ -319,6 +330,7 @@ type StreamingOutputCallResponse struct {
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 {
......@@ -328,9 +340,22 @@ func (m *StreamingOutputCallResponse) GetPayload() *Payload {
}
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 {
......@@ -539,9 +564,9 @@ func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
s.RegisterService(&_TestService_serviceDesc, srv)
}
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(Empty)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TestServiceServer).EmptyCall(ctx, in)
......@@ -551,9 +576,9 @@ func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, codec
return out, nil
}
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(SimpleRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
......@@ -700,3 +725,43 @@ var _TestService_serviceDesc = grpc.ServiceDesc{
},
},
}
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,
}
......@@ -35,17 +35,13 @@ package main
import (
"flag"
"fmt"
"io"
"net"
"strconv"
"time"
"github.com/golang/protobuf/proto"
"golang.org/x/net/context"
"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"
)
......@@ -56,138 +52,6 @@ var (
port = flag.Int("port", 10000, "The server port")
)
type testServer struct {
}
func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
return new(testpb.Empty), nil
}
func newPayload(t testpb.PayloadType, size int32) (*testpb.Payload, error) {
if size < 0 {
return nil, fmt.Errorf("requested a response with invalid length %d", size)
}
body := make([]byte, size)
switch t {
case testpb.PayloadType_COMPRESSABLE:
case testpb.PayloadType_UNCOMPRESSABLE:
return nil, fmt.Errorf("payloadType UNCOMPRESSABLE is not supported")
default:
return nil, fmt.Errorf("unsupported payload type: %d", t)
}
return &testpb.Payload{
Type: t.Enum(),
Body: body,
}, nil
}
func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
pl, err := newPayload(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 := newPayload(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 := newPayload(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 := newPayload(m.GetResponseType(), c.GetSize())
if err != nil {
return err
}
if err := stream.Send(&testpb.StreamingOutputCallResponse{
Payload: pl,
}); err != nil {
return err
}
}
}
return nil
}
func main() {
flag.Parse()
p := strconv.Itoa(*port)
......@@ -204,6 +68,6 @@ func main() {
opts = []grpc.ServerOption{grpc.Creds(creds)}
}
server := grpc.NewServer(opts...)
testpb.RegisterTestServiceServer(server, &testServer{})
testpb.RegisterTestServiceServer(server, interop.NewTestServer())
server.Serve(lis)
}
/*
*
* 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
}
......@@ -46,27 +46,16 @@ const (
binHdrSuffix = "-bin"
)
// grpc-http2 requires ASCII header key and value (more detail can be found in
// "Requests" subsection in go/grpc-http2).
func isASCII(s string) bool {
for _, c := range s {
if c > 127 {
return false
}
}
return true
}
// encodeKeyValue encodes key and value qualified for transmission via gRPC.
// Transmitting binary headers violates HTTP/2 spec.
// TODO(zhaoq): Maybe check if k is ASCII also.
func encodeKeyValue(k, v string) (string, string) {
if isASCII(v) {
return k, v
}
key := strings.ToLower(k + binHdrSuffix)
k = strings.ToLower(k)
if strings.HasSuffix(k, binHdrSuffix) {
val := base64.StdEncoding.EncodeToString([]byte(v))
return key, string(val)
v = string(val)
}
return k, v
}
// DecodeKeyValue returns the original key and value corresponding to the
......@@ -75,12 +64,11 @@ func DecodeKeyValue(k, v string) (string, string, error) {
if !strings.HasSuffix(k, binHdrSuffix) {
return k, v, nil
}
key := k[:len(k)-len(binHdrSuffix)]
val, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return "", "", err
}
return key, string(val), nil
return k, string(val), nil
}
// MD is a mapping from metadata keys to values. Users should use the following
......
package etcd
import (
"log"
"sync"
etcdcl "github.com/coreos/etcd/client"
"golang.org/x/net/context"
"google.golang.org/grpc/naming"
)
type kv struct {
key, value string
}
// recvBuffer is an unbounded channel of *kv to record all the pending changes from etcd server.
type recvBuffer struct {
c chan *kv
mu sync.Mutex
stopping bool
backlog []*kv
}
func newRecvBuffer() *recvBuffer {
b := &recvBuffer{
c: make(chan *kv, 1),
}
return b
}
func (b *recvBuffer) put(r *kv) {
b.mu.Lock()
defer b.mu.Unlock()
if b.stopping {
return
}
b.backlog = append(b.backlog, r)
select {
case b.c <- b.backlog[0]:
b.backlog = b.backlog[1:]
default:
}
}
func (b *recvBuffer) load() {
b.mu.Lock()
defer b.mu.Unlock()
if b.stopping || len(b.backlog) == 0 {
return
}
select {
case b.c <- b.backlog[0]:
b.backlog = b.backlog[1:]
default:
}
}
func (b *recvBuffer) get() <-chan *kv {
return b.c
}
// stop terminates the recvBuffer. After it is called, the recvBuffer is not usable any more.
func (b *recvBuffer) stop() {
b.mu.Lock()
b.stopping = true
close(b.c)
b.mu.Unlock()
}
type etcdNR struct {
kAPI etcdcl.KeysAPI
recv *recvBuffer
ctx context.Context
cancel context.CancelFunc
}
// NewETCDNR creates an etcd NameResolver.
func NewETCDNR(cfg etcdcl.Config) (naming.Resolver, error) {
c, err := etcdcl.New(cfg)
if err != nil {
return nil, err
}
kAPI := etcdcl.NewKeysAPI(c)
ctx, cancel := context.WithCancel(context.Background())
return &etcdNR{
kAPI: kAPI,
recv: newRecvBuffer(),
ctx: ctx,
cancel: cancel,
}, nil
}
// getNode builds the resulting key-value map starting from node recursively.
func getNode(node *etcdcl.Node, res map[string]string) {
if !node.Dir {
res[node.Key] = node.Value
return
}
for _, val := range node.Nodes {
getNode(val, res)
}
}
func (nr *etcdNR) Get(target string) map[string]string {
resp, err := nr.kAPI.Get(nr.ctx, target, &etcdcl.GetOptions{Recursive: true, Sort: true})
if err != nil {
log.Printf("etcdNR.Get(_) stopped: %v", err)
return nil
}
res := make(map[string]string)
getNode(resp.Node, res)
return res
}
func (nr *etcdNR) Watch(target string) {
watcher := nr.kAPI.Watcher(target, &etcdcl.WatcherOptions{Recursive: true})
for {
resp, err := watcher.Next(nr.ctx)
if err != nil {
log.Printf("etcdNR.Watch(_) stopped: %v", err)
break
}
if resp.Node.Dir {
continue
}
entry := &kv{key: resp.Node.Key, value: resp.Node.Value}
nr.recv.put(entry)
}
}
func (nr *etcdNR) GetUpdate() (string, string) {
i := <-nr.recv.get()
nr.recv.load()
if i == nil {
return "", ""
}
// returns key and the corresponding value of the updated kv pair
return i.key, i.value
}
func (nr *etcdNR) Stop() {
nr.recv.stop()
nr.cancel()
}
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Package naming defines the naming API and related data structures for gRPC.
// The interface is EXPERIMENTAL and may be suject to change.
package naming
// Resolver dose name resolution and watches for the resolution changes.
// Operation defines the corresponding operations for a name resolution change.
type Operation uint8
const (
// Add indicates a new address is added.
Add Operation = iota
// Delete indicates an exisiting address is deleted.
Delete
)
// Update defines a name resolution update. Notice that it is not valid having both
// empty string Addr and nil Metadata in an Update.
type Update struct {
// Op indicates the operation of the update.
Op Operation
// Addr is the updated address. It is empty string if there is no address update.
Addr string
// Metadata is the updated metadata. It is nil if there is no metadata update.
// Metadata is not required for a custom naming implementation.
Metadata interface{}
}
// Resolver creates a Watcher for a target to track its resolution changes.
type Resolver interface {
// Get gets a snapshot of the current name resolution results for target.
Get(target string) map[string]string
// Watch watches for the name resolution changes on target. It blocks until Stop() is invoked. The watch results are obtained via GetUpdate().
Watch(target string)
// GetUpdate returns a name resolution change when watch is triggered. It blocks until it observes a change. The caller needs to call it again to get the next change.
GetUpdate() (string, string)
// Stop shuts down the NameResolver.
Stop()
// Resolve creates a Watcher for target.
Resolve(target string) (Watcher, error)
}
// Watcher watches for the updates on the specified target.
type Watcher interface {
// Next blocks until an update or error happens. It may return one or more
// updates. The first call should get the full set of the results.
Next() ([]*Update, error)
// Close closes the Watcher.
Close()
}
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Package peer defines various peer information associated with RPCs and
// corresponding utils.
package peer
import (
"net"
"golang.org/x/net/context"
"google.golang.org/grpc/credentials"
)
// Peer contains the information of the peer for an RPC.
type Peer struct {
// Addr is the peer address.
Addr net.Addr
// AuthInfo is the authentication information of the transport.
// It is nil if there is no transport security being used.
AuthInfo credentials.AuthInfo
}
type peerKey struct{}
// NewContext creates a new context with peer information attached.
func NewContext(ctx context.Context, p *Peer) context.Context {
return context.WithValue(ctx, peerKey{}, p)
}
// FromContext returns the peer information in ctx if it exists.
func FromContext(ctx context.Context) (p *Peer, ok bool) {
p, ok = ctx.Value(peerKey{}).(*Peer)
return
}
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package grpc
import (
"container/list"
"fmt"
"sync"
"golang.org/x/net/context"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/naming"
"google.golang.org/grpc/transport"
)
// Picker picks a Conn for RPC requests.
// This is EXPERIMENTAL and please do not implement your own Picker for now.
type Picker interface {
// Init does initial processing for the Picker, e.g., initiate some connections.
Init(cc *ClientConn) error
// Pick blocks until either a transport.ClientTransport is ready for the upcoming RPC
// or some error happens.
Pick(ctx context.Context) (transport.ClientTransport, error)
// PickAddr picks a peer address for connecting. This will be called repeated for
// connecting/reconnecting.
PickAddr() (string, error)
// State returns the connectivity state of the underlying connections.
State() (ConnectivityState, error)
// WaitForStateChange blocks until the state changes to something other than
// the sourceState. It returns the new state or error.
WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error)
// Close closes all the Conn's owned by this Picker.
Close() error
}
// unicastPicker is the default Picker which is used when there is no custom Picker
// specified by users. It always picks the same Conn.
type unicastPicker struct {
target string
conn *Conn
}
func (p *unicastPicker) Init(cc *ClientConn) error {
c, err := NewConn(cc)
if err != nil {
return err
}
p.conn = c
return nil
}
func (p *unicastPicker) Pick(ctx context.Context) (transport.ClientTransport, error) {
return p.conn.Wait(ctx)
}
func (p *unicastPicker) PickAddr() (string, error) {
return p.target, nil
}
func (p *unicastPicker) State() (ConnectivityState, error) {
return p.conn.State(), nil
}
func (p *unicastPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
return p.conn.WaitForStateChange(ctx, sourceState)
}
func (p *unicastPicker) Close() error {
if p.conn != nil {
return p.conn.Close()
}
return nil
}
// unicastNamingPicker picks an address from a name resolver to set up the connection.
type unicastNamingPicker struct {
cc *ClientConn
resolver naming.Resolver
watcher naming.Watcher
mu sync.Mutex
// The list of the addresses are obtained from watcher.
addrs *list.List
// It tracks the current picked addr by PickAddr(). The next PickAddr may
// push it forward on addrs.
pickedAddr *list.Element
conn *Conn
}
// NewUnicastNamingPicker creates a Picker to pick addresses from a name resolver
// to connect.
func NewUnicastNamingPicker(r naming.Resolver) Picker {
return &unicastNamingPicker{
resolver: r,
addrs: list.New(),
}
}
type addrInfo struct {
addr string
// Set to true if this addrInfo needs to be deleted in the next PickAddrr() call.
deleting bool
}
// processUpdates calls Watcher.Next() once and processes the obtained updates.
func (p *unicastNamingPicker) processUpdates() error {
updates, err := p.watcher.Next()
if err != nil {
return err
}
for _, update := range updates {
switch update.Op {
case naming.Add:
p.mu.Lock()
p.addrs.PushBack(&addrInfo{
addr: update.Addr,
})
p.mu.Unlock()
// Initial connection setup
if p.conn == nil {
conn, err := NewConn(p.cc)
if err != nil {
return err
}
p.conn = conn
}
case naming.Delete:
p.mu.Lock()
for e := p.addrs.Front(); e != nil; e = e.Next() {
if update.Addr == e.Value.(*addrInfo).addr {
if e == p.pickedAddr {
// Do not remove the element now if it is the current picked
// one. We leave the deletion to the next PickAddr() call.
e.Value.(*addrInfo).deleting = true
// Notify Conn to close it. All the live RPCs on this connection
// will be aborted.
p.conn.NotifyReset()
} else {
p.addrs.Remove(e)
}
}
}
p.mu.Unlock()
default:
grpclog.Println("Unknown update.Op ", update.Op)
}
}
return nil
}
// monitor runs in a standalone goroutine to keep watching name resolution updates until the watcher
// is closed.
func (p *unicastNamingPicker) monitor() {
for {
if err := p.processUpdates(); err != nil {
return
}
}
}
func (p *unicastNamingPicker) Init(cc *ClientConn) error {
w, err := p.resolver.Resolve(cc.target)
if err != nil {
return err
}
p.watcher = w
p.cc = cc
// Get the initial name resolution.
if err := p.processUpdates(); err != nil {
return err
}
go p.monitor()
return nil
}
func (p *unicastNamingPicker) Pick(ctx context.Context) (transport.ClientTransport, error) {
return p.conn.Wait(ctx)
}
func (p *unicastNamingPicker) PickAddr() (string, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.pickedAddr == nil {
p.pickedAddr = p.addrs.Front()
} else {
pa := p.pickedAddr
p.pickedAddr = pa.Next()
if pa.Value.(*addrInfo).deleting {
p.addrs.Remove(pa)
}
if p.pickedAddr == nil {
p.pickedAddr = p.addrs.Front()
}
}
if p.pickedAddr == nil {
return "", fmt.Errorf("there is no address available to pick")
}
return p.pickedAddr.Value.(*addrInfo).addr, nil
}
func (p *unicastNamingPicker) State() (ConnectivityState, error) {
return 0, fmt.Errorf("State() is not supported for unicastNamingPicker")
}
func (p *unicastNamingPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
return 0, fmt.Errorf("WaitForStateChange is not supported for unicastNamingPciker")
}
func (p *unicastNamingPicker) Close() error {
p.watcher.Close()
p.conn.Close()
return nil
}
......@@ -35,9 +35,12 @@ package grpc
import (
"bytes"
"compress/gzip"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"math"
"math/rand"
"os"
"time"
......@@ -75,6 +78,71 @@ func (protoCodec) String() string {
return "proto"
}
// Compressor defines the interface gRPC uses to compress a message.
type Compressor interface {
// Do compresses p into w.
Do(w io.Writer, p []byte) error
// Type returns the compression algorithm the Compressor uses.
Type() string
}
// NewGZIPCompressor creates a Compressor based on GZIP.
func NewGZIPCompressor() Compressor {
return &gzipCompressor{}
}
type gzipCompressor struct {
}
func (c *gzipCompressor) Do(w io.Writer, p []byte) error {
z := gzip.NewWriter(w)
if _, err := z.Write(p); err != nil {
return err
}
return z.Close()
}
func (c *gzipCompressor) Type() string {
return "gzip"
}
// Decompressor defines the interface gRPC uses to decompress a message.
type Decompressor interface {
// Do reads the data from r and uncompress them.
Do(r io.Reader) ([]byte, error)
// Type returns the compression algorithm the Decompressor uses.
Type() string
}
type gzipDecompressor struct {
}
// NewGZIPDecompressor creates a Decompressor based on GZIP.
func NewGZIPDecompressor() Decompressor {
return &gzipDecompressor{}
}
func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) {
z, err := gzip.NewReader(r)
if err != nil {
return nil, err
}
defer z.Close()
return ioutil.ReadAll(z)
}
func (d *gzipDecompressor) Type() string {
return "gzip"
}
// callInfo contains all related configuration and information about an RPC.
type callInfo struct {
failFast bool
headerMD metadata.MD
trailerMD metadata.MD
traceInfo traceInfo // in trace.go
}
// CallOption configures a Call before it starts or extracts information from
// a Call after it completes.
type CallOption interface {
......@@ -118,8 +186,7 @@ type payloadFormat uint8
const (
compressionNone payloadFormat = iota // no compression
compressionFlate
// More formats
compressionMade
)
// parser reads complelete gRPC messages from the underlying reader.
......@@ -127,42 +194,40 @@ type parser struct {
s io.Reader
}
// msgFixedHeader defines the header of a gRPC message (go/grpc-wirefmt).
type msgFixedHeader struct {
T payloadFormat
Length uint32
}
// recvMsg is to read a complete gRPC message from the stream. It is blocking if
// the message has not been complete yet. It returns the message and its type,
// EOF is returned with nil msg and 0 pf if the entire stream is done. Other
// non-nil error is returned if something is wrong on reading.
func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) {
var hdr msgFixedHeader
if err := binary.Read(p.s, binary.BigEndian, &hdr); err != nil {
// The header of a gRPC message. Find more detail
// at http://www.grpc.io/docs/guides/wire.html.
var buf [5]byte
if _, err := io.ReadFull(p.s, buf[:]); err != nil {
return 0, nil, err
}
if hdr.Length == 0 {
return hdr.T, nil, nil
pf = payloadFormat(buf[0])
length := binary.BigEndian.Uint32(buf[1:])
if length == 0 {
return pf, nil, nil
}
msg = make([]byte, int(hdr.Length))
msg = make([]byte, int(length))
if _, err := io.ReadFull(p.s, msg); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return 0, nil, err
}
return hdr.T, msg, nil
return pf, msg, nil
}
// encode serializes msg and prepends the message header. If msg is nil, it
// generates the message header of 0 message length.
func encode(c Codec, msg interface{}, pf payloadFormat) ([]byte, error) {
var buf bytes.Buffer
// Write message fixed header.
buf.WriteByte(uint8(pf))
func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer) ([]byte, error) {
var b []byte
var length uint32
var length uint
if msg != nil {
var err error
// TODO(zhaoq): optimize to reduce memory alloc and copying.
......@@ -170,27 +235,71 @@ func encode(c Codec, msg interface{}, pf payloadFormat) ([]byte, error) {
if err != nil {
return nil, err
}
length = uint32(len(b))
if cp != nil {
if err := cp.Do(cbuf, b); err != nil {
return nil, err
}
b = cbuf.Bytes()
}
length = uint(len(b))
}
if length > math.MaxUint32 {
return nil, Errorf(codes.InvalidArgument, "grpc: message too large (%d bytes)", length)
}
var szHdr [4]byte
binary.BigEndian.PutUint32(szHdr[:], length)
buf.Write(szHdr[:])
buf.Write(b)
return buf.Bytes(), nil
const (
payloadLen = 1
sizeLen = 4
)
var buf = make([]byte, payloadLen+sizeLen+len(b))
// Write payload format
if cp == nil {
buf[0] = byte(compressionNone)
} else {
buf[0] = byte(compressionMade)
}
// Write length of b into buf
binary.BigEndian.PutUint32(buf[1:], uint32(length))
// Copy encoded msg to buf
copy(buf[5:], b)
return buf, nil
}
func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) error {
switch pf {
case compressionNone:
case compressionMade:
if recvCompress == "" {
return transport.StreamErrorf(codes.InvalidArgument, "grpc: received unexpected payload format %d", pf)
}
if dc == nil || recvCompress != dc.Type() {
return transport.StreamErrorf(codes.InvalidArgument, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress)
}
default:
return transport.StreamErrorf(codes.InvalidArgument, "grpc: received unexpected payload format %d", pf)
}
return nil
}
func recv(p *parser, c Codec, m interface{}) error {
func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}) error {
pf, d, err := p.recvMsg()
if err != nil {
return err
}
switch pf {
case compressionNone:
if err := c.Unmarshal(d, m); err != nil {
return Errorf(codes.Internal, "grpc: %v", err)
if err := checkRecvPayload(pf, s.RecvCompress(), dc); err != nil {
return err
}
default:
return Errorf(codes.Internal, "gprc: compression is not supported yet.")
if pf == compressionMade {
d, err = dc.Do(bytes.NewReader(d))
if err != nil {
return transport.StreamErrorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
}
}
if err := c.Unmarshal(d, m); err != nil {
return transport.StreamErrorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err)
}
return nil
}
......@@ -217,6 +326,18 @@ func Code(err error) codes.Code {
return codes.Unknown
}
// ErrorDesc returns the error description of err if it was produced by the rpc system.
// Otherwise, it returns err.Error() or empty string when err is nil.
func ErrorDesc(err error) string {
if err == nil {
return ""
}
if e, ok := err.(rpcError); ok {
return e.desc
}
return err.Error()
}
// Errorf returns an error containing an error code and a description;
// Errorf returns nil if c is OK.
func Errorf(c codes.Code, format string, a ...interface{}) error {
......@@ -232,6 +353,8 @@ func Errorf(c codes.Code, format string, a ...interface{}) error {
// toRPCErr converts an error into a rpcError.
func toRPCErr(err error) error {
switch e := err.(type) {
case rpcError:
return err
case transport.StreamError:
return rpcError{
code: e.Code,
......
......@@ -34,13 +34,16 @@
package grpc
import (
"bytes"
"errors"
"fmt"
"io"
"net"
"reflect"
"runtime"
"strings"
"sync"
"time"
"golang.org/x/net/context"
"golang.org/x/net/trace"
......@@ -51,7 +54,7 @@ import (
"google.golang.org/grpc/transport"
)
type methodHandler func(srv interface{}, ctx context.Context, codec Codec, buf []byte) (interface{}, error)
type methodHandler func(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error)
// MethodDesc represents an RPC service's method specification.
type MethodDesc struct {
......@@ -84,11 +87,14 @@ type Server struct {
lis map[net.Listener]bool
conns map[transport.ServerTransport]bool
m map[string]*service // service name -> service info
events trace.EventLog
}
type options struct {
creds credentials.Credentials
codec Codec
cp Compressor
dc Decompressor
maxConcurrentStreams uint32
}
......@@ -102,6 +108,18 @@ func CustomCodec(codec Codec) ServerOption {
}
}
func RPCCompressor(cp Compressor) ServerOption {
return func(o *options) {
o.cp = cp
}
}
func RPCDecompressor(dc Decompressor) ServerOption {
return func(o *options) {
o.dc = dc
}
}
// MaxConcurrentStreams returns a ServerOption that will apply a limit on the number
// of concurrent streams to each ServerTransport.
func MaxConcurrentStreams(n uint32) ServerOption {
......@@ -128,12 +146,33 @@ func NewServer(opt ...ServerOption) *Server {
// Set the default codec.
opts.codec = protoCodec{}
}
return &Server{
s := &Server{
lis: make(map[net.Listener]bool),
opts: opts,
conns: make(map[transport.ServerTransport]bool),
m: make(map[string]*service),
}
if EnableTracing {
_, file, line, _ := runtime.Caller(1)
s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line))
}
return s
}
// printf records an event in s's event log, unless s has been stopped.
// REQUIRES s.mu is held.
func (s *Server) printf(format string, a ...interface{}) {
if s.events != nil {
s.events.Printf(format, a...)
}
}
// errorf records an error in s's event log, unless s has been stopped.
// REQUIRES s.mu is held.
func (s *Server) errorf(format string, a ...interface{}) {
if s.events != nil {
s.events.Errorf(format, a...)
}
}
// RegisterService register a service and its implementation to the gRPC
......@@ -151,6 +190,7 @@ func (s *Server) RegisterService(sd *ServiceDesc, ss interface{}) {
func (s *Server) register(sd *ServiceDesc, ss interface{}) {
s.mu.Lock()
defer s.mu.Unlock()
s.printf("RegisterService(%q)", sd.ServiceName)
if _, ok := s.m[sd.ServiceName]; ok {
grpclog.Fatalf("grpc: Server.RegisterService found duplicate service registration for %q", sd.ServiceName)
}
......@@ -182,6 +222,7 @@ var (
// Service returns when lis.Accept fails.
func (s *Server) Serve(lis net.Listener) error {
s.mu.Lock()
s.printf("serving")
if s.lis == nil {
s.mu.Unlock()
return ErrServerStopped
......@@ -197,15 +238,23 @@ func (s *Server) Serve(lis net.Listener) error {
for {
c, err := lis.Accept()
if err != nil {
s.mu.Lock()
s.printf("done serving; Accept = %v", err)
s.mu.Unlock()
return err
}
var authInfo credentials.AuthInfo
if creds, ok := s.opts.creds.(credentials.TransportAuthenticator); ok {
c, authInfo, err = creds.ServerHandshake(c)
var conn net.Conn
conn, authInfo, err = creds.ServerHandshake(c)
if err != nil {
s.mu.Lock()
s.errorf("ServerHandshake(%q) failed: %v", c.RemoteAddr(), err)
s.mu.Unlock()
grpclog.Println("grpc: Server.Serve failed to complete security handshake.")
continue
}
c = conn
}
s.mu.Lock()
if s.conns == nil {
......@@ -213,29 +262,85 @@ func (s *Server) Serve(lis net.Listener) error {
c.Close()
return nil
}
s.mu.Unlock()
go s.serveNewHTTP2Transport(c, authInfo)
}
}
func (s *Server) serveNewHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) {
st, err := transport.NewServerTransport("http2", c, s.opts.maxConcurrentStreams, authInfo)
if err != nil {
s.mu.Lock()
s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err)
s.mu.Unlock()
c.Close()
grpclog.Println("grpc: Server.Serve failed to create ServerTransport: ", err)
continue
return
}
s.conns[st] = true
s.mu.Unlock()
if !s.addConn(st) {
c.Close()
return
}
s.serveStreams(st)
}
go func() {
func (s *Server) serveStreams(st transport.ServerTransport) {
defer s.removeConn(st)
defer st.Close()
var wg sync.WaitGroup
st.HandleStreams(func(stream *transport.Stream) {
s.handleStream(st, stream)
wg.Add(1)
go func() {
defer wg.Done()
s.handleStream(st, stream, s.traceInfo(st, stream))
}()
})
wg.Wait()
}
// traceInfo returns a traceInfo and associates it with stream, if tracing is enabled.
// If tracing is not enabled, it returns nil.
func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Stream) (trInfo *traceInfo) {
if !EnableTracing {
return nil
}
trInfo = &traceInfo{
tr: trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()),
}
trInfo.firstLine.client = false
trInfo.firstLine.remoteAddr = st.RemoteAddr()
stream.TraceContext(trInfo.tr)
if dl, ok := stream.Context().Deadline(); ok {
trInfo.firstLine.deadline = dl.Sub(time.Now())
}
return trInfo
}
func (s *Server) addConn(st transport.ServerTransport) bool {
s.mu.Lock()
defer s.mu.Unlock()
if s.conns == nil {
return false
}
s.conns[st] = true
return true
}
func (s *Server) removeConn(st transport.ServerTransport) {
s.mu.Lock()
defer s.mu.Unlock()
if s.conns != nil {
delete(s.conns, st)
s.mu.Unlock()
}()
}
}
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, pf payloadFormat, opts *transport.Options) error {
p, err := encode(s.opts.codec, msg, pf)
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options) error {
var cbuf *bytes.Buffer
if cp != nil {
cbuf = new(bytes.Buffer)
}
p, err := encode(s.opts.codec, msg, cp, cbuf)
if err != nil {
// This typically indicates a fatal issue (e.g., memory
// corruption or hardware faults) the application program
......@@ -249,17 +354,15 @@ func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Str
return t.Write(stream, p, opts)
}
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc) (err error) {
var traceInfo traceInfo
if EnableTracing {
traceInfo.tr = trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method())
defer traceInfo.tr.Finish()
traceInfo.firstLine.client = false
traceInfo.tr.LazyLog(&traceInfo.firstLine, false)
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) {
if trInfo != nil {
defer trInfo.tr.Finish()
trInfo.firstLine.client = false
trInfo.tr.LazyLog(&trInfo.firstLine, false)
defer func() {
if err != nil && err != io.EOF {
traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
traceInfo.tr.SetError()
trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
trInfo.tr.SetError()
}
}()
}
......@@ -276,21 +379,50 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
// Nothing to do here.
case transport.StreamError:
if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil {
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err)
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err)
}
default:
panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err))
}
return err
}
if traceInfo.tr != nil {
traceInfo.tr.LazyLog(&payload{sent: false, msg: req}, true)
if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil {
switch err := err.(type) {
case transport.StreamError:
if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil {
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err)
}
default:
if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil {
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err)
}
}
return err
}
switch pf {
case compressionNone:
statusCode := codes.OK
statusDesc := ""
reply, appErr := md.Handler(srv.server, stream.Context(), s.opts.codec, req)
df := func(v interface{}) error {
if pf == compressionMade {
var err error
req, err = s.opts.dc.Do(bytes.NewReader(req))
if err != nil {
if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil {
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err)
}
return err
}
}
if err := s.opts.codec.Unmarshal(req, v); err != nil {
return err
}
if trInfo != nil {
trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true)
}
return nil
}
reply, appErr := md.Handler(srv.server, stream.Context(), df)
if appErr != nil {
if err, ok := appErr.(rpcError); ok {
statusCode = err.code
......@@ -299,17 +431,27 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
statusCode = convertCode(appErr)
statusDesc = appErr.Error()
}
if trInfo != nil && statusCode != codes.OK {
trInfo.tr.LazyLog(stringer(statusDesc), true)
trInfo.tr.SetError()
}
if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil {
grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err)
return err
}
return nil
}
if trInfo != nil {
trInfo.tr.LazyLog(stringer("OK"), false)
}
opts := &transport.Options{
Last: true,
Delay: false,
}
if err := s.sendResponse(t, stream, reply, compressionNone, opts); err != nil {
if s.opts.cp != nil {
stream.SetSendCompress(s.opts.cp.Type())
}
if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil {
switch err := err.(type) {
case transport.ConnectionError:
// Nothing to do here.
......@@ -322,36 +464,39 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
}
return err
}
if traceInfo.tr != nil {
traceInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true)
if trInfo != nil {
trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true)
}
return t.WriteStatus(stream, statusCode, statusDesc)
default:
panic(fmt.Sprintf("payload format to be supported: %d", pf))
}
}
}
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc) (err error) {
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) {
if s.opts.cp != nil {
stream.SetSendCompress(s.opts.cp.Type())
}
ss := &serverStream{
t: t,
s: stream,
p: &parser{s: stream},
codec: s.opts.codec,
tracing: EnableTracing,
cp: s.opts.cp,
dc: s.opts.dc,
trInfo: trInfo,
}
if ss.tracing {
ss.traceInfo.tr = trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method())
ss.traceInfo.firstLine.client = false
ss.traceInfo.tr.LazyLog(&ss.traceInfo.firstLine, false)
if ss.cp != nil {
ss.cbuf = new(bytes.Buffer)
}
if trInfo != nil {
trInfo.tr.LazyLog(&trInfo.firstLine, false)
defer func() {
ss.mu.Lock()
if err != nil && err != io.EOF {
ss.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.traceInfo.tr.SetError()
ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.trInfo.tr.SetError()
}
ss.traceInfo.tr.Finish()
ss.traceInfo.tr = nil
ss.trInfo.tr.Finish()
ss.trInfo.tr = nil
ss.mu.Unlock()
}()
}
......@@ -359,48 +504,94 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
if err, ok := appErr.(rpcError); ok {
ss.statusCode = err.code
ss.statusDesc = err.desc
} else if err, ok := appErr.(transport.StreamError); ok {
ss.statusCode = err.Code
ss.statusDesc = err.Desc
} else {
ss.statusCode = convertCode(appErr)
ss.statusDesc = appErr.Error()
}
}
if trInfo != nil {
ss.mu.Lock()
if ss.statusCode != codes.OK {
ss.trInfo.tr.LazyLog(stringer(ss.statusDesc), true)
ss.trInfo.tr.SetError()
} else {
ss.trInfo.tr.LazyLog(stringer("OK"), false)
}
ss.mu.Unlock()
}
return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc)
}
func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream) {
func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) {
sm := stream.Method()
if sm != "" && sm[0] == '/' {
sm = sm[1:]
}
pos := strings.LastIndex(sm, "/")
if pos == -1 {
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{sm}}, true)
trInfo.tr.SetError()
}
if err := t.WriteStatus(stream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", stream.Method())); err != nil {
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
trInfo.tr.SetError()
}
grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err)
}
if trInfo != nil {
trInfo.tr.Finish()
}
return
}
service := sm[:pos]
method := sm[pos+1:]
srv, ok := s.m[service]
if !ok {
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true)
trInfo.tr.SetError()
}
if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil {
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
trInfo.tr.SetError()
}
grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err)
}
if trInfo != nil {
trInfo.tr.Finish()
}
return
}
// Unary RPC or Streaming RPC?
if md, ok := srv.md[method]; ok {
s.processUnaryRPC(t, stream, srv, md)
s.processUnaryRPC(t, stream, srv, md, trInfo)
return
}
if sd, ok := srv.sd[method]; ok {
s.processStreamingRPC(t, stream, srv, sd)
s.processStreamingRPC(t, stream, srv, sd, trInfo)
return
}
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"Unknown method %v", []interface{}{method}}, true)
trInfo.tr.SetError()
}
if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown method %v", method)); err != nil {
if trInfo != nil {
trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
trInfo.tr.SetError()
}
grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err)
}
if trInfo != nil {
trInfo.tr.Finish()
}
}
// Stop stops the gRPC server. Once Stop returns, the server stops accepting
......@@ -418,6 +609,12 @@ func (s *Server) Stop() {
for c := range cs {
c.Close()
}
s.mu.Lock()
if s.events != nil {
s.events.Finish()
s.events = nil
}
s.mu.Unlock()
}
// TestingCloseConns closes all exiting transports but keeps s.lis accepting new
......
......@@ -34,6 +34,7 @@
package grpc
import (
"bytes"
"errors"
"io"
"sync"
......@@ -96,35 +97,63 @@ type ClientStream interface {
// NewClientStream creates a new Stream for the client side. This is called
// by generated code.
func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
var (
t transport.ClientTransport
err error
)
t, err = cc.dopts.picker.Pick(ctx)
if err != nil {
return nil, toRPCErr(err)
}
// TODO(zhaoq): CallOption is omitted. Add support when it is needed.
callHdr := &transport.CallHdr{
Host: cc.authority,
Method: method,
Flush: desc.ServerStreams&&desc.ClientStreams,
}
if cc.dopts.cp != nil {
callHdr.SendCompress = cc.dopts.cp.Type()
}
cs := &clientStream{
desc: desc,
codec: cc.dopts.codec,
cp: cc.dopts.cp,
dc: cc.dopts.dc,
tracing: EnableTracing,
}
if cc.dopts.cp != nil {
callHdr.SendCompress = cc.dopts.cp.Type()
cs.cbuf = new(bytes.Buffer)
}
if cs.tracing {
cs.traceInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
cs.traceInfo.firstLine.client = true
cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
cs.trInfo.firstLine.client = true
if deadline, ok := ctx.Deadline(); ok {
cs.traceInfo.firstLine.deadline = deadline.Sub(time.Now())
}
cs.traceInfo.tr.LazyLog(&cs.traceInfo.firstLine, false)
cs.trInfo.firstLine.deadline = deadline.Sub(time.Now())
}
t, _, err := cc.wait(ctx, 0)
if err != nil {
return nil, toRPCErr(err)
cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false)
ctx = trace.NewContext(ctx, cs.trInfo.tr)
}
s, err := t.NewStream(ctx, callHdr)
if err != nil {
cs.finish(err)
return nil, toRPCErr(err)
}
cs.t = t
cs.s = s
cs.p = &parser{s: s}
// Listen on ctx.Done() to detect cancellation when there is no pending
// I/O operations on this stream.
go func() {
select {
case <-t.Error():
// Incur transport error, simply exit.
case <-s.Context().Done():
err := s.Context().Err()
cs.finish(err)
cs.closeTransportStream(transport.ContextErr(err))
}
}()
return cs, nil
}
......@@ -135,13 +164,17 @@ type clientStream struct {
p *parser
desc *StreamDesc
codec Codec
cp Compressor
cbuf *bytes.Buffer
dc Decompressor
tracing bool // set to EnableTracing when the clientStream is created.
mu sync.Mutex // protects traceInfo
// traceInfo.tr is set when the clientStream is created (if EnableTracing is true),
mu sync.Mutex
closed bool
// trInfo.tr is set when the clientStream is created (if EnableTracing is true),
// and is set to nil when the clientStream's finish method is called.
traceInfo traceInfo
trInfo traceInfo
}
func (cs *clientStream) Context() context.Context {
......@@ -152,7 +185,7 @@ func (cs *clientStream) Header() (metadata.MD, error) {
m, err := cs.s.Header()
if err != nil {
if _, ok := err.(transport.ConnectionError); !ok {
cs.t.CloseStream(cs.s, err)
cs.closeTransportStream(err)
}
}
return m, err
......@@ -165,8 +198,8 @@ func (cs *clientStream) Trailer() metadata.MD {
func (cs *clientStream) SendMsg(m interface{}) (err error) {
if cs.tracing {
cs.mu.Lock()
if cs.traceInfo.tr != nil {
cs.traceInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
if cs.trInfo.tr != nil {
cs.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
}
cs.mu.Unlock()
}
......@@ -175,11 +208,16 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
return
}
if _, ok := err.(transport.ConnectionError); !ok {
cs.t.CloseStream(cs.s, err)
cs.closeTransportStream(err)
}
err = toRPCErr(err)
}()
out, err := encode(cs.codec, m, compressionNone)
out, err := encode(cs.codec, m, cs.cp, cs.cbuf)
defer func() {
if cs.cbuf != nil {
cs.cbuf.Reset()
}
}()
if err != nil {
return transport.StreamErrorf(codes.Internal, "grpc: %v", err)
}
......@@ -187,7 +225,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
}
func (cs *clientStream) RecvMsg(m interface{}) (err error) {
err = recv(cs.p, cs.codec, m)
err = recv(cs.p, cs.codec, cs.s, cs.dc, m)
defer func() {
// err != nil indicates the termination of the stream.
if err != nil {
......@@ -197,8 +235,8 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) {
if err == nil {
if cs.tracing {
cs.mu.Lock()
if cs.traceInfo.tr != nil {
cs.traceInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
if cs.trInfo.tr != nil {
cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
}
cs.mu.Unlock()
}
......@@ -206,8 +244,8 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) {
return
}
// Special handling for client streaming rpc.
err = recv(cs.p, cs.codec, m)
cs.t.CloseStream(cs.s, err)
err = recv(cs.p, cs.codec, cs.s, cs.dc, m)
cs.closeTransportStream(err)
if err == nil {
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
}
......@@ -220,7 +258,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) {
return toRPCErr(err)
}
if _, ok := err.(transport.ConnectionError); !ok {
cs.t.CloseStream(cs.s, err)
cs.closeTransportStream(err)
}
if err == io.EOF {
if cs.s.StatusCode() == codes.OK {
......@@ -238,27 +276,38 @@ func (cs *clientStream) CloseSend() (err error) {
return
}
if _, ok := err.(transport.ConnectionError); !ok {
cs.t.CloseStream(cs.s, err)
cs.closeTransportStream(err)
}
err = toRPCErr(err)
return
}
func (cs *clientStream) closeTransportStream(err error) {
cs.mu.Lock()
if cs.closed {
cs.mu.Unlock()
return
}
cs.closed = true
cs.mu.Unlock()
cs.t.CloseStream(cs.s, err)
}
func (cs *clientStream) finish(err error) {
if !cs.tracing {
return
}
cs.mu.Lock()
defer cs.mu.Unlock()
if cs.traceInfo.tr != nil {
if cs.trInfo.tr != nil {
if err == nil || err == io.EOF {
cs.traceInfo.tr.LazyPrintf("RPC: [OK]")
cs.trInfo.tr.LazyPrintf("RPC: [OK]")
} else {
cs.traceInfo.tr.LazyPrintf("RPC: [%v]", err)
cs.traceInfo.tr.SetError()
cs.trInfo.tr.LazyPrintf("RPC: [%v]", err)
cs.trInfo.tr.SetError()
}
cs.traceInfo.tr.Finish()
cs.traceInfo.tr = nil
cs.trInfo.tr.Finish()
cs.trInfo.tr = nil
}
}
......@@ -280,15 +329,14 @@ type serverStream struct {
s *transport.Stream
p *parser
codec Codec
cp Compressor
dc Decompressor
cbuf *bytes.Buffer
statusCode codes.Code
statusDesc string
trInfo *traceInfo
tracing bool // set to EnableTracing when the serverStream is created.
mu sync.Mutex // protects traceInfo
// traceInfo.tr is set when the serverStream is created (if EnableTracing is true),
// and is set to nil when the serverStream's finish method is called.
traceInfo traceInfo
mu sync.Mutex // protects trInfo.tr after the service handler runs.
}
func (ss *serverStream) Context() context.Context {
......@@ -309,19 +357,25 @@ func (ss *serverStream) SetTrailer(md metadata.MD) {
func (ss *serverStream) SendMsg(m interface{}) (err error) {
defer func() {
if ss.tracing {
if ss.trInfo != nil {
ss.mu.Lock()
if ss.trInfo.tr != nil {
if err == nil {
ss.traceInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
ss.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
} else {
ss.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.traceInfo.tr.SetError()
ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.trInfo.tr.SetError()
}
}
ss.mu.Unlock()
}
}()
out, err := encode(ss.codec, m, compressionNone)
out, err := encode(ss.codec, m, ss.cp, ss.cbuf)
defer func() {
if ss.cbuf != nil {
ss.cbuf.Reset()
}
}()
if err != nil {
err = transport.StreamErrorf(codes.Internal, "grpc: %v", err)
return err
......@@ -331,16 +385,18 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
func (ss *serverStream) RecvMsg(m interface{}) (err error) {
defer func() {
if ss.tracing {
if ss.trInfo != nil {
ss.mu.Lock()
if ss.trInfo.tr != nil {
if err == nil {
ss.traceInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
ss.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
} else if err != io.EOF {
ss.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.traceInfo.tr.SetError()
ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
ss.trInfo.tr.SetError()
}
}
ss.mu.Unlock()
}
}()
return recv(ss.p, ss.codec, m)
return recv(ss.p, ss.codec, ss.s, ss.dc, m)
}
......@@ -14,12 +14,18 @@ It has these top-level messages:
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 {
......@@ -30,6 +36,7 @@ type Buffer struct {
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 {
......@@ -39,4 +46,14 @@ func (m *Buffer) GetBody() []byte {
}
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,
}
......@@ -22,6 +22,7 @@ It has these top-level messages:
package grpc_testing
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
......@@ -30,13 +31,14 @@ import (
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// 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
......@@ -76,6 +78,7 @@ func (x *PayloadType) UnmarshalJSON(data []byte) error {
*x = PayloadType(value)
return nil
}
func (PayloadType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Empty struct {
XXX_unrecognized []byte `json:"-"`
......@@ -84,6 +87,7 @@ type Empty struct {
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 {
......@@ -97,6 +101,7 @@ type Payload struct {
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 {
......@@ -132,6 +137,7 @@ type SimpleRequest struct {
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 {
......@@ -183,6 +189,7 @@ type SimpleResponse struct {
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 {
......@@ -215,6 +222,7 @@ type StreamingInputCallRequest struct {
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 {
......@@ -233,6 +241,7 @@ type StreamingInputCallResponse struct {
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 {
......@@ -255,6 +264,7 @@ type ResponseParameters struct {
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 {
......@@ -287,6 +297,7 @@ type StreamingOutputCallRequest struct {
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 {
......@@ -319,6 +330,7 @@ type StreamingOutputCallResponse struct {
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 {
......@@ -328,9 +340,22 @@ func (m *StreamingOutputCallResponse) GetPayload() *Payload {
}
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 {
......@@ -539,9 +564,9 @@ func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
s.RegisterService(&_TestService_serviceDesc, srv)
}
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(Empty)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TestServiceServer).EmptyCall(ctx, in)
......@@ -551,9 +576,9 @@ func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, codec
return out, nil
}
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(SimpleRequest)
if err := codec.Unmarshal(buf, in); err != nil {
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TestServiceServer).UnaryCall(ctx, in)
......@@ -700,3 +725,43 @@ var _TestService_serviceDesc = grpc.ServiceDesc{
},
},
}
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,
}
......@@ -114,3 +114,7 @@ type fmtStringer struct {
func (f *fmtStringer) String() string {
return fmt.Sprintf(f.format, f.a...)
}
type stringer string
func (s stringer) String() string { return string(s) }
......@@ -37,7 +37,7 @@ import (
"fmt"
"sync"
"github.com/bradfitz/http2"
"golang.org/x/net/http2"
)
const (
......@@ -87,6 +87,7 @@ func (flushIO) isItem() bool {
type ping struct {
ack bool
data [8]byte
}
func (ping) isItem() bool {
......
......@@ -43,13 +43,14 @@ import (
"sync"
"time"
"github.com/bradfitz/http2"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/context"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
// http2Client implements the ClientTransport interface with HTTP2.
......@@ -209,6 +210,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
s := &Stream{
id: t.nextID,
method: callHdr.Method,
sendCompress: callHdr.SendCompress,
buf: newRecvBuffer(),
fc: fc,
sendQuotaPool: newQuotaPool(int(t.streamSendQuota)),
......@@ -238,10 +240,14 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
return nil, ContextErr(context.DeadlineExceeded)
}
}
pr := &peer.Peer{
Addr: t.conn.RemoteAddr(),
}
// Attach Auth info if there is any.
if t.authInfo != nil {
ctx = credentials.NewContext(ctx, t.authInfo)
pr.AuthInfo = t.authInfo
}
ctx = peer.NewContext(ctx, pr)
authData := make(map[string]string)
for _, c := range t.authCreds {
// Construct URI required to get auth request metadata.
......@@ -293,7 +299,18 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
}
s := t.newStream(ctx, callHdr)
t.activeStreams[s.id] = s
// This stream is not counted when applySetings(...) initialize t.streamsQuota.
// Reset t.streamsQuota to the right value.
var reset bool
if !checkStreamsQuota && t.streamsQuota != nil {
reset = true
}
t.mu.Unlock()
if reset {
t.streamsQuota.reset(-1)
}
// HPACK encodes various headers. Note that once WriteField(...) is
// called, the corresponding headers/continuation frame has to be sent
// because hpack.Encoder is stateful.
......@@ -306,6 +323,9 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
t.hEnc.WriteField(hpack.HeaderField{Name: "user-agent", Value: t.userAgent})
t.hEnc.WriteField(hpack.HeaderField{Name: "te", Value: "trailers"})
if callHdr.SendCompress != "" {
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress})
}
if timeout > 0 {
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: timeoutEncode(timeout)})
}
......@@ -333,6 +353,10 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
} else {
endHeaders = true
}
var flush bool
if endHeaders && (hasMD || callHdr.Flush) {
flush = true
}
if first {
// Sends a HeadersFrame to server to start a new stream.
p := http2.HeadersFrameParam{
......@@ -344,11 +368,11 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
// Do a force flush for the buffered frames iff it is the last headers frame
// and there is header metadata to be sent. Otherwise, there is flushing until
// the corresponding data frame is written.
err = t.framer.writeHeaders(hasMD && endHeaders, p)
err = t.framer.writeHeaders(flush, p)
first = false
} else {
// Sends Continuation frames for the leftover headers.
err = t.framer.writeContinuation(hasMD && endHeaders, s.id, endHeaders, t.hBuf.Next(size))
err = t.framer.writeContinuation(flush, s.id, endHeaders, t.hBuf.Next(size))
}
if err != nil {
t.notifyError(err)
......@@ -372,6 +396,11 @@ func (t *http2Client) CloseStream(s *Stream, err error) {
if updateStreams {
t.streamsQuota.add(1)
}
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), the caller needs
// to call cancel on the stream to interrupt the blocking on
// other goroutines.
s.cancel()
s.mu.Lock()
if q := s.fc.restoreConn(); q > 0 {
t.controlBuf.put(&windowUpdate{0, q})
......@@ -386,11 +415,6 @@ func (t *http2Client) CloseStream(s *Stream, err error) {
}
s.state = streamDone
s.mu.Unlock()
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), the caller needs
// to call cancel on the stream to interrupt the blocking on
// other goroutines.
s.cancel()
if _, ok := err.(StreamError); ok {
t.controlBuf.put(&resetStream{s.id, http2.ErrCodeCancel})
}
......@@ -635,7 +659,9 @@ func (t *http2Client) handleSettings(f *http2.SettingsFrame) {
}
func (t *http2Client) handlePing(f *http2.PingFrame) {
t.controlBuf.put(&ping{true})
pingAck := &ping{ack: true}
copy(pingAck.data[:], f.Data[:])
t.controlBuf.put(pingAck)
}
func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
......@@ -676,8 +702,10 @@ func (t *http2Client) operateHeaders(hDec *hpackDecoder, s *Stream, frame header
if !endHeaders {
return s
}
s.mu.Lock()
if !endStream {
s.recvCompress = hDec.state.encoding
}
if !s.headerDone {
if !endStream && len(hDec.state.mdata) > 0 {
s.header = hDec.state.mdata
......@@ -740,7 +768,7 @@ func (t *http2Client) reader() {
endStream := frame.Header().Flags.Has(http2.FlagHeadersEndStream)
curStream = t.operateHeaders(hDec, curStream, frame, endStream)
case *http2.ContinuationFrame:
curStream = t.operateHeaders(hDec, curStream, frame, false)
curStream = t.operateHeaders(hDec, curStream, frame, frame.HeadersEnded())
case *http2.DataFrame:
t.handleData(frame)
case *http2.RSTStreamFrame:
......@@ -816,9 +844,7 @@ func (t *http2Client) controller() {
case *flushIO:
t.framer.flushWrite()
case *ping:
// TODO(zhaoq): Ack with all-0 data now. will change to some
// meaningful content when this is actually in use.
t.framer.writePing(true, i.ack, [8]byte{})
t.framer.writePing(true, i.ack, i.data)
default:
grpclog.Printf("transport: http2Client.controller got unexpected item type %v\n", i)
}
......
......@@ -42,13 +42,14 @@ import (
"strconv"
"sync"
"github.com/bradfitz/http2"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/context"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
// ErrIllegalHeaderWrite indicates that setting header is illegal because of
......@@ -138,7 +139,7 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI
// operateHeader takes action on the decoded headers. It returns the current
// stream if there are remaining headers on the wire (in the following
// Continuation frame).
func (t *http2Server) operateHeaders(hDec *hpackDecoder, s *Stream, frame headerFrame, endStream bool, handle func(*Stream), wg *sync.WaitGroup) (pendingStream *Stream) {
func (t *http2Server) operateHeaders(hDec *hpackDecoder, s *Stream, frame headerFrame, endStream bool, handle func(*Stream)) (pendingStream *Stream) {
defer func() {
if pendingStream == nil {
hDec.state = decodeState{}
......@@ -163,31 +164,20 @@ func (t *http2Server) operateHeaders(hDec *hpackDecoder, s *Stream, frame header
if !endHeaders {
return s
}
t.mu.Lock()
if t.state != reachable {
t.mu.Unlock()
return nil
}
if uint32(len(t.activeStreams)) >= t.maxStreams {
t.mu.Unlock()
t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream})
return nil
}
s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota))
t.activeStreams[s.id] = s
t.mu.Unlock()
s.windowHandler = func(n int) {
t.updateWindow(s, uint32(n))
}
s.recvCompress = hDec.state.encoding
if hDec.state.timeoutSet {
s.ctx, s.cancel = context.WithTimeout(context.TODO(), hDec.state.timeout)
} else {
s.ctx, s.cancel = context.WithCancel(context.TODO())
}
pr := &peer.Peer{
Addr: t.conn.RemoteAddr(),
}
// Attach Auth info if there is any.
if t.authInfo != nil {
s.ctx = credentials.NewContext(s.ctx, t.authInfo)
pr.AuthInfo = t.authInfo
}
s.ctx = peer.NewContext(s.ctx, pr)
// Cache the current stream to the context so that the server application
// can find out. Required when the server wants to send some metadata
// back to the client (unary call only).
......@@ -201,13 +191,25 @@ func (t *http2Server) operateHeaders(hDec *hpackDecoder, s *Stream, frame header
ctx: s.ctx,
recv: s.buf,
}
s.recvCompress = hDec.state.encoding
s.method = hDec.state.method
wg.Add(1)
go func() {
t.mu.Lock()
if t.state != reachable {
t.mu.Unlock()
return nil
}
if uint32(len(t.activeStreams)) >= t.maxStreams {
t.mu.Unlock()
t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream})
return nil
}
s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota))
t.activeStreams[s.id] = s
t.mu.Unlock()
s.windowHandler = func(n int) {
t.updateWindow(s, uint32(n))
}
handle(s)
wg.Done()
}()
return nil
}
......@@ -243,8 +245,6 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
hDec := newHPACKDecoder()
var curStream *Stream
var wg sync.WaitGroup
defer wg.Wait()
for {
frame, err := t.framer.readFrame()
if err != nil {
......@@ -273,9 +273,9 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
fc: fc,
}
endStream := frame.Header().Flags.Has(http2.FlagHeadersEndStream)
curStream = t.operateHeaders(hDec, curStream, frame, endStream, handle, &wg)
curStream = t.operateHeaders(hDec, curStream, frame, endStream, handle)
case *http2.ContinuationFrame:
curStream = t.operateHeaders(hDec, curStream, frame, false, handle, &wg)
curStream = t.operateHeaders(hDec, curStream, frame, frame.HeadersEnded(), handle)
case *http2.DataFrame:
t.handleData(frame)
case *http2.RSTStreamFrame:
......@@ -384,7 +384,9 @@ func (t *http2Server) handleSettings(f *http2.SettingsFrame) {
}
func (t *http2Server) handlePing(f *http2.PingFrame) {
t.controlBuf.put(&ping{true})
pingAck := &ping{ack: true}
copy(pingAck.data[:], f.Data[:])
t.controlBuf.put(pingAck)
}
func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) {
......@@ -446,6 +448,9 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
t.hBuf.Reset()
t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"})
if s.sendCompress != "" {
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress})
}
for k, v := range md {
for _, entry := range v {
t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry})
......@@ -463,17 +468,24 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
// TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early
// OK is adopted.
func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc string) error {
s.mu.RLock()
var headersSent bool
s.mu.Lock()
if s.state == streamDone {
s.mu.RUnlock()
s.mu.Unlock()
return nil
}
s.mu.RUnlock()
if s.headerOk {
headersSent = true
}
s.mu.Unlock()
if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
return err
}
t.hBuf.Reset()
if !headersSent {
t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"})
}
t.hEnc.WriteField(
hpack.HeaderField{
Name: "grpc-status",
......@@ -513,6 +525,9 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
t.hBuf.Reset()
t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"})
if s.sendCompress != "" {
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress})
}
p := http2.HeadersFrameParam{
StreamID: s.id,
BlockFragment: t.hBuf.Bytes(),
......@@ -628,9 +643,7 @@ func (t *http2Server) controller() {
case *flushIO:
t.framer.flushWrite()
case *ping:
// TODO(zhaoq): Ack with all-0 data now. will change to some
// meaningful content when this is actually in use.
t.framer.writePing(true, i.ack, [8]byte{})
t.framer.writePing(true, i.ack, i.data)
default:
grpclog.Printf("transport: http2Server.controller got unexpected item type %v\n", i)
}
......@@ -660,9 +673,9 @@ func (t *http2Server) Close() (err error) {
t.mu.Unlock()
close(t.shutdownChan)
err = t.conn.Close()
// Notify all active streams.
// Cancel all active streams.
for _, s := range streams {
s.write(recvMsg{err: ErrConnClosing})
s.cancel()
}
return
}
......@@ -684,8 +697,11 @@ func (t *http2Server) closeStream(s *Stream) {
s.state = streamDone
s.mu.Unlock()
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), the caller needs
// to call cancel on the stream to interrupt the blocking on
// other goroutines.
// goroutines (e.g., bi-directional streaming), cancel needs to be
// called to interrupt the potential blocking on other goroutines.
s.cancel()
}
func (t *http2Server) RemoteAddr() net.Addr {
return t.conn.RemoteAddr()
}
......@@ -43,8 +43,8 @@ import (
"sync/atomic"
"time"
"github.com/bradfitz/http2"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
......@@ -52,7 +52,7 @@ import (
const (
// The primary user agent
primaryUA = "grpc-go/0.7"
primaryUA = "grpc-go/0.11"
// http2MaxFrameLen specifies the max length of a HTTP2 frame.
http2MaxFrameLen = 16384 // 16KB frame
// http://http2.github.io/http2-spec/#SettingValues
......@@ -89,6 +89,7 @@ var (
// Records the states during HPACK decoding. Must be reset once the
// decoding of the entire headers are finished.
type decodeState struct {
encoding string
// statusCode caches the stream status received from the trailer
// the server sent. Client side only.
statusCode codes.Code
......@@ -140,6 +141,13 @@ func newHPACKDecoder() *hpackDecoder {
d := &hpackDecoder{}
d.h = hpack.NewDecoder(http2InitHeaderTableSize, func(f hpack.HeaderField) {
switch f.Name {
case "content-type":
if !strings.Contains(f.Value, "application/grpc") {
d.err = StreamErrorf(codes.FailedPrecondition, "transport: received the unexpected header")
return
}
case "grpc-encoding":
d.state.encoding = f.Value
case "grpc-status":
code, err := strconv.Atoi(f.Value)
if err != nil {
......
......@@ -47,6 +47,7 @@ import (
"time"
"golang.org/x/net/context"
"golang.org/x/net/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
......@@ -170,6 +171,8 @@ type Stream struct {
cancel context.CancelFunc
// method records the associated RPC method of the stream.
method string
recvCompress string
sendCompress string
buf *recvBuffer
dec io.Reader
fc *inFlow
......@@ -200,6 +203,17 @@ type Stream struct {
statusDesc string
}
// RecvCompress returns the compression algorithm applied to the inbound
// message. It is empty string if there is no compression applied.
func (s *Stream) RecvCompress() string {
return s.recvCompress
}
// SetSendCompress sets the compression algorithm to the stream.
func (s *Stream) SetSendCompress(str string) {
s.sendCompress = str
}
// Header acquires the key-value pairs of header metadata once it
// is available. It blocks until i) the metadata is ready or ii) there is no
// header metadata or iii) the stream is cancelled/expired.
......@@ -232,6 +246,11 @@ func (s *Stream) Context() context.Context {
return s.ctx
}
// TraceContext recreates the context of s with a trace.Trace.
func (s *Stream) TraceContext(tr trace.Trace) {
s.ctx = trace.NewContext(s.ctx, tr)
}
// Method returns the method for the stream.
func (s *Stream) Method() string {
return s.method
......@@ -342,8 +361,18 @@ type Options struct {
// CallHdr carries the information of a particular RPC.
type CallHdr struct {
Host string // peer host
Method string // the operation to perform on the specified host
// Host specifies peer host.
Host string
// Method specifies the operation to perform.
Method string
// RecvCompress specifies the compression algorithm applied on inbound messages.
RecvCompress string
// SendCompress specifies the compression algorithm applied on outbound message.
SendCompress string
// Flush indicates if new stream command should be sent to the peer without
// waiting for the first data. This is a hint though. The transport may modify
// the flush decision for performance purpose.
Flush bool
}
// ClientTransport is the common interface for all gRPC client side transport
......@@ -390,6 +419,8 @@ type ServerTransport interface {
// should not be accessed any more. All the pending streams and their
// handlers will be terminated asynchronously.
Close() error
// RemoteAddr returns the remote network address.
RemoteAddr() net.Addr
}
// StreamErrorf creates an StreamError with the specified error code and description.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment