Signed-off-by: Alexander Morozov <lk4d4@docker.com>
| ... | ... |
@@ -102,7 +102,7 @@ clone git github.com/pborman/uuid v1.0 |
| 102 | 102 |
# get desired notary commit, might also need to be updated in Dockerfile |
| 103 | 103 |
clone git github.com/docker/notary v0.3.0 |
| 104 | 104 |
|
| 105 |
-clone git google.golang.org/grpc ab0be5212fb225475f2087566eded7da5d727960 https://github.com/grpc/grpc-go.git |
|
| 105 |
+clone git google.golang.org/grpc v1.0.1-GA https://github.com/grpc/grpc-go.git |
|
| 106 | 106 |
clone git github.com/miekg/pkcs11 df8ae6ca730422dba20c768ff38ef7d79077a59f |
| 107 | 107 |
clone git github.com/docker/go v1.5.1-1-1-gbaf439e |
| 108 | 108 |
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c |
| ... | ... |
@@ -114,7 +114,7 @@ clone git github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb2 |
| 114 | 114 |
clone git github.com/coreos/go-systemd v4 |
| 115 | 115 |
clone git github.com/godbus/dbus v4.0.0 |
| 116 | 116 |
clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 |
| 117 |
-clone git github.com/golang/protobuf 3c84672111d91bb5ac31719e112f9f7126a0e26e |
|
| 117 |
+clone git github.com/golang/protobuf 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a |
|
| 118 | 118 |
|
| 119 | 119 |
# gelf logging driver deps |
| 120 | 120 |
clone git github.com/Graylog2/go-gelf aab2f594e4585d43468ac57287b0dece9d806883 |
| ... | ... |
@@ -146,7 +146,7 @@ clone git github.com/docker/containerd 4c21ad662f71af56c0e6b29c0afef72df441d1ff |
| 146 | 146 |
# cluster |
| 147 | 147 |
clone git github.com/docker/swarmkit 27fbaef4ceed648bb575969ccc9083a6e104a719 |
| 148 | 148 |
clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 |
| 149 |
-clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028 |
|
| 149 |
+clone git github.com/gogo/protobuf v0.3 |
|
| 150 | 150 |
clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a |
| 151 | 151 |
clone git github.com/google/certificate-transparency 0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341 |
| 152 | 152 |
clone git golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2 https://github.com/golang/crypto.git |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
|
| 3 |
-Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+http://github.com/gogo/protobuf |
|
| 5 | 5 |
|
| 6 | 6 |
Go support for Protocol Buffers - Google's data interchange format |
| 7 | 7 |
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-# Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+# Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
# |
| 3 |
-# Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-# http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+# Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+# http://github.com/gogo/protobuf |
|
| 5 | 5 |
# |
| 6 | 6 |
# Redistribution and use in source and binary forms, with or without |
| 7 | 7 |
# modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-// Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
// |
| 3 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 5 | 5 |
// |
| 6 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 7 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -24,7 +24,9 @@ var _ = math.Inf |
| 24 | 24 |
|
| 25 | 25 |
// This is a compile-time assertion to ensure that this generated file |
| 26 | 26 |
// is compatible with the proto package it is being compiled against. |
| 27 |
-const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 27 |
+// A compilation error at this line likely means your copy of the |
|
| 28 |
+// proto package needs to be updated. |
|
| 29 |
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package |
|
| 28 | 30 |
|
| 29 | 31 |
var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
|
| 30 | 32 |
ExtendedType: (*google_protobuf.EnumOptions)(nil), |
| ... | ... |
@@ -587,75 +589,77 @@ func init() {
|
| 587 | 587 |
proto.RegisterExtension(E_Castvalue) |
| 588 | 588 |
} |
| 589 | 589 |
|
| 590 |
+func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
|
|
| 591 |
+ |
|
| 590 | 592 |
var fileDescriptorGogo = []byte{
|
| 591 |
- // 1096 bytes of a gzipped FileDescriptorProto |
|
| 592 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x97, 0xcb, 0x6f, 0xdc, 0x54, |
|
| 593 |
- 0x14, 0x87, 0x85, 0x48, 0x95, 0x99, 0x93, 0x17, 0x99, 0x84, 0x50, 0x2a, 0x10, 0xed, 0x8e, 0x55, |
|
| 594 |
- 0xba, 0x42, 0xa8, 0xae, 0x10, 0x6a, 0xab, 0x34, 0x2a, 0x22, 0x10, 0x05, 0x52, 0x40, 0x2c, 0x46, |
|
| 595 |
- 0x9e, 0xc9, 0x8d, 0x3b, 0xe0, 0xf1, 0x35, 0xbe, 0x76, 0xd5, 0xb0, 0x43, 0xe5, 0x21, 0x84, 0x78, |
|
| 596 |
- 0x23, 0x41, 0x4b, 0xcb, 0x63, 0xc1, 0xfb, 0x59, 0x1e, 0x7b, 0x36, 0xc0, 0x9a, 0xff, 0x81, 0x0d, |
|
| 597 |
- 0x10, 0x5e, 0x52, 0x76, 0xd9, 0xf4, 0x1e, 0xfb, 0x1c, 0xcf, 0xb5, 0x67, 0xa4, 0x7b, 0x67, 0xe7, |
|
| 598 |
- 0x64, 0xee, 0xf7, 0xcd, 0xf5, 0x39, 0xbe, 0xe7, 0x37, 0x06, 0x08, 0x64, 0x20, 0x97, 0xe3, 0x44, |
|
| 599 |
- 0xa6, 0xb2, 0xd5, 0xc4, 0xeb, 0xfc, 0xf2, 0xd0, 0xe1, 0x40, 0xca, 0x20, 0x14, 0x47, 0xf3, 0xbf, |
|
| 600 |
- 0x3a, 0xd9, 0xf6, 0xd1, 0x2d, 0xa1, 0xba, 0x49, 0x2f, 0x4e, 0x65, 0x52, 0x2c, 0xf6, 0x1e, 0x80, |
|
| 601 |
- 0x05, 0x5a, 0xdc, 0x16, 0x51, 0xd6, 0x6f, 0xc7, 0x89, 0xd8, 0xee, 0x5d, 0x68, 0xdd, 0xb6, 0x5c, |
|
| 602 |
- 0x90, 0xcb, 0x4c, 0x2e, 0xaf, 0xe8, 0x4f, 0x1f, 0x8c, 0xd3, 0x9e, 0x8c, 0xd4, 0xc1, 0x6b, 0xbf, |
|
| 603 |
- 0xdf, 0x78, 0xf8, 0x86, 0x3b, 0x1b, 0x1b, 0xf3, 0x84, 0xe2, 0x67, 0xeb, 0x39, 0xe8, 0x6d, 0xc0, |
|
| 604 |
- 0xcd, 0x15, 0x9f, 0x4a, 0x93, 0x5e, 0x14, 0x88, 0xc4, 0x62, 0xfc, 0x99, 0x8c, 0x0b, 0x86, 0xf1, |
|
| 605 |
- 0x21, 0x42, 0xbd, 0x53, 0x30, 0x33, 0x8e, 0xeb, 0x17, 0x72, 0x4d, 0x0b, 0x53, 0xb2, 0x0a, 0x73, |
|
| 606 |
- 0xb9, 0xa4, 0x9b, 0xa9, 0x54, 0xf6, 0x23, 0xbf, 0x2f, 0x2c, 0x9a, 0x5f, 0x73, 0x4d, 0x73, 0x63, |
|
| 607 |
- 0x16, 0xb1, 0x53, 0x25, 0xe5, 0x9d, 0x85, 0x45, 0xfc, 0xcf, 0x79, 0x3f, 0xcc, 0x84, 0x69, 0x3b, |
|
| 608 |
- 0x32, 0xd2, 0x76, 0x16, 0x97, 0xb1, 0xf2, 0xb7, 0x8b, 0x13, 0xb9, 0x72, 0xa1, 0x14, 0x18, 0x5e, |
|
| 609 |
- 0xa3, 0x13, 0x81, 0x48, 0x53, 0x91, 0xa8, 0xb6, 0x1f, 0x86, 0x23, 0x36, 0x79, 0xba, 0x17, 0x96, |
|
| 610 |
- 0xc6, 0x4b, 0xbb, 0xd5, 0x4e, 0xac, 0x16, 0xe4, 0x89, 0x30, 0xf4, 0x36, 0xe1, 0x96, 0x11, 0x9d, |
|
| 611 |
- 0x75, 0x70, 0x5e, 0x26, 0xe7, 0xe2, 0x50, 0x77, 0x51, 0xbb, 0x0e, 0xfc, 0xff, 0xb2, 0x1f, 0x0e, |
|
| 612 |
- 0xce, 0x77, 0xc9, 0xd9, 0x22, 0x96, 0xdb, 0x82, 0xc6, 0xfb, 0x60, 0xfe, 0xbc, 0x48, 0x3a, 0x52, |
|
| 613 |
- 0x89, 0xb6, 0x78, 0x2a, 0xf3, 0x43, 0x07, 0xdd, 0x15, 0xd2, 0xcd, 0x11, 0xb8, 0x82, 0x1c, 0xba, |
|
| 614 |
- 0x8e, 0x41, 0x63, 0xdb, 0xef, 0x0a, 0x07, 0xc5, 0x55, 0x52, 0x4c, 0xe2, 0x7a, 0x44, 0x4f, 0xc0, |
|
| 615 |
- 0x74, 0x20, 0x8b, 0x5b, 0x72, 0xc0, 0xdf, 0x23, 0x7c, 0x8a, 0x19, 0x52, 0xc4, 0x32, 0xce, 0x42, |
|
| 616 |
- 0x3f, 0x75, 0xd9, 0xc1, 0xfb, 0xac, 0x60, 0x86, 0x14, 0x63, 0x94, 0xf5, 0x03, 0x56, 0x28, 0xa3, |
|
| 617 |
- 0x9e, 0xf7, 0xc2, 0x94, 0x8c, 0xc2, 0x1d, 0x19, 0xb9, 0x6c, 0xe2, 0x43, 0x32, 0x00, 0x21, 0x28, |
|
| 618 |
- 0x38, 0x0e, 0x4d, 0xd7, 0x46, 0x7c, 0x44, 0x78, 0x43, 0x70, 0x07, 0xf4, 0x39, 0xe3, 0x21, 0xa3, |
|
| 619 |
- 0x57, 0x38, 0x28, 0x3e, 0x26, 0xc5, 0xac, 0x81, 0xd1, 0x6d, 0xa4, 0x42, 0xa5, 0x81, 0x70, 0x91, |
|
| 620 |
- 0x7c, 0xc2, 0xb7, 0x41, 0x08, 0x95, 0xb2, 0x23, 0xa2, 0xee, 0x39, 0x37, 0xc3, 0xa7, 0x5c, 0x4a, |
|
| 621 |
- 0x66, 0x50, 0xa1, 0x27, 0x4f, 0xdf, 0x4f, 0xd4, 0x39, 0x3f, 0x74, 0x6a, 0xc7, 0x67, 0xe4, 0x98, |
|
| 622 |
- 0x2e, 0x21, 0xaa, 0x48, 0x16, 0x8d, 0xa3, 0xf9, 0x9c, 0x2b, 0x62, 0x60, 0x74, 0xf4, 0x54, 0xea, |
|
| 623 |
- 0x77, 0x42, 0xd1, 0x1e, 0xc7, 0xf6, 0x05, 0x1f, 0xbd, 0x82, 0x5d, 0x33, 0x8d, 0xba, 0xd3, 0xaa, |
|
| 624 |
- 0xf7, 0xb4, 0x93, 0xe6, 0x4b, 0xee, 0x74, 0x0e, 0x20, 0xfc, 0x18, 0xdc, 0x3a, 0x72, 0xd4, 0x3b, |
|
| 625 |
- 0xc8, 0xbe, 0x22, 0xd9, 0xd2, 0x88, 0x71, 0x4f, 0x23, 0x61, 0x5c, 0xe5, 0xd7, 0x3c, 0x12, 0x44, |
|
| 626 |
- 0xcd, 0xa5, 0xab, 0x96, 0x45, 0xca, 0xdf, 0x1e, 0xaf, 0x6a, 0xdf, 0x70, 0xd5, 0x0a, 0xb6, 0x52, |
|
| 627 |
- 0xb5, 0x87, 0x61, 0x89, 0x8c, 0xe3, 0xf5, 0xf5, 0x5b, 0x1e, 0xac, 0x05, 0xbd, 0x59, 0xed, 0xee, |
|
| 628 |
- 0xe3, 0x70, 0xa8, 0x2c, 0xe7, 0x85, 0x54, 0x44, 0x0a, 0x19, 0xbd, 0xe7, 0xd8, 0xc1, 0x7c, 0x8d, |
|
| 629 |
- 0xcc, 0x3c, 0xf1, 0x57, 0x4a, 0xc1, 0x9a, 0x1f, 0xa3, 0xfc, 0x51, 0x38, 0xc8, 0xf2, 0x2c, 0x4a, |
|
| 630 |
- 0x44, 0x57, 0x06, 0x91, 0x6e, 0xe3, 0x96, 0x83, 0xfa, 0xbb, 0x5a, 0xab, 0x36, 0x0d, 0x1c, 0xcd, |
|
| 631 |
- 0x67, 0xe0, 0xa6, 0xf2, 0xf7, 0x46, 0xbb, 0xd7, 0x8f, 0x65, 0x92, 0x5a, 0x8c, 0xdf, 0x73, 0xa7, |
|
| 632 |
- 0x4a, 0xee, 0x4c, 0x8e, 0x79, 0x2b, 0x30, 0x9b, 0xff, 0xe9, 0xfa, 0x48, 0xfe, 0x40, 0xa2, 0x99, |
|
| 633 |
- 0x01, 0x45, 0x83, 0xa3, 0x2b, 0xfb, 0xb1, 0x9f, 0xb8, 0xcc, 0xbf, 0x1f, 0x79, 0x70, 0x10, 0x52, |
|
| 634 |
- 0x3c, 0x7d, 0x73, 0xb5, 0x24, 0x6e, 0xdd, 0x31, 0x24, 0x59, 0x13, 0x4a, 0xf9, 0x41, 0xe9, 0x79, |
|
| 635 |
- 0x66, 0x8f, 0xce, 0x6c, 0x35, 0x88, 0xbd, 0xfb, 0xb1, 0x3c, 0xd5, 0xb8, 0xb4, 0xcb, 0x2e, 0xee, |
|
| 636 |
- 0x95, 0x15, 0xaa, 0xa4, 0xa5, 0x77, 0x1a, 0x66, 0x2a, 0x51, 0x69, 0x57, 0x3d, 0x4b, 0xaa, 0x69, |
|
| 637 |
- 0x33, 0x29, 0xbd, 0xbb, 0x60, 0x02, 0x63, 0xcf, 0x8e, 0x3f, 0x47, 0x78, 0xbe, 0xdc, 0xbb, 0x07, |
|
| 638 |
- 0x1a, 0x1c, 0x77, 0x76, 0xf4, 0x79, 0x42, 0x4b, 0x04, 0x71, 0x8e, 0x3a, 0x3b, 0xfe, 0x02, 0xe3, |
|
| 639 |
- 0x8c, 0x20, 0xee, 0x5e, 0xc2, 0x9f, 0x5e, 0x9a, 0xa0, 0x71, 0xc5, 0xb5, 0x3b, 0x0e, 0x93, 0x94, |
|
| 640 |
- 0x71, 0x76, 0xfa, 0x45, 0xfa, 0x72, 0x26, 0xbc, 0xbb, 0xe1, 0x80, 0x63, 0xc1, 0x5f, 0x26, 0xb4, |
|
| 641 |
- 0x58, 0xaf, 0x13, 0x64, 0xca, 0xc8, 0x35, 0x3b, 0xfe, 0x0a, 0xe1, 0x26, 0x85, 0x5b, 0xa7, 0x5c, |
|
| 642 |
- 0xb3, 0x0b, 0x5e, 0xe5, 0xad, 0x13, 0x81, 0x65, 0xe3, 0x48, 0xb3, 0xd3, 0xaf, 0x71, 0xd5, 0x19, |
|
| 643 |
- 0xd1, 0xa7, 0xa9, 0x59, 0x8e, 0x29, 0x3b, 0xff, 0x3a, 0xf1, 0x03, 0x06, 0x2b, 0x60, 0x8c, 0x49, |
|
| 644 |
- 0xbb, 0xe2, 0x0d, 0xae, 0x80, 0x41, 0xe1, 0x31, 0xaa, 0x47, 0x9f, 0xdd, 0xf4, 0x26, 0x1f, 0xa3, |
|
| 645 |
- 0x5a, 0xf2, 0x61, 0x37, 0xf3, 0x69, 0x61, 0x57, 0xbc, 0xc5, 0xdd, 0xcc, 0xd7, 0xe3, 0x36, 0xea, |
|
| 646 |
- 0x59, 0x62, 0x77, 0xbc, 0xcd, 0xdb, 0xa8, 0x45, 0x89, 0x4e, 0xa6, 0xd6, 0x70, 0x8e, 0xd8, 0x7d, |
|
| 647 |
- 0xef, 0x90, 0x6f, 0x7e, 0x28, 0x46, 0xbc, 0x47, 0x60, 0x69, 0x74, 0x86, 0xd8, 0xad, 0x97, 0xf6, |
|
| 648 |
- 0x6a, 0xbf, 0xfa, 0xcd, 0x08, 0xd1, 0x91, 0xb7, 0x38, 0x2a, 0x3f, 0xec, 0xda, 0xcb, 0x7b, 0xd5, |
|
| 649 |
- 0x17, 0x3b, 0x33, 0x3e, 0xf4, 0x2f, 0x34, 0x18, 0x8c, 0x6e, 0xbb, 0xeb, 0x0a, 0xb9, 0x0c, 0x08, |
|
| 650 |
- 0x8f, 0x06, 0x4d, 0x6e, 0x3b, 0x7f, 0x95, 0x8f, 0x06, 0x11, 0x1a, 0x6e, 0x44, 0x59, 0x18, 0xe2, |
|
| 651 |
- 0xc3, 0xd1, 0xba, 0x7d, 0x44, 0x4c, 0x88, 0x70, 0x8b, 0xd9, 0x3f, 0xf6, 0xe9, 0x60, 0x30, 0xa0, |
|
| 652 |
- 0x67, 0xe8, 0x01, 0xd1, 0xef, 0xe8, 0x1a, 0x58, 0xc8, 0x3f, 0xf7, 0x79, 0x20, 0xe0, 0x6a, 0x7d, |
|
| 653 |
- 0x9e, 0xa0, 0x78, 0x69, 0x4c, 0x77, 0x62, 0xeb, 0xb7, 0xfe, 0xb5, 0x5f, 0xbc, 0x83, 0x1a, 0xc8, |
|
| 654 |
- 0x40, 0x90, 0xbf, 0x75, 0x5a, 0x04, 0xbb, 0x55, 0x41, 0xfe, 0xa2, 0x79, 0x0c, 0x26, 0x9f, 0x50, |
|
| 655 |
- 0x32, 0x4a, 0xfd, 0xc0, 0x46, 0xff, 0x4d, 0x34, 0xaf, 0xc7, 0x82, 0xf5, 0x65, 0x22, 0xf4, 0xa5, |
|
| 656 |
- 0xb2, 0xb1, 0xff, 0x10, 0x5b, 0x02, 0x08, 0x77, 0x7d, 0x95, 0xba, 0xdc, 0xf7, 0xbf, 0x0c, 0x33, |
|
| 657 |
- 0x80, 0x9b, 0xc6, 0xeb, 0x27, 0xc5, 0x8e, 0x8d, 0xfd, 0x8f, 0x37, 0x4d, 0xeb, 0xf5, 0x00, 0x6c, |
|
| 658 |
- 0xe2, 0x65, 0xfe, 0xbe, 0x6d, 0x83, 0xff, 0x27, 0x78, 0x40, 0x9c, 0x3c, 0x02, 0x0b, 0xfa, 0x79, |
|
| 659 |
- 0xa9, 0x63, 0x27, 0x61, 0x55, 0xae, 0xca, 0xf5, 0xfc, 0x41, 0xbc, 0x1e, 0x00, 0x00, 0xff, 0xff, |
|
| 660 |
- 0x87, 0x5c, 0xee, 0x2b, 0x7e, 0x11, 0x00, 0x00, |
|
| 593 |
+ // 1098 bytes of a gzipped FileDescriptorProto |
|
| 594 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x97, 0xc9, 0x6f, 0x1c, 0x45, |
|
| 595 |
+ 0x14, 0x87, 0x85, 0x70, 0xe4, 0x99, 0xe7, 0x0d, 0x8f, 0x8d, 0x09, 0x11, 0x88, 0xe4, 0xc6, 0xc9, |
|
| 596 |
+ 0x39, 0x45, 0x28, 0x65, 0x45, 0x96, 0x63, 0x39, 0xa3, 0x20, 0x0c, 0x23, 0x13, 0x07, 0x10, 0x87, |
|
| 597 |
+ 0x51, 0xcf, 0xb8, 0xdc, 0x19, 0xe8, 0xee, 0x6a, 0xba, 0xba, 0xa3, 0x38, 0x37, 0x14, 0x16, 0x21, |
|
| 598 |
+ 0xc4, 0x8e, 0x04, 0x09, 0x09, 0xcb, 0x81, 0x7d, 0x0d, 0xcb, 0x9d, 0x0b, 0x70, 0xe6, 0x7f, 0xe0, |
|
| 599 |
+ 0x02, 0x98, 0x4d, 0xf2, 0xcd, 0x17, 0xf4, 0xba, 0xdf, 0xeb, 0xa9, 0x1e, 0x8f, 0x54, 0x35, 0xb7, |
|
| 600 |
+ 0xf6, 0xb8, 0xbe, 0x6f, 0xaa, 0xdf, 0xeb, 0x7a, 0xbf, 0x69, 0x00, 0x5f, 0xf9, 0x6a, 0x31, 0x4e, |
|
| 601 |
+ 0x54, 0xaa, 0x1a, 0x75, 0xbc, 0xce, 0x2f, 0x8f, 0x1c, 0xf5, 0x95, 0xf2, 0x03, 0x79, 0x3c, 0xff, |
|
| 602 |
+ 0xab, 0x93, 0x6d, 0x1f, 0xdf, 0x92, 0xba, 0x9b, 0xf4, 0xe2, 0x54, 0x25, 0xc5, 0x62, 0xf1, 0x20, |
|
| 603 |
+ 0xcc, 0xd1, 0xe2, 0xb6, 0x8c, 0xb2, 0xb0, 0x1d, 0x27, 0x72, 0xbb, 0x77, 0xa9, 0x71, 0xd7, 0x62, |
|
| 604 |
+ 0x41, 0x2e, 0x32, 0xb9, 0xb8, 0x16, 0x65, 0xe1, 0x43, 0x71, 0xda, 0x53, 0x91, 0x3e, 0x7c, 0xf3, |
|
| 605 |
+ 0xb7, 0x5b, 0x8f, 0xde, 0x72, 0x6f, 0x6d, 0x63, 0x96, 0x50, 0xfc, 0x5f, 0x2b, 0x07, 0xc5, 0x06, |
|
| 606 |
+ 0xdc, 0x5e, 0xf1, 0xe9, 0x34, 0xe9, 0x45, 0xbe, 0x4c, 0x2c, 0xc6, 0x9f, 0xc8, 0x38, 0x67, 0x18, |
|
| 607 |
+ 0x1f, 0x26, 0x54, 0xac, 0xc2, 0xd4, 0x28, 0xae, 0x9f, 0xc9, 0x35, 0x29, 0x4d, 0x49, 0x13, 0x66, |
|
| 608 |
+ 0x72, 0x49, 0x37, 0xd3, 0xa9, 0x0a, 0x23, 0x2f, 0x94, 0x16, 0xcd, 0x2f, 0xb9, 0xa6, 0xbe, 0x31, |
|
| 609 |
+ 0x8d, 0xd8, 0x6a, 0x49, 0x89, 0xf3, 0x30, 0x8f, 0x9f, 0x5c, 0xf4, 0x82, 0x4c, 0x9a, 0xb6, 0x63, |
|
| 610 |
+ 0x43, 0x6d, 0xe7, 0x71, 0x19, 0x2b, 0x7f, 0xbd, 0x32, 0x96, 0x2b, 0xe7, 0x4a, 0x81, 0xe1, 0x35, |
|
| 611 |
+ 0x3a, 0xe1, 0xcb, 0x34, 0x95, 0x89, 0x6e, 0x7b, 0x41, 0x30, 0x64, 0x93, 0x67, 0x7a, 0x41, 0x69, |
|
| 612 |
+ 0xbc, 0xba, 0x5b, 0xed, 0x44, 0xb3, 0x20, 0x57, 0x82, 0x40, 0x6c, 0xc2, 0x1d, 0x43, 0x3a, 0xeb, |
|
| 613 |
+ 0xe0, 0xbc, 0x46, 0xce, 0xf9, 0x03, 0xdd, 0x45, 0x6d, 0x0b, 0xf8, 0xf3, 0xb2, 0x1f, 0x0e, 0xce, |
|
| 614 |
+ 0x77, 0xc8, 0xd9, 0x20, 0x96, 0xdb, 0x82, 0xc6, 0xfb, 0x61, 0xf6, 0xa2, 0x4c, 0x3a, 0x4a, 0xcb, |
|
| 615 |
+ 0xb6, 0x7c, 0x2a, 0xf3, 0x02, 0x07, 0xdd, 0x75, 0xd2, 0xcd, 0x10, 0xb8, 0x86, 0x1c, 0xba, 0x4e, |
|
| 616 |
+ 0x42, 0x6d, 0xdb, 0xeb, 0x4a, 0x07, 0xc5, 0x0d, 0x52, 0x8c, 0xe3, 0x7a, 0x44, 0x57, 0x60, 0xd2, |
|
| 617 |
+ 0x57, 0xc5, 0x2d, 0x39, 0xe0, 0xef, 0x12, 0x3e, 0xc1, 0x0c, 0x29, 0x62, 0x15, 0x67, 0x81, 0x97, |
|
| 618 |
+ 0xba, 0xec, 0xe0, 0x3d, 0x56, 0x30, 0x43, 0x8a, 0x11, 0xca, 0xfa, 0x3e, 0x2b, 0xb4, 0x51, 0xcf, |
|
| 619 |
+ 0x65, 0x98, 0x50, 0x51, 0xb0, 0xa3, 0x22, 0x97, 0x4d, 0x7c, 0x40, 0x06, 0x20, 0x04, 0x05, 0x4b, |
|
| 620 |
+ 0x50, 0x77, 0x6d, 0xc4, 0x87, 0x84, 0xd7, 0x24, 0x77, 0xa0, 0x09, 0x33, 0x3c, 0x64, 0x7a, 0x2a, |
|
| 621 |
+ 0x72, 0x50, 0x7c, 0x44, 0x8a, 0x69, 0x03, 0xa3, 0xdb, 0x48, 0xa5, 0x4e, 0x7d, 0xe9, 0x22, 0xf9, |
|
| 622 |
+ 0x98, 0x6f, 0x83, 0x10, 0x2a, 0x65, 0x47, 0x46, 0xdd, 0x0b, 0x6e, 0x86, 0x4f, 0xb8, 0x94, 0xcc, |
|
| 623 |
+ 0xa0, 0x62, 0x15, 0xa6, 0x42, 0x2f, 0xd1, 0x17, 0xbc, 0xc0, 0xa9, 0x1d, 0x9f, 0x92, 0x63, 0xb2, |
|
| 624 |
+ 0x84, 0xa8, 0x22, 0x59, 0x34, 0x8a, 0xe6, 0x33, 0xae, 0x88, 0x81, 0xd1, 0xd1, 0xd3, 0xa9, 0xd7, |
|
| 625 |
+ 0x09, 0x64, 0x7b, 0x14, 0xdb, 0xe7, 0x7c, 0xf4, 0x0a, 0x76, 0xdd, 0x34, 0x2e, 0x41, 0x5d, 0xf7, |
|
| 626 |
+ 0x2e, 0x3b, 0x69, 0xbe, 0xe0, 0x4e, 0xe7, 0x00, 0xc2, 0x8f, 0xc1, 0x9d, 0x43, 0x47, 0xbd, 0x83, |
|
| 627 |
+ 0xec, 0x4b, 0x92, 0x2d, 0x0c, 0x19, 0xf7, 0x34, 0x12, 0x46, 0x55, 0x7e, 0xc5, 0x23, 0x41, 0x0e, |
|
| 628 |
+ 0xb8, 0x5a, 0x30, 0x9f, 0x45, 0xda, 0xdb, 0x1e, 0xad, 0x6a, 0x5f, 0x73, 0xd5, 0x0a, 0xb6, 0x52, |
|
| 629 |
+ 0xb5, 0x73, 0xb0, 0x40, 0xc6, 0xd1, 0xfa, 0xfa, 0x0d, 0x0f, 0xd6, 0x82, 0xde, 0xac, 0x76, 0xf7, |
|
| 630 |
+ 0x71, 0x38, 0x52, 0x96, 0xf3, 0x52, 0x2a, 0x23, 0x8d, 0x4c, 0x3b, 0xf4, 0x62, 0x07, 0xf3, 0x4d, |
|
| 631 |
+ 0x32, 0xf3, 0xc4, 0x5f, 0x2b, 0x05, 0xeb, 0x5e, 0x8c, 0xf2, 0x47, 0xe1, 0x30, 0xcb, 0xb3, 0x28, |
|
| 632 |
+ 0x91, 0x5d, 0xe5, 0x47, 0xbd, 0xcb, 0x72, 0xcb, 0x41, 0xfd, 0xed, 0x40, 0xab, 0x36, 0x0d, 0x1c, |
|
| 633 |
+ 0xcd, 0x67, 0xe1, 0xb6, 0xf2, 0xf7, 0x46, 0xbb, 0x17, 0xc6, 0x2a, 0x49, 0x2d, 0xc6, 0xef, 0xb8, |
|
| 634 |
+ 0x53, 0x25, 0x77, 0x36, 0xc7, 0xc4, 0x1a, 0x4c, 0xe7, 0x7f, 0xba, 0x3e, 0x92, 0xdf, 0x93, 0x68, |
|
| 635 |
+ 0xaa, 0x4f, 0xd1, 0xe0, 0xe8, 0xaa, 0x30, 0xf6, 0x12, 0x97, 0xf9, 0xf7, 0x03, 0x0f, 0x0e, 0x42, |
|
| 636 |
+ 0x8a, 0xa7, 0x6f, 0x66, 0x20, 0x89, 0x1b, 0xf7, 0x1c, 0x90, 0xac, 0x4b, 0xad, 0x3d, 0xbf, 0xf4, |
|
| 637 |
+ 0x3c, 0xbd, 0x47, 0x67, 0xb6, 0x1a, 0xc4, 0xe2, 0x01, 0x2c, 0x4f, 0x35, 0x2e, 0xed, 0xb2, 0x2b, |
|
| 638 |
+ 0x7b, 0x65, 0x85, 0x2a, 0x69, 0x29, 0xce, 0xc0, 0x54, 0x25, 0x2a, 0xed, 0xaa, 0x67, 0x48, 0x35, |
|
| 639 |
+ 0x69, 0x26, 0xa5, 0x38, 0x01, 0x63, 0x18, 0x7b, 0x76, 0xfc, 0x59, 0xc2, 0xf3, 0xe5, 0xe2, 0x14, |
|
| 640 |
+ 0xd4, 0x38, 0xee, 0xec, 0xe8, 0x73, 0x84, 0x96, 0x08, 0xe2, 0x1c, 0x75, 0x76, 0xfc, 0x79, 0xc6, |
|
| 641 |
+ 0x19, 0x41, 0xdc, 0xbd, 0x84, 0x3f, 0xbe, 0x38, 0x46, 0xe3, 0x8a, 0x6b, 0xb7, 0x04, 0xe3, 0x94, |
|
| 642 |
+ 0x71, 0x76, 0xfa, 0x05, 0xfa, 0x72, 0x26, 0xc4, 0x7d, 0x70, 0xc8, 0xb1, 0xe0, 0x2f, 0x11, 0x5a, |
|
| 643 |
+ 0xac, 0x17, 0xab, 0x30, 0x61, 0xe4, 0x9a, 0x1d, 0x7f, 0x99, 0x70, 0x93, 0xc2, 0xad, 0x53, 0xae, |
|
| 644 |
+ 0xd9, 0x05, 0xaf, 0xf0, 0xd6, 0x89, 0xc0, 0xb2, 0x71, 0xa4, 0xd9, 0xe9, 0x57, 0xb9, 0xea, 0x8c, |
|
| 645 |
+ 0x88, 0x65, 0xa8, 0x97, 0x63, 0xca, 0xce, 0xbf, 0x46, 0x7c, 0x9f, 0xc1, 0x0a, 0x18, 0x63, 0xd2, |
|
| 646 |
+ 0xae, 0x78, 0x9d, 0x2b, 0x60, 0x50, 0x78, 0x8c, 0x06, 0xa3, 0xcf, 0x6e, 0x7a, 0x83, 0x8f, 0xd1, |
|
| 647 |
+ 0x40, 0xf2, 0x61, 0x37, 0xf3, 0x69, 0x61, 0x57, 0xbc, 0xc9, 0xdd, 0xcc, 0xd7, 0xe3, 0x36, 0x06, |
|
| 648 |
+ 0xb3, 0xc4, 0xee, 0x78, 0x8b, 0xb7, 0x31, 0x10, 0x25, 0xa2, 0x05, 0x8d, 0x83, 0x39, 0x62, 0xf7, |
|
| 649 |
+ 0xbd, 0x4d, 0xbe, 0xd9, 0x03, 0x31, 0x22, 0x1e, 0x81, 0x85, 0xe1, 0x19, 0x62, 0xb7, 0x5e, 0xdd, |
|
| 650 |
+ 0x1b, 0xf8, 0xd5, 0x6f, 0x46, 0x88, 0x38, 0xd7, 0xff, 0xd5, 0x6f, 0xe6, 0x87, 0x5d, 0x7b, 0x6d, |
|
| 651 |
+ 0xaf, 0xfa, 0x62, 0x67, 0xc6, 0x87, 0x58, 0x01, 0xe8, 0x8f, 0x6e, 0xbb, 0xeb, 0x3a, 0xb9, 0x0c, |
|
| 652 |
+ 0x08, 0x8f, 0x06, 0x4d, 0x6e, 0x3b, 0x7f, 0x83, 0x8f, 0x06, 0x11, 0x62, 0x09, 0x6a, 0x51, 0x16, |
|
| 653 |
+ 0x04, 0xf8, 0x70, 0x34, 0xee, 0x1e, 0x12, 0x13, 0x32, 0xd8, 0x62, 0xf6, 0xf7, 0x7d, 0x3a, 0x18, |
|
| 654 |
+ 0x0c, 0x88, 0x13, 0x70, 0x48, 0x86, 0x1d, 0xb9, 0x65, 0x23, 0xff, 0xd8, 0xe7, 0x81, 0x80, 0xab, |
|
| 655 |
+ 0xc5, 0x32, 0x40, 0xf1, 0xd2, 0x98, 0xee, 0xc4, 0xd6, 0x6f, 0xfd, 0x73, 0xbf, 0x78, 0x07, 0x35, |
|
| 656 |
+ 0x90, 0xbe, 0x20, 0x7f, 0xeb, 0xb4, 0x08, 0x76, 0xab, 0x82, 0xfc, 0x45, 0xf3, 0x24, 0x8c, 0x3f, |
|
| 657 |
+ 0xa1, 0x55, 0x94, 0x7a, 0xbe, 0x8d, 0xfe, 0x8b, 0x68, 0x5e, 0x8f, 0x05, 0x0b, 0x55, 0x22, 0x53, |
|
| 658 |
+ 0xcf, 0xd7, 0x36, 0xf6, 0x6f, 0x62, 0x4b, 0x00, 0xe1, 0xae, 0xa7, 0x53, 0x97, 0xfb, 0xfe, 0x87, |
|
| 659 |
+ 0x61, 0x06, 0x70, 0xd3, 0x78, 0xfd, 0xa4, 0xdc, 0xb1, 0xb1, 0xff, 0xf2, 0xa6, 0x69, 0xbd, 0x38, |
|
| 660 |
+ 0x05, 0x75, 0xbc, 0xcc, 0xdf, 0xb7, 0x6d, 0xf0, 0x7f, 0x04, 0xf7, 0x89, 0xd3, 0xc7, 0x60, 0xae, |
|
| 661 |
+ 0xab, 0xc2, 0x41, 0xec, 0x34, 0x34, 0x55, 0x53, 0xb5, 0xf2, 0x07, 0xf1, 0xff, 0x00, 0x00, 0x00, |
|
| 662 |
+ 0xff, 0xff, 0x87, 0x5c, 0xee, 0x2b, 0x7e, 0x11, 0x00, 0x00, |
|
| 661 | 663 |
} |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -1,4 +1,6 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 2 | 4 |
// http://github.com/gogo/protobuf |
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| ... | ... |
@@ -84,14 +84,20 @@ func mergeStruct(out, in reflect.Value) {
|
| 84 | 84 |
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
- if emIn, ok := in.Addr().Interface().(extensionsMap); ok {
|
|
| 88 |
- emOut := out.Addr().Interface().(extensionsMap) |
|
| 89 |
- mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) |
|
| 90 |
- } else if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
|
|
| 87 |
+ if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
|
|
| 91 | 88 |
emOut := out.Addr().Interface().(extensionsBytes) |
| 92 | 89 |
bIn := emIn.GetExtensions() |
| 93 | 90 |
bOut := emOut.GetExtensions() |
| 94 | 91 |
*bOut = append(*bOut, *bIn...) |
| 92 |
+ } else if emIn, ok := extendable(in.Addr().Interface()); ok {
|
|
| 93 |
+ emOut, _ := extendable(out.Addr().Interface()) |
|
| 94 |
+ mIn, muIn := emIn.extensionsRead() |
|
| 95 |
+ if mIn != nil {
|
|
| 96 |
+ mOut := emOut.extensionsWrite() |
|
| 97 |
+ muIn.Lock() |
|
| 98 |
+ mergeExtension(mOut, mIn) |
|
| 99 |
+ muIn.Unlock() |
|
| 100 |
+ } |
|
| 95 | 101 |
} |
| 96 | 102 |
|
| 97 | 103 |
uf := in.FieldByName("XXX_unrecognized")
|
| ... | ... |
@@ -378,6 +378,11 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group |
| 378 | 378 |
wire := int(u & 0x7) |
| 379 | 379 |
if wire == WireEndGroup {
|
| 380 | 380 |
if is_group {
|
| 381 |
+ if required > 0 {
|
|
| 382 |
+ // Not enough information to determine the exact field. |
|
| 383 |
+ // (See below.) |
|
| 384 |
+ return &RequiredNotSetError{"{Unknown}"}
|
|
| 385 |
+ } |
|
| 381 | 386 |
return nil // input is satisfied |
| 382 | 387 |
} |
| 383 | 388 |
return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
|
| ... | ... |
@@ -390,16 +395,20 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group |
| 390 | 390 |
if !ok {
|
| 391 | 391 |
// Maybe it's an extension? |
| 392 | 392 |
if prop.extendable {
|
| 393 |
- if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) {
|
|
| 394 |
- if err = o.skip(st, tag, wire); err == nil {
|
|
| 395 |
- if ee, eok := e.(extensionsMap); eok {
|
|
| 396 |
- ext := ee.ExtensionMap()[int32(tag)] // may be missing |
|
| 397 |
- ext.enc = append(ext.enc, o.buf[oi:o.index]...) |
|
| 398 |
- ee.ExtensionMap()[int32(tag)] = ext |
|
| 399 |
- } else if ee, eok := e.(extensionsBytes); eok {
|
|
| 400 |
- ext := ee.GetExtensions() |
|
| 393 |
+ if e, eok := structPointer_Interface(base, st).(extensionsBytes); eok {
|
|
| 394 |
+ if isExtensionField(e, int32(tag)) {
|
|
| 395 |
+ if err = o.skip(st, tag, wire); err == nil {
|
|
| 396 |
+ ext := e.GetExtensions() |
|
| 401 | 397 |
*ext = append(*ext, o.buf[oi:o.index]...) |
| 402 | 398 |
} |
| 399 |
+ continue |
|
| 400 |
+ } |
|
| 401 |
+ } else if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
|
|
| 402 |
+ if err = o.skip(st, tag, wire); err == nil {
|
|
| 403 |
+ extmap := e.extensionsWrite() |
|
| 404 |
+ ext := extmap[int32(tag)] // may be missing |
|
| 405 |
+ ext.enc = append(ext.enc, o.buf[oi:o.index]...) |
|
| 406 |
+ extmap[int32(tag)] = ext |
|
| 403 | 407 |
} |
| 404 | 408 |
continue |
| 405 | 409 |
} |
| ... | ... |
@@ -773,10 +782,11 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
|
| 773 | 773 |
} |
| 774 | 774 |
} |
| 775 | 775 |
keyelem, valelem := keyptr.Elem(), valptr.Elem() |
| 776 |
- if !keyelem.IsValid() || !valelem.IsValid() {
|
|
| 777 |
- // We did not decode the key or the value in the map entry. |
|
| 778 |
- // Either way, it's an invalid map entry. |
|
| 779 |
- return fmt.Errorf("proto: bad map data: missing key/val")
|
|
| 776 |
+ if !keyelem.IsValid() {
|
|
| 777 |
+ keyelem = reflect.Zero(p.mtype.Key()) |
|
| 778 |
+ } |
|
| 779 |
+ if !valelem.IsValid() {
|
|
| 780 |
+ valelem = reflect.Zero(p.mtype.Elem()) |
|
| 780 | 781 |
} |
| 781 | 782 |
|
| 782 | 783 |
v.SetMapIndex(keyelem, valelem) |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -64,8 +64,16 @@ var ( |
| 64 | 64 |
// a struct with a repeated field containing a nil element. |
| 65 | 65 |
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
| 66 | 66 |
|
| 67 |
+ // errOneofHasNil is the error returned if Marshal is called with |
|
| 68 |
+ // a struct with a oneof field containing a nil element. |
|
| 69 |
+ errOneofHasNil = errors.New("proto: oneof field has nil value")
|
|
| 70 |
+ |
|
| 67 | 71 |
// ErrNil is the error returned if Marshal is called with nil. |
| 68 | 72 |
ErrNil = errors.New("proto: Marshal called with nil")
|
| 73 |
+ |
|
| 74 |
+ // ErrTooLarge is the error returned if Marshal is called with a |
|
| 75 |
+ // message that encodes to >2GB. |
|
| 76 |
+ ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
|
| 69 | 77 |
) |
| 70 | 78 |
|
| 71 | 79 |
// The fundamental encoders that put bytes on the wire. |
| ... | ... |
@@ -74,6 +82,10 @@ var ( |
| 74 | 74 |
|
| 75 | 75 |
const maxVarintBytes = 10 // maximum length of a varint |
| 76 | 76 |
|
| 77 |
+// maxMarshalSize is the largest allowed size of an encoded protobuf, |
|
| 78 |
+// since C++ and Java use signed int32s for the size. |
|
| 79 |
+const maxMarshalSize = 1<<31 - 1 |
|
| 80 |
+ |
|
| 77 | 81 |
// EncodeVarint returns the varint encoding of x. |
| 78 | 82 |
// This is the format for the |
| 79 | 83 |
// int32, int64, uint32, uint64, bool, and enum |
| ... | ... |
@@ -273,6 +285,9 @@ func (p *Buffer) Marshal(pb Message) error {
|
| 273 | 273 |
stats.Encode++ |
| 274 | 274 |
} |
| 275 | 275 |
|
| 276 |
+ if len(p.buf) > maxMarshalSize {
|
|
| 277 |
+ return ErrTooLarge |
|
| 278 |
+ } |
|
| 276 | 279 |
return err |
| 277 | 280 |
} |
| 278 | 281 |
|
| ... | ... |
@@ -1058,10 +1073,25 @@ func size_slice_struct_group(p *Properties, base structPointer) (n int) {
|
| 1058 | 1058 |
|
| 1059 | 1059 |
// Encode an extension map. |
| 1060 | 1060 |
func (o *Buffer) enc_map(p *Properties, base structPointer) error {
|
| 1061 |
- v := *structPointer_ExtMap(base, p.field) |
|
| 1062 |
- if err := encodeExtensionMap(v); err != nil {
|
|
| 1061 |
+ exts := structPointer_ExtMap(base, p.field) |
|
| 1062 |
+ if err := encodeExtensionsMap(*exts); err != nil {
|
|
| 1063 |
+ return err |
|
| 1064 |
+ } |
|
| 1065 |
+ |
|
| 1066 |
+ return o.enc_map_body(*exts) |
|
| 1067 |
+} |
|
| 1068 |
+ |
|
| 1069 |
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
|
|
| 1070 |
+ exts := structPointer_Extensions(base, p.field) |
|
| 1071 |
+ if err := encodeExtensions(exts); err != nil {
|
|
| 1063 | 1072 |
return err |
| 1064 | 1073 |
} |
| 1074 |
+ v, _ := exts.extensionsRead() |
|
| 1075 |
+ |
|
| 1076 |
+ return o.enc_map_body(v) |
|
| 1077 |
+} |
|
| 1078 |
+ |
|
| 1079 |
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
|
|
| 1065 | 1080 |
// Fast-path for common cases: zero or one extensions. |
| 1066 | 1081 |
if len(v) <= 1 {
|
| 1067 | 1082 |
for _, e := range v {
|
| ... | ... |
@@ -1084,8 +1114,13 @@ func (o *Buffer) enc_map(p *Properties, base structPointer) error {
|
| 1084 | 1084 |
} |
| 1085 | 1085 |
|
| 1086 | 1086 |
func size_map(p *Properties, base structPointer) int {
|
| 1087 |
- v := *structPointer_ExtMap(base, p.field) |
|
| 1088 |
- return sizeExtensionMap(v) |
|
| 1087 |
+ v := structPointer_ExtMap(base, p.field) |
|
| 1088 |
+ return extensionsMapSize(*v) |
|
| 1089 |
+} |
|
| 1090 |
+ |
|
| 1091 |
+func size_exts(p *Properties, base structPointer) int {
|
|
| 1092 |
+ v := structPointer_Extensions(base, p.field) |
|
| 1093 |
+ return extensionsSize(v) |
|
| 1089 | 1094 |
} |
| 1090 | 1095 |
|
| 1091 | 1096 |
// Encode a map field. |
| ... | ... |
@@ -1114,7 +1149,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
|
| 1114 | 1114 |
if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
|
| 1115 | 1115 |
return err |
| 1116 | 1116 |
} |
| 1117 |
- if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil {
|
|
| 1117 |
+ if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
|
|
| 1118 | 1118 |
return err |
| 1119 | 1119 |
} |
| 1120 | 1120 |
return nil |
| ... | ... |
@@ -1124,11 +1159,6 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
|
| 1124 | 1124 |
for _, key := range v.MapKeys() {
|
| 1125 | 1125 |
val := v.MapIndex(key) |
| 1126 | 1126 |
|
| 1127 |
- // The only illegal map entry values are nil message pointers. |
|
| 1128 |
- if val.Kind() == reflect.Ptr && val.IsNil() {
|
|
| 1129 |
- return errors.New("proto: map has nil element")
|
|
| 1130 |
- } |
|
| 1131 |
- |
|
| 1132 | 1127 |
keycopy.Set(key) |
| 1133 | 1128 |
valcopy.Set(val) |
| 1134 | 1129 |
|
| ... | ... |
@@ -1216,13 +1246,18 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
| 1216 | 1216 |
return err |
| 1217 | 1217 |
} |
| 1218 | 1218 |
} |
| 1219 |
+ if len(o.buf) > maxMarshalSize {
|
|
| 1220 |
+ return ErrTooLarge |
|
| 1221 |
+ } |
|
| 1219 | 1222 |
} |
| 1220 | 1223 |
} |
| 1221 | 1224 |
|
| 1222 | 1225 |
// Do oneof fields. |
| 1223 | 1226 |
if prop.oneofMarshaler != nil {
|
| 1224 | 1227 |
m := structPointer_Interface(base, prop.stype).(Message) |
| 1225 |
- if err := prop.oneofMarshaler(m, o); err != nil {
|
|
| 1228 |
+ if err := prop.oneofMarshaler(m, o); err == ErrNil {
|
|
| 1229 |
+ return errOneofHasNil |
|
| 1230 |
+ } else if err != nil {
|
|
| 1226 | 1231 |
return err |
| 1227 | 1232 |
} |
| 1228 | 1233 |
} |
| ... | ... |
@@ -1230,6 +1265,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
| 1230 | 1230 |
// Add unrecognized fields at the end. |
| 1231 | 1231 |
if prop.unrecField.IsValid() {
|
| 1232 | 1232 |
v := *structPointer_Bytes(base, prop.unrecField) |
| 1233 |
+ if len(o.buf)+len(v) > maxMarshalSize {
|
|
| 1234 |
+ return ErrTooLarge |
|
| 1235 |
+ } |
|
| 1233 | 1236 |
if len(v) > 0 {
|
| 1234 | 1237 |
o.buf = append(o.buf, v...) |
| 1235 | 1238 |
} |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-// Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
// |
| 3 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 5 | 5 |
// |
| 6 | 6 |
// Go support for Protocol Buffers - Google's data interchange format |
| 7 | 7 |
// |
| ... | ... |
@@ -121,9 +121,16 @@ func equalStruct(v1, v2 reflect.Value) bool {
|
| 121 | 121 |
} |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 |
+ if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
|
|
| 125 |
+ em2 := v2.FieldByName("XXX_InternalExtensions")
|
|
| 126 |
+ if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
|
|
| 127 |
+ return false |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 124 | 131 |
if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
|
| 125 | 132 |
em2 := v2.FieldByName("XXX_extensions")
|
| 126 |
- if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
| 133 |
+ if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
| 127 | 134 |
return false |
| 128 | 135 |
} |
| 129 | 136 |
} |
| ... | ... |
@@ -184,6 +191,13 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
| 184 | 184 |
} |
| 185 | 185 |
return true |
| 186 | 186 |
case reflect.Ptr: |
| 187 |
+ // Maps may have nil values in them, so check for nil. |
|
| 188 |
+ if v1.IsNil() && v2.IsNil() {
|
|
| 189 |
+ return true |
|
| 190 |
+ } |
|
| 191 |
+ if v1.IsNil() != v2.IsNil() {
|
|
| 192 |
+ return false |
|
| 193 |
+ } |
|
| 187 | 194 |
return equalAny(v1.Elem(), v2.Elem(), prop) |
| 188 | 195 |
case reflect.Slice: |
| 189 | 196 |
if v1.Type().Elem().Kind() == reflect.Uint8 {
|
| ... | ... |
@@ -223,8 +237,14 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 | 225 |
// base is the struct type that the extensions are based on. |
| 226 |
-// em1 and em2 are extension maps. |
|
| 227 |
-func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
| 226 |
+// x1 and x2 are InternalExtensions. |
|
| 227 |
+func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
|
|
| 228 |
+ em1, _ := x1.extensionsRead() |
|
| 229 |
+ em2, _ := x2.extensionsRead() |
|
| 230 |
+ return equalExtMap(base, em1, em2) |
|
| 231 |
+} |
|
| 232 |
+ |
|
| 233 |
+func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
| 228 | 234 |
if len(em1) != len(em2) {
|
| 229 | 235 |
return false |
| 230 | 236 |
} |
| ... | ... |
@@ -52,23 +52,112 @@ type ExtensionRange struct {
|
| 52 | 52 |
Start, End int32 // both inclusive |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
-// extendableProto is an interface implemented by any protocol buffer that may be extended. |
|
| 55 |
+// extendableProto is an interface implemented by any protocol buffer generated by the current |
|
| 56 |
+// proto compiler that may be extended. |
|
| 56 | 57 |
type extendableProto interface {
|
| 57 | 58 |
Message |
| 58 | 59 |
ExtensionRangeArray() []ExtensionRange |
| 60 |
+ extensionsWrite() map[int32]Extension |
|
| 61 |
+ extensionsRead() (map[int32]Extension, sync.Locker) |
|
| 59 | 62 |
} |
| 60 | 63 |
|
| 61 |
-type extensionsMap interface {
|
|
| 62 |
- extendableProto |
|
| 64 |
+// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous |
|
| 65 |
+// version of the proto compiler that may be extended. |
|
| 66 |
+type extendableProtoV1 interface {
|
|
| 67 |
+ Message |
|
| 68 |
+ ExtensionRangeArray() []ExtensionRange |
|
| 63 | 69 |
ExtensionMap() map[int32]Extension |
| 64 | 70 |
} |
| 65 | 71 |
|
| 66 | 72 |
type extensionsBytes interface {
|
| 67 |
- extendableProto |
|
| 73 |
+ Message |
|
| 74 |
+ ExtensionRangeArray() []ExtensionRange |
|
| 68 | 75 |
GetExtensions() *[]byte |
| 69 | 76 |
} |
| 70 | 77 |
|
| 78 |
+// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. |
|
| 79 |
+type extensionAdapter struct {
|
|
| 80 |
+ extendableProtoV1 |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+func (e extensionAdapter) extensionsWrite() map[int32]Extension {
|
|
| 84 |
+ return e.ExtensionMap() |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
| 88 |
+ return e.ExtensionMap(), notLocker{}
|
|
| 89 |
+} |
|
| 90 |
+ |
|
| 91 |
+// notLocker is a sync.Locker whose Lock and Unlock methods are nops. |
|
| 92 |
+type notLocker struct{}
|
|
| 93 |
+ |
|
| 94 |
+func (n notLocker) Lock() {}
|
|
| 95 |
+func (n notLocker) Unlock() {}
|
|
| 96 |
+ |
|
| 97 |
+// extendable returns the extendableProto interface for the given generated proto message. |
|
| 98 |
+// If the proto message has the old extension format, it returns a wrapper that implements |
|
| 99 |
+// the extendableProto interface. |
|
| 100 |
+func extendable(p interface{}) (extendableProto, bool) {
|
|
| 101 |
+ if ep, ok := p.(extendableProto); ok {
|
|
| 102 |
+ return ep, ok |
|
| 103 |
+ } |
|
| 104 |
+ if ep, ok := p.(extendableProtoV1); ok {
|
|
| 105 |
+ return extensionAdapter{ep}, ok
|
|
| 106 |
+ } |
|
| 107 |
+ return nil, false |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+// XXX_InternalExtensions is an internal representation of proto extensions. |
|
| 111 |
+// |
|
| 112 |
+// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, |
|
| 113 |
+// thus gaining the unexported 'extensions' method, which can be called only from the proto package. |
|
| 114 |
+// |
|
| 115 |
+// The methods of XXX_InternalExtensions are not concurrency safe in general, |
|
| 116 |
+// but calls to logically read-only methods such as has and get may be executed concurrently. |
|
| 117 |
+type XXX_InternalExtensions struct {
|
|
| 118 |
+ // The struct must be indirect so that if a user inadvertently copies a |
|
| 119 |
+ // generated message and its embedded XXX_InternalExtensions, they |
|
| 120 |
+ // avoid the mayhem of a copied mutex. |
|
| 121 |
+ // |
|
| 122 |
+ // The mutex serializes all logically read-only operations to p.extensionMap. |
|
| 123 |
+ // It is up to the client to ensure that write operations to p.extensionMap are |
|
| 124 |
+ // mutually exclusive with other accesses. |
|
| 125 |
+ p *struct {
|
|
| 126 |
+ mu sync.Mutex |
|
| 127 |
+ extensionMap map[int32]Extension |
|
| 128 |
+ } |
|
| 129 |
+} |
|
| 130 |
+ |
|
| 131 |
+// extensionsWrite returns the extension map, creating it on first use. |
|
| 132 |
+func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
|
|
| 133 |
+ if e.p == nil {
|
|
| 134 |
+ e.p = new(struct {
|
|
| 135 |
+ mu sync.Mutex |
|
| 136 |
+ extensionMap map[int32]Extension |
|
| 137 |
+ }) |
|
| 138 |
+ e.p.extensionMap = make(map[int32]Extension) |
|
| 139 |
+ } |
|
| 140 |
+ return e.p.extensionMap |
|
| 141 |
+} |
|
| 142 |
+ |
|
| 143 |
+// extensionsRead returns the extensions map for read-only use. It may be nil. |
|
| 144 |
+// The caller must hold the returned mutex's lock when accessing Elements within the map. |
|
| 145 |
+func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
| 146 |
+ if e.p == nil {
|
|
| 147 |
+ return nil, nil |
|
| 148 |
+ } |
|
| 149 |
+ return e.p.extensionMap, &e.p.mu |
|
| 150 |
+} |
|
| 151 |
+ |
|
| 152 |
+type extensionRange interface {
|
|
| 153 |
+ Message |
|
| 154 |
+ ExtensionRangeArray() []ExtensionRange |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 71 | 157 |
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() |
| 158 |
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() |
|
| 159 |
+var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem() |
|
| 160 |
+var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem() |
|
| 72 | 161 |
|
| 73 | 162 |
// ExtensionDesc represents an extension specification. |
| 74 | 163 |
// Used in generated code from the protocol compiler. |
| ... | ... |
@@ -101,20 +190,23 @@ type Extension struct {
|
| 101 | 101 |
} |
| 102 | 102 |
|
| 103 | 103 |
// SetRawExtension is for testing only. |
| 104 |
-func SetRawExtension(base extendableProto, id int32, b []byte) {
|
|
| 105 |
- if ebase, ok := base.(extensionsMap); ok {
|
|
| 106 |
- ebase.ExtensionMap()[id] = Extension{enc: b}
|
|
| 107 |
- } else if ebase, ok := base.(extensionsBytes); ok {
|
|
| 104 |
+func SetRawExtension(base Message, id int32, b []byte) {
|
|
| 105 |
+ if ebase, ok := base.(extensionsBytes); ok {
|
|
| 108 | 106 |
clearExtension(base, id) |
| 109 | 107 |
ext := ebase.GetExtensions() |
| 110 | 108 |
*ext = append(*ext, b...) |
| 111 |
- } else {
|
|
| 112 |
- panic("unreachable")
|
|
| 109 |
+ return |
|
| 110 |
+ } |
|
| 111 |
+ epb, ok := extendable(base) |
|
| 112 |
+ if !ok {
|
|
| 113 |
+ return |
|
| 113 | 114 |
} |
| 115 |
+ extmap := epb.extensionsWrite() |
|
| 116 |
+ extmap[id] = Extension{enc: b}
|
|
| 114 | 117 |
} |
| 115 | 118 |
|
| 116 | 119 |
// isExtensionField returns true iff the given field number is in an extension range. |
| 117 |
-func isExtensionField(pb extendableProto, field int32) bool {
|
|
| 120 |
+func isExtensionField(pb extensionRange, field int32) bool {
|
|
| 118 | 121 |
for _, er := range pb.ExtensionRangeArray() {
|
| 119 | 122 |
if er.Start <= field && field <= er.End {
|
| 120 | 123 |
return true |
| ... | ... |
@@ -125,8 +217,12 @@ func isExtensionField(pb extendableProto, field int32) bool {
|
| 125 | 125 |
|
| 126 | 126 |
// checkExtensionTypes checks that the given extension is valid for pb. |
| 127 | 127 |
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
|
| 128 |
+ var pbi interface{} = pb
|
|
| 128 | 129 |
// Check the extended type. |
| 129 |
- if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
|
|
| 130 |
+ if ea, ok := pbi.(extensionAdapter); ok {
|
|
| 131 |
+ pbi = ea.extendableProtoV1 |
|
| 132 |
+ } |
|
| 133 |
+ if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
|
|
| 130 | 134 |
return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
|
| 131 | 135 |
} |
| 132 | 136 |
// Check the range. |
| ... | ... |
@@ -172,43 +268,57 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
|
| 172 | 172 |
return prop |
| 173 | 173 |
} |
| 174 | 174 |
|
| 175 |
-// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. |
|
| 176 |
-func encodeExtensionMap(m map[int32]Extension) error {
|
|
| 175 |
+// encode encodes any unmarshaled (unencoded) extensions in e. |
|
| 176 |
+func encodeExtensions(e *XXX_InternalExtensions) error {
|
|
| 177 |
+ m, mu := e.extensionsRead() |
|
| 178 |
+ if m == nil {
|
|
| 179 |
+ return nil // fast path |
|
| 180 |
+ } |
|
| 181 |
+ mu.Lock() |
|
| 182 |
+ defer mu.Unlock() |
|
| 183 |
+ return encodeExtensionsMap(m) |
|
| 184 |
+} |
|
| 185 |
+ |
|
| 186 |
+// encode encodes any unmarshaled (unencoded) extensions in e. |
|
| 187 |
+func encodeExtensionsMap(m map[int32]Extension) error {
|
|
| 177 | 188 |
for k, e := range m {
|
| 178 |
- err := encodeExtension(&e) |
|
| 179 |
- if err != nil {
|
|
| 189 |
+ if e.value == nil || e.desc == nil {
|
|
| 190 |
+ // Extension is only in its encoded form. |
|
| 191 |
+ continue |
|
| 192 |
+ } |
|
| 193 |
+ |
|
| 194 |
+ // We don't skip extensions that have an encoded form set, |
|
| 195 |
+ // because the extension value may have been mutated after |
|
| 196 |
+ // the last time this function was called. |
|
| 197 |
+ |
|
| 198 |
+ et := reflect.TypeOf(e.desc.ExtensionType) |
|
| 199 |
+ props := extensionProperties(e.desc) |
|
| 200 |
+ |
|
| 201 |
+ p := NewBuffer(nil) |
|
| 202 |
+ // If e.value has type T, the encoder expects a *struct{ X T }.
|
|
| 203 |
+ // Pass a *T with a zero field and hope it all works out. |
|
| 204 |
+ x := reflect.New(et) |
|
| 205 |
+ x.Elem().Set(reflect.ValueOf(e.value)) |
|
| 206 |
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
| 180 | 207 |
return err |
| 181 | 208 |
} |
| 209 |
+ e.enc = p.buf |
|
| 182 | 210 |
m[k] = e |
| 183 | 211 |
} |
| 184 | 212 |
return nil |
| 185 | 213 |
} |
| 186 | 214 |
|
| 187 |
-func encodeExtension(e *Extension) error {
|
|
| 188 |
- if e.value == nil || e.desc == nil {
|
|
| 189 |
- // Extension is only in its encoded form. |
|
| 190 |
- return nil |
|
| 191 |
- } |
|
| 192 |
- // We don't skip extensions that have an encoded form set, |
|
| 193 |
- // because the extension value may have been mutated after |
|
| 194 |
- // the last time this function was called. |
|
| 195 |
- |
|
| 196 |
- et := reflect.TypeOf(e.desc.ExtensionType) |
|
| 197 |
- props := extensionProperties(e.desc) |
|
| 198 |
- |
|
| 199 |
- p := NewBuffer(nil) |
|
| 200 |
- // If e.value has type T, the encoder expects a *struct{ X T }.
|
|
| 201 |
- // Pass a *T with a zero field and hope it all works out. |
|
| 202 |
- x := reflect.New(et) |
|
| 203 |
- x.Elem().Set(reflect.ValueOf(e.value)) |
|
| 204 |
- if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
| 205 |
- return err |
|
| 215 |
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
|
|
| 216 |
+ m, mu := e.extensionsRead() |
|
| 217 |
+ if m == nil {
|
|
| 218 |
+ return 0 |
|
| 206 | 219 |
} |
| 207 |
- e.enc = p.buf |
|
| 208 |
- return nil |
|
| 220 |
+ mu.Lock() |
|
| 221 |
+ defer mu.Unlock() |
|
| 222 |
+ return extensionsMapSize(m) |
|
| 209 | 223 |
} |
| 210 | 224 |
|
| 211 |
-func sizeExtensionMap(m map[int32]Extension) (n int) {
|
|
| 225 |
+func extensionsMapSize(m map[int32]Extension) (n int) {
|
|
| 212 | 226 |
for _, e := range m {
|
| 213 | 227 |
if e.value == nil || e.desc == nil {
|
| 214 | 228 |
// Extension is only in its encoded form. |
| ... | ... |
@@ -233,12 +343,8 @@ func sizeExtensionMap(m map[int32]Extension) (n int) {
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
// HasExtension returns whether the given extension is present in pb. |
| 236 |
-func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
|
|
| 237 |
- // TODO: Check types, field numbers, etc.? |
|
| 238 |
- if epb, doki := pb.(extensionsMap); doki {
|
|
| 239 |
- _, ok := epb.ExtensionMap()[extension.Field] |
|
| 240 |
- return ok |
|
| 241 |
- } else if epb, doki := pb.(extensionsBytes); doki {
|
|
| 236 |
+func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
|
| 237 |
+ if epb, doki := pb.(extensionsBytes); doki {
|
|
| 242 | 238 |
ext := epb.GetExtensions() |
| 243 | 239 |
buf := *ext |
| 244 | 240 |
o := 0 |
| ... | ... |
@@ -258,7 +364,19 @@ func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
|
| 258 | 258 |
} |
| 259 | 259 |
return false |
| 260 | 260 |
} |
| 261 |
- panic("unreachable")
|
|
| 261 |
+ // TODO: Check types, field numbers, etc.? |
|
| 262 |
+ epb, ok := extendable(pb) |
|
| 263 |
+ if !ok {
|
|
| 264 |
+ return false |
|
| 265 |
+ } |
|
| 266 |
+ extmap, mu := epb.extensionsRead() |
|
| 267 |
+ if extmap == nil {
|
|
| 268 |
+ return false |
|
| 269 |
+ } |
|
| 270 |
+ mu.Lock() |
|
| 271 |
+ _, ok = extmap[extension.Field] |
|
| 272 |
+ mu.Unlock() |
|
| 273 |
+ return ok |
|
| 262 | 274 |
} |
| 263 | 275 |
|
| 264 | 276 |
func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
|
| ... | ... |
@@ -281,64 +399,32 @@ func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
|
| 281 | 281 |
return -1 |
| 282 | 282 |
} |
| 283 | 283 |
|
| 284 |
-func clearExtension(pb extendableProto, fieldNum int32) {
|
|
| 285 |
- if epb, doki := pb.(extensionsMap); doki {
|
|
| 286 |
- delete(epb.ExtensionMap(), fieldNum) |
|
| 287 |
- } else if epb, doki := pb.(extensionsBytes); doki {
|
|
| 284 |
+// ClearExtension removes the given extension from pb. |
|
| 285 |
+func ClearExtension(pb Message, extension *ExtensionDesc) {
|
|
| 286 |
+ clearExtension(pb, extension.Field) |
|
| 287 |
+} |
|
| 288 |
+ |
|
| 289 |
+func clearExtension(pb Message, fieldNum int32) {
|
|
| 290 |
+ if epb, doki := pb.(extensionsBytes); doki {
|
|
| 288 | 291 |
offset := 0 |
| 289 | 292 |
for offset != -1 {
|
| 290 | 293 |
offset = deleteExtension(epb, fieldNum, offset) |
| 291 | 294 |
} |
| 292 |
- } else {
|
|
| 293 |
- panic("unreachable")
|
|
| 295 |
+ return |
|
| 296 |
+ } |
|
| 297 |
+ epb, ok := extendable(pb) |
|
| 298 |
+ if !ok {
|
|
| 299 |
+ return |
|
| 294 | 300 |
} |
| 295 |
-} |
|
| 296 |
- |
|
| 297 |
-// ClearExtension removes the given extension from pb. |
|
| 298 |
-func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
|
|
| 299 | 301 |
// TODO: Check types, field numbers, etc.? |
| 300 |
- clearExtension(pb, extension.Field) |
|
| 302 |
+ extmap := epb.extensionsWrite() |
|
| 303 |
+ delete(extmap, fieldNum) |
|
| 301 | 304 |
} |
| 302 | 305 |
|
| 303 | 306 |
// GetExtension parses and returns the given extension of pb. |
| 304 |
-// If the extension is not present it returns ErrMissingExtension. |
|
| 305 |
-func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
|
|
| 306 |
- if err := checkExtensionTypes(pb, extension); err != nil {
|
|
| 307 |
- return nil, err |
|
| 308 |
- } |
|
| 309 |
- |
|
| 310 |
- if epb, doki := pb.(extensionsMap); doki {
|
|
| 311 |
- emap := epb.ExtensionMap() |
|
| 312 |
- e, ok := emap[extension.Field] |
|
| 313 |
- if !ok {
|
|
| 314 |
- // defaultExtensionValue returns the default value or |
|
| 315 |
- // ErrMissingExtension if there is no default. |
|
| 316 |
- return defaultExtensionValue(extension) |
|
| 317 |
- } |
|
| 318 |
- if e.value != nil {
|
|
| 319 |
- // Already decoded. Check the descriptor, though. |
|
| 320 |
- if e.desc != extension {
|
|
| 321 |
- // This shouldn't happen. If it does, it means that |
|
| 322 |
- // GetExtension was called twice with two different |
|
| 323 |
- // descriptors with the same field number. |
|
| 324 |
- return nil, errors.New("proto: descriptor conflict")
|
|
| 325 |
- } |
|
| 326 |
- return e.value, nil |
|
| 327 |
- } |
|
| 328 |
- |
|
| 329 |
- v, err := decodeExtension(e.enc, extension) |
|
| 330 |
- if err != nil {
|
|
| 331 |
- return nil, err |
|
| 332 |
- } |
|
| 333 |
- |
|
| 334 |
- // Remember the decoded version and drop the encoded version. |
|
| 335 |
- // That way it is safe to mutate what we return. |
|
| 336 |
- e.value = v |
|
| 337 |
- e.desc = extension |
|
| 338 |
- e.enc = nil |
|
| 339 |
- emap[extension.Field] = e |
|
| 340 |
- return e.value, nil |
|
| 341 |
- } else if epb, doki := pb.(extensionsBytes); doki {
|
|
| 307 |
+// If the extension is not present and has no default value it returns ErrMissingExtension. |
|
| 308 |
+func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|
| 309 |
+ if epb, doki := pb.(extensionsBytes); doki {
|
|
| 342 | 310 |
ext := epb.GetExtensions() |
| 343 | 311 |
o := 0 |
| 344 | 312 |
for o < len(*ext) {
|
| ... | ... |
@@ -360,7 +446,50 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
|
| 360 | 360 |
} |
| 361 | 361 |
return defaultExtensionValue(extension) |
| 362 | 362 |
} |
| 363 |
- panic("unreachable")
|
|
| 363 |
+ epb, ok := extendable(pb) |
|
| 364 |
+ if !ok {
|
|
| 365 |
+ return nil, errors.New("proto: not an extendable proto")
|
|
| 366 |
+ } |
|
| 367 |
+ if err := checkExtensionTypes(epb, extension); err != nil {
|
|
| 368 |
+ return nil, err |
|
| 369 |
+ } |
|
| 370 |
+ |
|
| 371 |
+ emap, mu := epb.extensionsRead() |
|
| 372 |
+ if emap == nil {
|
|
| 373 |
+ return defaultExtensionValue(extension) |
|
| 374 |
+ } |
|
| 375 |
+ mu.Lock() |
|
| 376 |
+ defer mu.Unlock() |
|
| 377 |
+ e, ok := emap[extension.Field] |
|
| 378 |
+ if !ok {
|
|
| 379 |
+ // defaultExtensionValue returns the default value or |
|
| 380 |
+ // ErrMissingExtension if there is no default. |
|
| 381 |
+ return defaultExtensionValue(extension) |
|
| 382 |
+ } |
|
| 383 |
+ |
|
| 384 |
+ if e.value != nil {
|
|
| 385 |
+ // Already decoded. Check the descriptor, though. |
|
| 386 |
+ if e.desc != extension {
|
|
| 387 |
+ // This shouldn't happen. If it does, it means that |
|
| 388 |
+ // GetExtension was called twice with two different |
|
| 389 |
+ // descriptors with the same field number. |
|
| 390 |
+ return nil, errors.New("proto: descriptor conflict")
|
|
| 391 |
+ } |
|
| 392 |
+ return e.value, nil |
|
| 393 |
+ } |
|
| 394 |
+ |
|
| 395 |
+ v, err := decodeExtension(e.enc, extension) |
|
| 396 |
+ if err != nil {
|
|
| 397 |
+ return nil, err |
|
| 398 |
+ } |
|
| 399 |
+ |
|
| 400 |
+ // Remember the decoded version and drop the encoded version. |
|
| 401 |
+ // That way it is safe to mutate what we return. |
|
| 402 |
+ e.value = v |
|
| 403 |
+ e.desc = extension |
|
| 404 |
+ e.enc = nil |
|
| 405 |
+ emap[extension.Field] = e |
|
| 406 |
+ return e.value, nil |
|
| 364 | 407 |
} |
| 365 | 408 |
|
| 366 | 409 |
// defaultExtensionValue returns the default value for extension. |
| ... | ... |
@@ -434,14 +563,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
| 434 | 434 |
// GetExtensions returns a slice of the extensions present in pb that are also listed in es. |
| 435 | 435 |
// The returned slice has the same length as es; missing extensions will appear as nil elements. |
| 436 | 436 |
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
|
| 437 |
- epb, ok := pb.(extendableProto) |
|
| 438 |
- if !ok {
|
|
| 439 |
- err = errors.New("proto: not an extendable proto")
|
|
| 440 |
- return |
|
| 441 |
- } |
|
| 442 | 437 |
extensions = make([]interface{}, len(es))
|
| 443 | 438 |
for i, e := range es {
|
| 444 |
- extensions[i], err = GetExtension(epb, e) |
|
| 439 |
+ extensions[i], err = GetExtension(pb, e) |
|
| 445 | 440 |
if err == ErrMissingExtension {
|
| 446 | 441 |
err = nil |
| 447 | 442 |
} |
| ... | ... |
@@ -452,9 +576,55 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
|
| 452 | 452 |
return |
| 453 | 453 |
} |
| 454 | 454 |
|
| 455 |
+// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. |
|
| 456 |
+// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing |
|
| 457 |
+// just the Field field, which defines the extension's field number. |
|
| 458 |
+func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
|
| 459 |
+ epb, ok := extendable(pb) |
|
| 460 |
+ if !ok {
|
|
| 461 |
+ return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
|
|
| 462 |
+ } |
|
| 463 |
+ registeredExtensions := RegisteredExtensions(pb) |
|
| 464 |
+ |
|
| 465 |
+ emap, mu := epb.extensionsRead() |
|
| 466 |
+ mu.Lock() |
|
| 467 |
+ defer mu.Unlock() |
|
| 468 |
+ extensions := make([]*ExtensionDesc, 0, len(emap)) |
|
| 469 |
+ for extid, e := range emap {
|
|
| 470 |
+ desc := e.desc |
|
| 471 |
+ if desc == nil {
|
|
| 472 |
+ desc = registeredExtensions[extid] |
|
| 473 |
+ if desc == nil {
|
|
| 474 |
+ desc = &ExtensionDesc{Field: extid}
|
|
| 475 |
+ } |
|
| 476 |
+ } |
|
| 477 |
+ |
|
| 478 |
+ extensions = append(extensions, desc) |
|
| 479 |
+ } |
|
| 480 |
+ return extensions, nil |
|
| 481 |
+} |
|
| 482 |
+ |
|
| 455 | 483 |
// SetExtension sets the specified extension of pb to the specified value. |
| 456 |
-func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error {
|
|
| 457 |
- if err := checkExtensionTypes(pb, extension); err != nil {
|
|
| 484 |
+func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
|
|
| 485 |
+ if epb, doki := pb.(extensionsBytes); doki {
|
|
| 486 |
+ ClearExtension(pb, extension) |
|
| 487 |
+ ext := epb.GetExtensions() |
|
| 488 |
+ et := reflect.TypeOf(extension.ExtensionType) |
|
| 489 |
+ props := extensionProperties(extension) |
|
| 490 |
+ p := NewBuffer(nil) |
|
| 491 |
+ x := reflect.New(et) |
|
| 492 |
+ x.Elem().Set(reflect.ValueOf(value)) |
|
| 493 |
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
| 494 |
+ return err |
|
| 495 |
+ } |
|
| 496 |
+ *ext = append(*ext, p.buf...) |
|
| 497 |
+ return nil |
|
| 498 |
+ } |
|
| 499 |
+ epb, ok := extendable(pb) |
|
| 500 |
+ if !ok {
|
|
| 501 |
+ return errors.New("proto: not an extendable proto")
|
|
| 502 |
+ } |
|
| 503 |
+ if err := checkExtensionTypes(epb, extension); err != nil {
|
|
| 458 | 504 |
return err |
| 459 | 505 |
} |
| 460 | 506 |
typ := reflect.TypeOf(extension.ExtensionType) |
| ... | ... |
@@ -469,26 +639,27 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
|
| 469 | 469 |
if reflect.ValueOf(value).IsNil() {
|
| 470 | 470 |
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
|
| 471 | 471 |
} |
| 472 |
- return setExtension(pb, extension, value) |
|
| 472 |
+ |
|
| 473 |
+ extmap := epb.extensionsWrite() |
|
| 474 |
+ extmap[extension.Field] = Extension{desc: extension, value: value}
|
|
| 475 |
+ return nil |
|
| 473 | 476 |
} |
| 474 | 477 |
|
| 475 |
-func setExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error {
|
|
| 476 |
- if epb, doki := pb.(extensionsMap); doki {
|
|
| 477 |
- epb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
|
|
| 478 |
- } else if epb, doki := pb.(extensionsBytes); doki {
|
|
| 479 |
- ClearExtension(pb, extension) |
|
| 478 |
+// ClearAllExtensions clears all extensions from pb. |
|
| 479 |
+func ClearAllExtensions(pb Message) {
|
|
| 480 |
+ if epb, doki := pb.(extensionsBytes); doki {
|
|
| 480 | 481 |
ext := epb.GetExtensions() |
| 481 |
- et := reflect.TypeOf(extension.ExtensionType) |
|
| 482 |
- props := extensionProperties(extension) |
|
| 483 |
- p := NewBuffer(nil) |
|
| 484 |
- x := reflect.New(et) |
|
| 485 |
- x.Elem().Set(reflect.ValueOf(value)) |
|
| 486 |
- if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
| 487 |
- return err |
|
| 488 |
- } |
|
| 489 |
- *ext = append(*ext, p.buf...) |
|
| 482 |
+ *ext = []byte{}
|
|
| 483 |
+ return |
|
| 484 |
+ } |
|
| 485 |
+ epb, ok := extendable(pb) |
|
| 486 |
+ if !ok {
|
|
| 487 |
+ return |
|
| 488 |
+ } |
|
| 489 |
+ m := epb.extensionsWrite() |
|
| 490 |
+ for k := range m {
|
|
| 491 |
+ delete(m, k) |
|
| 490 | 492 |
} |
| 491 |
- return nil |
|
| 492 | 493 |
} |
| 493 | 494 |
|
| 494 | 495 |
// A global registry of extensions. |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -33,9 +35,10 @@ import ( |
| 33 | 33 |
"reflect" |
| 34 | 34 |
"sort" |
| 35 | 35 |
"strings" |
| 36 |
+ "sync" |
|
| 36 | 37 |
) |
| 37 | 38 |
|
| 38 |
-func GetBoolExtension(pb extendableProto, extension *ExtensionDesc, ifnotset bool) bool {
|
|
| 39 |
+func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool {
|
|
| 39 | 40 |
if reflect.ValueOf(pb).IsNil() {
|
| 40 | 41 |
return ifnotset |
| 41 | 42 |
} |
| ... | ... |
@@ -60,8 +63,12 @@ func (this *Extension) Compare(that *Extension) int {
|
| 60 | 60 |
return bytes.Compare(this.enc, that.enc) |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
+func SizeOfInternalExtension(m extendableProto) (n int) {
|
|
| 64 |
+ return SizeOfExtensionMap(m.extensionsWrite()) |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 63 | 67 |
func SizeOfExtensionMap(m map[int32]Extension) (n int) {
|
| 64 |
- return sizeExtensionMap(m) |
|
| 68 |
+ return extensionsMapSize(m) |
|
| 65 | 69 |
} |
| 66 | 70 |
|
| 67 | 71 |
type sortableMapElem struct {
|
| ... | ... |
@@ -94,6 +101,10 @@ func (this sortableExtensions) String() string {
|
| 94 | 94 |
return "map[" + strings.Join(ss, ",") + "]" |
| 95 | 95 |
} |
| 96 | 96 |
|
| 97 |
+func StringFromInternalExtension(m extendableProto) string {
|
|
| 98 |
+ return StringFromExtensionsMap(m.extensionsWrite()) |
|
| 99 |
+} |
|
| 100 |
+ |
|
| 97 | 101 |
func StringFromExtensionsMap(m map[int32]Extension) string {
|
| 98 | 102 |
return newSortableExtensionsFromMap(m).String() |
| 99 | 103 |
} |
| ... | ... |
@@ -106,8 +117,12 @@ func StringFromExtensionsBytes(ext []byte) string {
|
| 106 | 106 |
return StringFromExtensionsMap(m) |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
+func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) {
|
|
| 110 |
+ return EncodeExtensionMap(m.extensionsWrite(), data) |
|
| 111 |
+} |
|
| 112 |
+ |
|
| 109 | 113 |
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
|
| 110 |
- if err := encodeExtensionMap(m); err != nil {
|
|
| 114 |
+ if err := encodeExtensionsMap(m); err != nil {
|
|
| 111 | 115 |
return 0, err |
| 112 | 116 |
} |
| 113 | 117 |
keys := make([]int, 0, len(m)) |
| ... | ... |
@@ -125,7 +140,7 @@ func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
|
| 125 | 125 |
if m[id].value == nil || m[id].desc == nil {
|
| 126 | 126 |
return m[id].enc, nil |
| 127 | 127 |
} |
| 128 |
- if err := encodeExtensionMap(m); err != nil {
|
|
| 128 |
+ if err := encodeExtensionsMap(m); err != nil {
|
|
| 129 | 129 |
return nil, err |
| 130 | 130 |
} |
| 131 | 131 |
return m[id].enc, nil |
| ... | ... |
@@ -189,17 +204,44 @@ func NewExtension(e []byte) Extension {
|
| 189 | 189 |
return ee |
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 |
-func AppendExtension(e extendableProto, tag int32, buf []byte) {
|
|
| 193 |
- if ee, eok := e.(extensionsMap); eok {
|
|
| 194 |
- ext := ee.ExtensionMap()[int32(tag)] // may be missing |
|
| 195 |
- ext.enc = append(ext.enc, buf...) |
|
| 196 |
- ee.ExtensionMap()[int32(tag)] = ext |
|
| 197 |
- } else if ee, eok := e.(extensionsBytes); eok {
|
|
| 192 |
+func AppendExtension(e Message, tag int32, buf []byte) {
|
|
| 193 |
+ if ee, eok := e.(extensionsBytes); eok {
|
|
| 198 | 194 |
ext := ee.GetExtensions() |
| 199 | 195 |
*ext = append(*ext, buf...) |
| 196 |
+ return |
|
| 197 |
+ } |
|
| 198 |
+ if ee, eok := e.(extendableProto); eok {
|
|
| 199 |
+ m := ee.extensionsWrite() |
|
| 200 |
+ ext := m[int32(tag)] // may be missing |
|
| 201 |
+ ext.enc = append(ext.enc, buf...) |
|
| 202 |
+ m[int32(tag)] = ext |
|
| 200 | 203 |
} |
| 201 | 204 |
} |
| 202 | 205 |
|
| 206 |
+func encodeExtension(e *Extension) error {
|
|
| 207 |
+ if e.value == nil || e.desc == nil {
|
|
| 208 |
+ // Extension is only in its encoded form. |
|
| 209 |
+ return nil |
|
| 210 |
+ } |
|
| 211 |
+ // We don't skip extensions that have an encoded form set, |
|
| 212 |
+ // because the extension value may have been mutated after |
|
| 213 |
+ // the last time this function was called. |
|
| 214 |
+ |
|
| 215 |
+ et := reflect.TypeOf(e.desc.ExtensionType) |
|
| 216 |
+ props := extensionProperties(e.desc) |
|
| 217 |
+ |
|
| 218 |
+ p := NewBuffer(nil) |
|
| 219 |
+ // If e.value has type T, the encoder expects a *struct{ X T }.
|
|
| 220 |
+ // Pass a *T with a zero field and hope it all works out. |
|
| 221 |
+ x := reflect.New(et) |
|
| 222 |
+ x.Elem().Set(reflect.ValueOf(e.value)) |
|
| 223 |
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
| 224 |
+ return err |
|
| 225 |
+ } |
|
| 226 |
+ e.enc = p.buf |
|
| 227 |
+ return nil |
|
| 228 |
+} |
|
| 229 |
+ |
|
| 203 | 230 |
func (this Extension) GoString() string {
|
| 204 | 231 |
if this.enc == nil {
|
| 205 | 232 |
if err := encodeExtension(&this); err != nil {
|
| ... | ... |
@@ -209,7 +251,7 @@ func (this Extension) GoString() string {
|
| 209 | 209 |
return fmt.Sprintf("proto.NewExtension(%#v)", this.enc)
|
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 |
-func SetUnsafeExtension(pb extendableProto, fieldNum int32, value interface{}) error {
|
|
| 212 |
+func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error {
|
|
| 213 | 213 |
typ := reflect.TypeOf(pb).Elem() |
| 214 | 214 |
ext, ok := extensionMaps[typ] |
| 215 | 215 |
if !ok {
|
| ... | ... |
@@ -219,10 +261,10 @@ func SetUnsafeExtension(pb extendableProto, fieldNum int32, value interface{}) e
|
| 219 | 219 |
if !ok {
|
| 220 | 220 |
return errors.New("proto: bad extension number; not in declared ranges")
|
| 221 | 221 |
} |
| 222 |
- return setExtension(pb, desc, value) |
|
| 222 |
+ return SetExtension(pb, desc, value) |
|
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 |
-func GetUnsafeExtension(pb extendableProto, fieldNum int32) (interface{}, error) {
|
|
| 225 |
+func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) {
|
|
| 226 | 226 |
typ := reflect.TypeOf(pb).Elem() |
| 227 | 227 |
ext, ok := extensionMaps[typ] |
| 228 | 228 |
if !ok {
|
| ... | ... |
@@ -234,3 +276,19 @@ func GetUnsafeExtension(pb extendableProto, fieldNum int32) (interface{}, error)
|
| 234 | 234 |
} |
| 235 | 235 |
return GetExtension(pb, desc) |
| 236 | 236 |
} |
| 237 |
+ |
|
| 238 |
+func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions {
|
|
| 239 |
+ x := &XXX_InternalExtensions{
|
|
| 240 |
+ p: new(struct {
|
|
| 241 |
+ mu sync.Mutex |
|
| 242 |
+ extensionMap map[int32]Extension |
|
| 243 |
+ }), |
|
| 244 |
+ } |
|
| 245 |
+ x.p.extensionMap = m |
|
| 246 |
+ return *x |
|
| 247 |
+} |
|
| 248 |
+ |
|
| 249 |
+func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension {
|
|
| 250 |
+ pb := extendable.(extendableProto) |
|
| 251 |
+ return pb.extensionsWrite() |
|
| 252 |
+} |
| ... | ... |
@@ -889,6 +889,10 @@ func isProto3Zero(v reflect.Value) bool {
|
| 889 | 889 |
return false |
| 890 | 890 |
} |
| 891 | 891 |
|
| 892 |
+// ProtoPackageIsVersion2 is referenced from generated protocol buffer files |
|
| 893 |
+// to assert that that code is compatible with this version of the proto package. |
|
| 894 |
+const GoGoProtoPackageIsVersion2 = true |
|
| 895 |
+ |
|
| 892 | 896 |
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files |
| 893 | 897 |
// to assert that that code is compatible with this version of the proto package. |
| 894 | 898 |
const GoGoProtoPackageIsVersion1 = true |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -149,9 +149,21 @@ func skipVarint(buf []byte) []byte {
|
| 149 | 149 |
|
| 150 | 150 |
// MarshalMessageSet encodes the extension map represented by m in the message set wire format. |
| 151 | 151 |
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. |
| 152 |
-func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
|
|
| 153 |
- if err := encodeExtensionMap(m); err != nil {
|
|
| 154 |
- return nil, err |
|
| 152 |
+func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
|
| 153 |
+ var m map[int32]Extension |
|
| 154 |
+ switch exts := exts.(type) {
|
|
| 155 |
+ case *XXX_InternalExtensions: |
|
| 156 |
+ if err := encodeExtensions(exts); err != nil {
|
|
| 157 |
+ return nil, err |
|
| 158 |
+ } |
|
| 159 |
+ m, _ = exts.extensionsRead() |
|
| 160 |
+ case map[int32]Extension: |
|
| 161 |
+ if err := encodeExtensionsMap(exts); err != nil {
|
|
| 162 |
+ return nil, err |
|
| 163 |
+ } |
|
| 164 |
+ m = exts |
|
| 165 |
+ default: |
|
| 166 |
+ return nil, errors.New("proto: not an extension map")
|
|
| 155 | 167 |
} |
| 156 | 168 |
|
| 157 | 169 |
// Sort extension IDs to provide a deterministic encoding. |
| ... | ... |
@@ -178,7 +190,17 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
|
| 178 | 178 |
|
| 179 | 179 |
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. |
| 180 | 180 |
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. |
| 181 |
-func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
|
|
| 181 |
+func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
|
| 182 |
+ var m map[int32]Extension |
|
| 183 |
+ switch exts := exts.(type) {
|
|
| 184 |
+ case *XXX_InternalExtensions: |
|
| 185 |
+ m = exts.extensionsWrite() |
|
| 186 |
+ case map[int32]Extension: |
|
| 187 |
+ m = exts |
|
| 188 |
+ default: |
|
| 189 |
+ return errors.New("proto: not an extension map")
|
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 182 | 192 |
ms := new(messageSet) |
| 183 | 193 |
if err := Unmarshal(buf, ms); err != nil {
|
| 184 | 194 |
return err |
| ... | ... |
@@ -209,7 +231,16 @@ func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
|
| 209 | 209 |
|
| 210 | 210 |
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. |
| 211 | 211 |
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. |
| 212 |
-func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) {
|
|
| 212 |
+func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
|
| 213 |
+ var m map[int32]Extension |
|
| 214 |
+ switch exts := exts.(type) {
|
|
| 215 |
+ case *XXX_InternalExtensions: |
|
| 216 |
+ m, _ = exts.extensionsRead() |
|
| 217 |
+ case map[int32]Extension: |
|
| 218 |
+ m = exts |
|
| 219 |
+ default: |
|
| 220 |
+ return nil, errors.New("proto: not an extension map")
|
|
| 221 |
+ } |
|
| 213 | 222 |
var b bytes.Buffer |
| 214 | 223 |
b.WriteByte('{')
|
| 215 | 224 |
|
| ... | ... |
@@ -252,7 +283,7 @@ func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) {
|
| 252 | 252 |
|
| 253 | 253 |
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. |
| 254 | 254 |
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. |
| 255 |
-func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error {
|
|
| 255 |
+func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
|
|
| 256 | 256 |
// Common-case fast path. |
| 257 | 257 |
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
|
| 258 | 258 |
return nil |
| ... | ... |
@@ -29,7 +29,7 @@ |
| 29 | 29 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | 30 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | 31 |
|
| 32 |
-// +build appengine |
|
| 32 |
+// +build appengine js |
|
| 33 | 33 |
|
| 34 | 34 |
// This file contains an implementation of proto field accesses using package reflect. |
| 35 | 35 |
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can |
| ... | ... |
@@ -139,6 +139,11 @@ func structPointer_StringSlice(p structPointer, f field) *[]string {
|
| 139 | 139 |
return structPointer_ifield(p, f).(*[]string) |
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 |
+// Extensions returns the address of an extension map field in the struct. |
|
| 143 |
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
| 144 |
+ return structPointer_ifield(p, f).(*XXX_InternalExtensions) |
|
| 145 |
+} |
|
| 146 |
+ |
|
| 142 | 147 |
// ExtMap returns the address of an extension map field in the struct. |
| 143 | 148 |
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
| 144 | 149 |
return structPointer_ifield(p, f).(*map[int32]Extension) |
| ... | ... |
@@ -29,7 +29,7 @@ |
| 29 | 29 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | 30 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | 31 |
|
| 32 |
-// +build !appengine |
|
| 32 |
+// +build !appengine,!js |
|
| 33 | 33 |
|
| 34 | 34 |
// This file contains the implementation of the proto field accesses using package unsafe. |
| 35 | 35 |
|
| ... | ... |
@@ -126,6 +126,10 @@ func structPointer_StringSlice(p structPointer, f field) *[]string {
|
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
// ExtMap returns the address of an extension map field in the struct. |
| 129 |
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
| 130 |
+ return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 129 | 133 |
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
| 130 | 134 |
return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 131 | 135 |
} |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -70,16 +72,13 @@ func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
|
| 70 | 70 |
|
| 71 | 71 |
func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer {
|
| 72 | 72 |
size := typ.Elem().Size() |
| 73 |
+ |
|
| 73 | 74 |
oldHeader := structPointer_GetSliceHeader(base, f) |
| 75 |
+ oldSlice := reflect.NewAt(typ, unsafe.Pointer(oldHeader)).Elem() |
|
| 74 | 76 |
newLen := oldHeader.Len + 1 |
| 75 |
- slice := reflect.MakeSlice(typ, newLen, newLen) |
|
| 76 |
- bas := toStructPointer(slice) |
|
| 77 |
- for i := 0; i < oldHeader.Len; i++ {
|
|
| 78 |
- newElemptr := uintptr(bas) + uintptr(i)*size |
|
| 79 |
- oldElemptr := oldHeader.Data + uintptr(i)*size |
|
| 80 |
- copyUintPtr(oldElemptr, newElemptr, int(size)) |
|
| 81 |
- } |
|
| 82 |
- |
|
| 77 |
+ newSlice := reflect.MakeSlice(typ, newLen, newLen) |
|
| 78 |
+ reflect.Copy(newSlice, oldSlice) |
|
| 79 |
+ bas := toStructPointer(newSlice) |
|
| 83 | 80 |
oldHeader.Data = uintptr(bas) |
| 84 | 81 |
oldHeader.Len = newLen |
| 85 | 82 |
oldHeader.Cap = newLen |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-// Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
// |
| 3 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 5 | 5 |
// |
| 6 | 6 |
// Go support for Protocol Buffers - Google's data interchange format |
| 7 | 7 |
// |
| ... | ... |
@@ -542,17 +542,13 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock |
| 542 | 542 |
p.dec = (*Buffer).dec_slice_int64 |
| 543 | 543 |
p.packedDec = (*Buffer).dec_slice_packed_int64 |
| 544 | 544 |
case reflect.Uint8: |
| 545 |
- p.enc = (*Buffer).enc_slice_byte |
|
| 546 | 545 |
p.dec = (*Buffer).dec_slice_byte |
| 547 |
- p.size = size_slice_byte |
|
| 548 |
- // This is a []byte, which is either a bytes field, |
|
| 549 |
- // or the value of a map field. In the latter case, |
|
| 550 |
- // we always encode an empty []byte, so we should not |
|
| 551 |
- // use the proto3 enc/size funcs. |
|
| 552 |
- // f == nil iff this is the key/value of a map field. |
|
| 553 |
- if p.proto3 && f != nil {
|
|
| 546 |
+ if p.proto3 {
|
|
| 554 | 547 |
p.enc = (*Buffer).enc_proto3_slice_byte |
| 555 | 548 |
p.size = size_proto3_slice_byte |
| 549 |
+ } else {
|
|
| 550 |
+ p.enc = (*Buffer).enc_slice_byte |
|
| 551 |
+ p.size = size_slice_byte |
|
| 556 | 552 |
} |
| 557 | 553 |
case reflect.Float32, reflect.Float64: |
| 558 | 554 |
switch t2.Bits() {
|
| ... | ... |
@@ -744,7 +740,9 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 744 | 744 |
propertiesMap[t] = prop |
| 745 | 745 |
|
| 746 | 746 |
// build properties |
| 747 |
- prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) |
|
| 747 |
+ prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || |
|
| 748 |
+ reflect.PtrTo(t).Implements(extendableProtoV1Type) || |
|
| 749 |
+ reflect.PtrTo(t).Implements(extendableBytesType) |
|
| 748 | 750 |
prop.unrecField = invalidField |
| 749 | 751 |
prop.Prop = make([]*Properties, t.NumField()) |
| 750 | 752 |
prop.order = make([]int, t.NumField()) |
| ... | ... |
@@ -756,7 +754,11 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 756 | 756 |
name := f.Name |
| 757 | 757 |
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
| 758 | 758 |
|
| 759 |
- if f.Name == "XXX_extensions" { // special case
|
|
| 759 |
+ if f.Name == "XXX_InternalExtensions" { // special case
|
|
| 760 |
+ p.enc = (*Buffer).enc_exts |
|
| 761 |
+ p.dec = nil // not needed |
|
| 762 |
+ p.size = size_exts |
|
| 763 |
+ } else if f.Name == "XXX_extensions" { // special case
|
|
| 760 | 764 |
if len(f.Tag.Get("protobuf")) > 0 {
|
| 761 | 765 |
p.enc = (*Buffer).enc_ext_slice_byte |
| 762 | 766 |
p.dec = nil // not needed |
| ... | ... |
@@ -766,13 +768,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 766 | 766 |
p.dec = nil // not needed |
| 767 | 767 |
p.size = size_map |
| 768 | 768 |
} |
| 769 |
- } |
|
| 770 |
- if f.Name == "XXX_unrecognized" { // special case
|
|
| 769 |
+ } else if f.Name == "XXX_unrecognized" { // special case
|
|
| 771 | 770 |
prop.unrecField = toField(&f) |
| 772 | 771 |
} |
| 773 |
- oneof := f.Tag.Get("protobuf_oneof") != "" // special case
|
|
| 774 |
- if oneof {
|
|
| 772 |
+ oneof := f.Tag.Get("protobuf_oneof") // special case
|
|
| 773 |
+ if oneof != "" {
|
|
| 775 | 774 |
isOneofMessage = true |
| 775 |
+ // Oneof fields don't use the traditional protobuf tag. |
|
| 776 |
+ p.OrigName = oneof |
|
| 776 | 777 |
} |
| 777 | 778 |
prop.Prop[i] = p |
| 778 | 779 |
prop.order[i] = i |
| ... | ... |
@@ -783,7 +786,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 783 | 783 |
} |
| 784 | 784 |
print("\n")
|
| 785 | 785 |
} |
| 786 |
- if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
|
|
| 786 |
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
|
|
| 787 | 787 |
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") |
| 788 | 788 |
} |
| 789 | 789 |
} |
| ... | ... |
@@ -921,3 +924,17 @@ func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
|
| 921 | 921 |
|
| 922 | 922 |
// MessageType returns the message type (pointer to struct) for a named message. |
| 923 | 923 |
func MessageType(name string) reflect.Type { return protoTypes[name] }
|
| 924 |
+ |
|
| 925 |
+// A registry of all linked proto files. |
|
| 926 |
+var ( |
|
| 927 |
+ protoFiles = make(map[string][]byte) // file name => fileDescriptor |
|
| 928 |
+) |
|
| 929 |
+ |
|
| 930 |
+// RegisterFile is called from generated code and maps from the |
|
| 931 |
+// full file name of a .proto file to its compressed FileDescriptorProto. |
|
| 932 |
+func RegisterFile(filename string, fileDescriptor []byte) {
|
|
| 933 |
+ protoFiles[filename] = fileDescriptor |
|
| 934 |
+} |
|
| 935 |
+ |
|
| 936 |
+// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. |
|
| 937 |
+func FileDescriptor(filename string) []byte { return protoFiles[filename] }
|
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-// Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
// |
| 3 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 5 | 5 |
// |
| 6 | 6 |
// Go support for Protocol Buffers - Google's data interchange format |
| 7 | 7 |
// |
| ... | ... |
@@ -50,6 +50,7 @@ import ( |
| 50 | 50 |
"reflect" |
| 51 | 51 |
"sort" |
| 52 | 52 |
"strings" |
| 53 |
+ "sync" |
|
| 53 | 54 |
) |
| 54 | 55 |
|
| 55 | 56 |
var ( |
| ... | ... |
@@ -159,7 +160,7 @@ func (w *textWriter) indent() { w.ind++ }
|
| 159 | 159 |
|
| 160 | 160 |
func (w *textWriter) unindent() {
|
| 161 | 161 |
if w.ind == 0 {
|
| 162 |
- log.Printf("proto: textWriter unindented too far")
|
|
| 162 |
+ log.Print("proto: textWriter unindented too far")
|
|
| 163 | 163 |
return |
| 164 | 164 |
} |
| 165 | 165 |
w.ind-- |
| ... | ... |
@@ -335,7 +336,8 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 335 | 335 |
} |
| 336 | 336 |
inner := fv.Elem().Elem() // interface -> *T -> T |
| 337 | 337 |
tag := inner.Type().Field(0).Tag.Get("protobuf")
|
| 338 |
- props.Parse(tag) // Overwrite the outer props. |
|
| 338 |
+ props = new(Properties) // Overwrite the outer props var, but not its pointee. |
|
| 339 |
+ props.Parse(tag) |
|
| 339 | 340 |
// Write the value in the oneof, not the oneof itself. |
| 340 | 341 |
fv = inner.Field(0) |
| 341 | 342 |
|
| ... | ... |
@@ -386,7 +388,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 386 | 386 |
pv = reflect.New(sv.Type()) |
| 387 | 387 |
pv.Elem().Set(sv) |
| 388 | 388 |
} |
| 389 |
- if pv.Type().Implements(extendableProtoType) {
|
|
| 389 |
+ if pv.Type().Implements(extensionRangeType) {
|
|
| 390 | 390 |
if err := writeExtensions(w, pv); err != nil {
|
| 391 | 391 |
return err |
| 392 | 392 |
} |
| ... | ... |
@@ -634,28 +636,37 @@ func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
| 634 | 634 |
// pv is assumed to be a pointer to a protocol message struct that is extendable. |
| 635 | 635 |
func writeExtensions(w *textWriter, pv reflect.Value) error {
|
| 636 | 636 |
emap := extensionMaps[pv.Type().Elem()] |
| 637 |
- ep := pv.Interface().(extendableProto) |
|
| 637 |
+ e := pv.Interface().(Message) |
|
| 638 | 638 |
|
| 639 |
- // Order the extensions by ID. |
|
| 640 |
- // This isn't strictly necessary, but it will give us |
|
| 641 |
- // canonical output, which will also make testing easier. |
|
| 642 | 639 |
var m map[int32]Extension |
| 643 |
- if em, ok := ep.(extensionsMap); ok {
|
|
| 644 |
- m = em.ExtensionMap() |
|
| 645 |
- } else if em, ok := ep.(extensionsBytes); ok {
|
|
| 640 |
+ var mu sync.Locker |
|
| 641 |
+ if em, ok := e.(extensionsBytes); ok {
|
|
| 646 | 642 |
eb := em.GetExtensions() |
| 647 | 643 |
var err error |
| 648 | 644 |
m, err = BytesToExtensionsMap(*eb) |
| 649 | 645 |
if err != nil {
|
| 650 | 646 |
return err |
| 651 | 647 |
} |
| 648 |
+ mu = notLocker{}
|
|
| 649 |
+ } else if _, ok := e.(extendableProto); ok {
|
|
| 650 |
+ ep, _ := extendable(e) |
|
| 651 |
+ m, mu = ep.extensionsRead() |
|
| 652 |
+ if m == nil {
|
|
| 653 |
+ return nil |
|
| 654 |
+ } |
|
| 652 | 655 |
} |
| 653 | 656 |
|
| 657 |
+ // Order the extensions by ID. |
|
| 658 |
+ // This isn't strictly necessary, but it will give us |
|
| 659 |
+ // canonical output, which will also make testing easier. |
|
| 660 |
+ |
|
| 661 |
+ mu.Lock() |
|
| 654 | 662 |
ids := make([]int32, 0, len(m)) |
| 655 | 663 |
for id := range m {
|
| 656 | 664 |
ids = append(ids, id) |
| 657 | 665 |
} |
| 658 | 666 |
sort.Sort(int32Slice(ids)) |
| 667 |
+ mu.Unlock() |
|
| 659 | 668 |
|
| 660 | 669 |
for _, extNum := range ids {
|
| 661 | 670 |
ext := m[extNum] |
| ... | ... |
@@ -671,7 +682,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
|
| 671 | 671 |
continue |
| 672 | 672 |
} |
| 673 | 673 |
|
| 674 |
- pb, err := GetExtension(ep, desc) |
|
| 674 |
+ pb, err := GetExtension(e, desc) |
|
| 675 | 675 |
if err != nil {
|
| 676 | 676 |
return fmt.Errorf("failed getting extension: %v", err)
|
| 677 | 677 |
} |
| ... | ... |
@@ -727,7 +738,14 @@ func (w *textWriter) writeIndent() {
|
| 727 | 727 |
w.complete = false |
| 728 | 728 |
} |
| 729 | 729 |
|
| 730 |
-func marshalText(w io.Writer, pb Message, compact bool) error {
|
|
| 730 |
+// TextMarshaler is a configurable text format marshaler. |
|
| 731 |
+type TextMarshaler struct {
|
|
| 732 |
+ Compact bool // use compact text format (one line). |
|
| 733 |
+} |
|
| 734 |
+ |
|
| 735 |
+// Marshal writes a given protocol buffer in text format. |
|
| 736 |
+// The only errors returned are from w. |
|
| 737 |
+func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
|
| 731 | 738 |
val := reflect.ValueOf(pb) |
| 732 | 739 |
if pb == nil || val.IsNil() {
|
| 733 | 740 |
w.Write([]byte("<nil>"))
|
| ... | ... |
@@ -742,7 +760,7 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
|
| 742 | 742 |
aw := &textWriter{
|
| 743 | 743 |
w: ww, |
| 744 | 744 |
complete: true, |
| 745 |
- compact: compact, |
|
| 745 |
+ compact: m.Compact, |
|
| 746 | 746 |
} |
| 747 | 747 |
|
| 748 | 748 |
if tm, ok := pb.(encoding.TextMarshaler); ok {
|
| ... | ... |
@@ -769,25 +787,29 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
|
| 769 | 769 |
return nil |
| 770 | 770 |
} |
| 771 | 771 |
|
| 772 |
+// Text is the same as Marshal, but returns the string directly. |
|
| 773 |
+func (m *TextMarshaler) Text(pb Message) string {
|
|
| 774 |
+ var buf bytes.Buffer |
|
| 775 |
+ m.Marshal(&buf, pb) |
|
| 776 |
+ return buf.String() |
|
| 777 |
+} |
|
| 778 |
+ |
|
| 779 |
+var ( |
|
| 780 |
+ defaultTextMarshaler = TextMarshaler{}
|
|
| 781 |
+ compactTextMarshaler = TextMarshaler{Compact: true}
|
|
| 782 |
+) |
|
| 783 |
+ |
|
| 784 |
+// TODO: consider removing some of the Marshal functions below. |
|
| 785 |
+ |
|
| 772 | 786 |
// MarshalText writes a given protocol buffer in text format. |
| 773 | 787 |
// The only errors returned are from w. |
| 774 |
-func MarshalText(w io.Writer, pb Message) error {
|
|
| 775 |
- return marshalText(w, pb, false) |
|
| 776 |
-} |
|
| 788 |
+func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
|
|
| 777 | 789 |
|
| 778 | 790 |
// MarshalTextString is the same as MarshalText, but returns the string directly. |
| 779 |
-func MarshalTextString(pb Message) string {
|
|
| 780 |
- var buf bytes.Buffer |
|
| 781 |
- marshalText(&buf, pb, false) |
|
| 782 |
- return buf.String() |
|
| 783 |
-} |
|
| 791 |
+func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
|
|
| 784 | 792 |
|
| 785 | 793 |
// CompactText writes a given protocol buffer in compact text format (one line). |
| 786 |
-func CompactText(w io.Writer, pb Message) error { return marshalText(w, pb, true) }
|
|
| 794 |
+func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
|
|
| 787 | 795 |
|
| 788 | 796 |
// CompactTextString is the same as CompactText, but returns the string directly. |
| 789 |
-func CompactTextString(pb Message) string {
|
|
| 790 |
- var buf bytes.Buffer |
|
| 791 |
- marshalText(&buf, pb, true) |
|
| 792 |
- return buf.String() |
|
| 793 |
-} |
|
| 797 |
+func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
|
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 2 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| 5 | 7 |
// modification, are permitted provided that the following conditions are |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 |
-// Extensions for Protocol Buffers to create more go like structures. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 | 2 |
// |
| 3 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 4 |
-// http://github.com/gogo/protobuf/gogoproto |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 4 |
+// http://github.com/gogo/protobuf |
|
| 5 | 5 |
// |
| 6 | 6 |
// Go support for Protocol Buffers - Google's data interchange format |
| 7 | 7 |
// |
| ... | ... |
@@ -519,7 +519,7 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 519 | 519 |
} |
| 520 | 520 |
reqFieldErr = err |
| 521 | 521 |
} |
| 522 |
- ep := sv.Addr().Interface().(extendableProto) |
|
| 522 |
+ ep := sv.Addr().Interface().(Message) |
|
| 523 | 523 |
if !rep {
|
| 524 | 524 |
SetExtension(ep, desc, ext.Interface()) |
| 525 | 525 |
} else {
|
| ... | ... |
@@ -571,8 +571,9 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 571 | 571 |
|
| 572 | 572 |
// The map entry should be this sequence of tokens: |
| 573 | 573 |
// < key : KEY value : VALUE > |
| 574 |
- // Technically the "key" and "value" could come in any order, |
|
| 575 |
- // but in practice they won't. |
|
| 574 |
+ // However, implementations may omit key or value, and technically |
|
| 575 |
+ // we should support them in any order. See b/28924776 for a time |
|
| 576 |
+ // this went wrong. |
|
| 576 | 577 |
|
| 577 | 578 |
tok := p.next() |
| 578 | 579 |
var terminator string |
| ... | ... |
@@ -584,32 +585,39 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 584 | 584 |
default: |
| 585 | 585 |
return p.errorf("expected '{' or '<', found %q", tok.value)
|
| 586 | 586 |
} |
| 587 |
- if err := p.consumeToken("key"); err != nil {
|
|
| 588 |
- return err |
|
| 589 |
- } |
|
| 590 |
- if err := p.consumeToken(":"); err != nil {
|
|
| 591 |
- return err |
|
| 592 |
- } |
|
| 593 |
- if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
| 594 |
- return err |
|
| 595 |
- } |
|
| 596 |
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 597 |
- return err |
|
| 598 |
- } |
|
| 599 |
- if err := p.consumeToken("value"); err != nil {
|
|
| 600 |
- return err |
|
| 601 |
- } |
|
| 602 |
- if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
| 603 |
- return err |
|
| 604 |
- } |
|
| 605 |
- if err := p.readAny(val, props.mvalprop); err != nil {
|
|
| 606 |
- return err |
|
| 607 |
- } |
|
| 608 |
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 609 |
- return err |
|
| 610 |
- } |
|
| 611 |
- if err := p.consumeToken(terminator); err != nil {
|
|
| 612 |
- return err |
|
| 587 |
+ for {
|
|
| 588 |
+ tok := p.next() |
|
| 589 |
+ if tok.err != nil {
|
|
| 590 |
+ return tok.err |
|
| 591 |
+ } |
|
| 592 |
+ if tok.value == terminator {
|
|
| 593 |
+ break |
|
| 594 |
+ } |
|
| 595 |
+ switch tok.value {
|
|
| 596 |
+ case "key": |
|
| 597 |
+ if err := p.consumeToken(":"); err != nil {
|
|
| 598 |
+ return err |
|
| 599 |
+ } |
|
| 600 |
+ if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
| 601 |
+ return err |
|
| 602 |
+ } |
|
| 603 |
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 604 |
+ return err |
|
| 605 |
+ } |
|
| 606 |
+ case "value": |
|
| 607 |
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
| 608 |
+ return err |
|
| 609 |
+ } |
|
| 610 |
+ if err := p.readAny(val, props.mvalprop); err != nil {
|
|
| 611 |
+ return err |
|
| 612 |
+ } |
|
| 613 |
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 614 |
+ return err |
|
| 615 |
+ } |
|
| 616 |
+ default: |
|
| 617 |
+ p.back() |
|
| 618 |
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) |
|
| 619 |
+ } |
|
| 613 | 620 |
} |
| 614 | 621 |
|
| 615 | 622 |
dst.SetMapIndex(key, val) |
| ... | ... |
@@ -632,7 +640,8 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 632 | 632 |
return err |
| 633 | 633 |
} |
| 634 | 634 |
reqFieldErr = err |
| 635 |
- } else if props.Required {
|
|
| 635 |
+ } |
|
| 636 |
+ if props.Required {
|
|
| 636 | 637 |
reqCount-- |
| 637 | 638 |
} |
| 638 | 639 |
|
| ... | ... |
@@ -30,4 +30,7 @@ |
| 30 | 30 |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | 31 |
|
| 32 | 32 |
regenerate: |
| 33 |
+ go install github.com/gogo/protobuf/protoc-gen-gogo |
|
| 33 | 34 |
protoc --gogo_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto |
| 35 |
+ go install github.com/gogo/protobuf/protoc-gen-gostring |
|
| 36 |
+ protoc --gostring_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto |
| ... | ... |
@@ -41,7 +41,9 @@ var _ = math.Inf |
| 41 | 41 |
|
| 42 | 42 |
// This is a compile-time assertion to ensure that this generated file |
| 43 | 43 |
// is compatible with the proto package it is being compiled against. |
| 44 |
-const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 44 |
+// A compilation error at this line likely means your copy of the |
|
| 45 |
+// proto package needs to be updated. |
|
| 46 |
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package |
|
| 45 | 47 |
|
| 46 | 48 |
type FieldDescriptorProto_Type int32 |
| 47 | 49 |
|
| ... | ... |
@@ -955,9 +957,9 @@ type FileOptions struct {
|
| 955 | 955 |
// suffixed package. |
| 956 | 956 |
JavananoUseDeprecatedPackage *bool `protobuf:"varint,38,opt,name=javanano_use_deprecated_package,json=javananoUseDeprecatedPackage" json:"javanano_use_deprecated_package,omitempty"` |
| 957 | 957 |
// The parser stores options it doesn't recognize here. See above. |
| 958 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 959 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 960 |
- XXX_unrecognized []byte `json:"-"` |
|
| 958 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 959 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 960 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 961 | 961 |
} |
| 962 | 962 |
|
| 963 | 963 |
func (m *FileOptions) Reset() { *m = FileOptions{} }
|
| ... | ... |
@@ -966,18 +968,12 @@ func (*FileOptions) ProtoMessage() {}
|
| 966 | 966 |
func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{9} }
|
| 967 | 967 |
|
| 968 | 968 |
var extRange_FileOptions = []proto.ExtensionRange{
|
| 969 |
- {1000, 536870911},
|
|
| 969 |
+ {Start: 1000, End: 536870911},
|
|
| 970 | 970 |
} |
| 971 | 971 |
|
| 972 | 972 |
func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 973 | 973 |
return extRange_FileOptions |
| 974 | 974 |
} |
| 975 |
-func (m *FileOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 976 |
- if m.XXX_extensions == nil {
|
|
| 977 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 978 |
- } |
|
| 979 |
- return m.XXX_extensions |
|
| 980 |
-} |
|
| 981 | 975 |
|
| 982 | 976 |
const Default_FileOptions_JavaMultipleFiles bool = false |
| 983 | 977 |
const Default_FileOptions_JavaGenerateEqualsAndHash bool = false |
| ... | ... |
@@ -1153,9 +1149,9 @@ type MessageOptions struct {
|
| 1153 | 1153 |
// parser. |
| 1154 | 1154 |
MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` |
| 1155 | 1155 |
// The parser stores options it doesn't recognize here. See above. |
| 1156 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1157 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1158 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1156 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1157 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1158 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1159 | 1159 |
} |
| 1160 | 1160 |
|
| 1161 | 1161 |
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
|
| ... | ... |
@@ -1164,18 +1160,12 @@ func (*MessageOptions) ProtoMessage() {}
|
| 1164 | 1164 |
func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{10} }
|
| 1165 | 1165 |
|
| 1166 | 1166 |
var extRange_MessageOptions = []proto.ExtensionRange{
|
| 1167 |
- {1000, 536870911},
|
|
| 1167 |
+ {Start: 1000, End: 536870911},
|
|
| 1168 | 1168 |
} |
| 1169 | 1169 |
|
| 1170 | 1170 |
func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1171 | 1171 |
return extRange_MessageOptions |
| 1172 | 1172 |
} |
| 1173 |
-func (m *MessageOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1174 |
- if m.XXX_extensions == nil {
|
|
| 1175 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1176 |
- } |
|
| 1177 |
- return m.XXX_extensions |
|
| 1178 |
-} |
|
| 1179 | 1173 |
|
| 1180 | 1174 |
const Default_MessageOptions_MessageSetWireFormat bool = false |
| 1181 | 1175 |
const Default_MessageOptions_NoStandardDescriptorAccessor bool = false |
| ... | ... |
@@ -1275,9 +1265,9 @@ type FieldOptions struct {
|
| 1275 | 1275 |
// For Google-internal migration only. Do not use. |
| 1276 | 1276 |
Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` |
| 1277 | 1277 |
// The parser stores options it doesn't recognize here. See above. |
| 1278 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1279 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1280 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1278 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1279 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1280 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1281 | 1281 |
} |
| 1282 | 1282 |
|
| 1283 | 1283 |
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
|
| ... | ... |
@@ -1286,18 +1276,12 @@ func (*FieldOptions) ProtoMessage() {}
|
| 1286 | 1286 |
func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{11} }
|
| 1287 | 1287 |
|
| 1288 | 1288 |
var extRange_FieldOptions = []proto.ExtensionRange{
|
| 1289 |
- {1000, 536870911},
|
|
| 1289 |
+ {Start: 1000, End: 536870911},
|
|
| 1290 | 1290 |
} |
| 1291 | 1291 |
|
| 1292 | 1292 |
func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1293 | 1293 |
return extRange_FieldOptions |
| 1294 | 1294 |
} |
| 1295 |
-func (m *FieldOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1296 |
- if m.XXX_extensions == nil {
|
|
| 1297 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1298 |
- } |
|
| 1299 |
- return m.XXX_extensions |
|
| 1300 |
-} |
|
| 1301 | 1295 |
|
| 1302 | 1296 |
const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING |
| 1303 | 1297 |
const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL |
| ... | ... |
@@ -1364,9 +1348,9 @@ type EnumOptions struct {
|
| 1364 | 1364 |
// is a formalization for deprecating enums. |
| 1365 | 1365 |
Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` |
| 1366 | 1366 |
// The parser stores options it doesn't recognize here. See above. |
| 1367 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1368 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1369 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1367 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1368 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1369 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1370 | 1370 |
} |
| 1371 | 1371 |
|
| 1372 | 1372 |
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
|
| ... | ... |
@@ -1375,18 +1359,12 @@ func (*EnumOptions) ProtoMessage() {}
|
| 1375 | 1375 |
func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{12} }
|
| 1376 | 1376 |
|
| 1377 | 1377 |
var extRange_EnumOptions = []proto.ExtensionRange{
|
| 1378 |
- {1000, 536870911},
|
|
| 1378 |
+ {Start: 1000, End: 536870911},
|
|
| 1379 | 1379 |
} |
| 1380 | 1380 |
|
| 1381 | 1381 |
func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1382 | 1382 |
return extRange_EnumOptions |
| 1383 | 1383 |
} |
| 1384 |
-func (m *EnumOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1385 |
- if m.XXX_extensions == nil {
|
|
| 1386 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1387 |
- } |
|
| 1388 |
- return m.XXX_extensions |
|
| 1389 |
-} |
|
| 1390 | 1384 |
|
| 1391 | 1385 |
const Default_EnumOptions_Deprecated bool = false |
| 1392 | 1386 |
|
| ... | ... |
@@ -1418,9 +1396,9 @@ type EnumValueOptions struct {
|
| 1418 | 1418 |
// this is a formalization for deprecating enum values. |
| 1419 | 1419 |
Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` |
| 1420 | 1420 |
// The parser stores options it doesn't recognize here. See above. |
| 1421 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1422 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1423 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1421 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1422 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1423 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1424 | 1424 |
} |
| 1425 | 1425 |
|
| 1426 | 1426 |
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
|
| ... | ... |
@@ -1429,18 +1407,12 @@ func (*EnumValueOptions) ProtoMessage() {}
|
| 1429 | 1429 |
func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{13} }
|
| 1430 | 1430 |
|
| 1431 | 1431 |
var extRange_EnumValueOptions = []proto.ExtensionRange{
|
| 1432 |
- {1000, 536870911},
|
|
| 1432 |
+ {Start: 1000, End: 536870911},
|
|
| 1433 | 1433 |
} |
| 1434 | 1434 |
|
| 1435 | 1435 |
func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1436 | 1436 |
return extRange_EnumValueOptions |
| 1437 | 1437 |
} |
| 1438 |
-func (m *EnumValueOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1439 |
- if m.XXX_extensions == nil {
|
|
| 1440 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1441 |
- } |
|
| 1442 |
- return m.XXX_extensions |
|
| 1443 |
-} |
|
| 1444 | 1438 |
|
| 1445 | 1439 |
const Default_EnumValueOptions_Deprecated bool = false |
| 1446 | 1440 |
|
| ... | ... |
@@ -1465,9 +1437,9 @@ type ServiceOptions struct {
|
| 1465 | 1465 |
// this is a formalization for deprecating services. |
| 1466 | 1466 |
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` |
| 1467 | 1467 |
// The parser stores options it doesn't recognize here. See above. |
| 1468 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1469 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1470 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1468 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1469 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1470 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1471 | 1471 |
} |
| 1472 | 1472 |
|
| 1473 | 1473 |
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
|
| ... | ... |
@@ -1476,18 +1448,12 @@ func (*ServiceOptions) ProtoMessage() {}
|
| 1476 | 1476 |
func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{14} }
|
| 1477 | 1477 |
|
| 1478 | 1478 |
var extRange_ServiceOptions = []proto.ExtensionRange{
|
| 1479 |
- {1000, 536870911},
|
|
| 1479 |
+ {Start: 1000, End: 536870911},
|
|
| 1480 | 1480 |
} |
| 1481 | 1481 |
|
| 1482 | 1482 |
func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1483 | 1483 |
return extRange_ServiceOptions |
| 1484 | 1484 |
} |
| 1485 |
-func (m *ServiceOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1486 |
- if m.XXX_extensions == nil {
|
|
| 1487 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1488 |
- } |
|
| 1489 |
- return m.XXX_extensions |
|
| 1490 |
-} |
|
| 1491 | 1485 |
|
| 1492 | 1486 |
const Default_ServiceOptions_Deprecated bool = false |
| 1493 | 1487 |
|
| ... | ... |
@@ -1512,9 +1478,9 @@ type MethodOptions struct {
|
| 1512 | 1512 |
// this is a formalization for deprecating methods. |
| 1513 | 1513 |
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` |
| 1514 | 1514 |
// The parser stores options it doesn't recognize here. See above. |
| 1515 |
- UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1516 |
- XXX_extensions map[int32]proto.Extension `json:"-"` |
|
| 1517 |
- XXX_unrecognized []byte `json:"-"` |
|
| 1515 |
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` |
|
| 1516 |
+ proto.XXX_InternalExtensions `json:"-"` |
|
| 1517 |
+ XXX_unrecognized []byte `json:"-"` |
|
| 1518 | 1518 |
} |
| 1519 | 1519 |
|
| 1520 | 1520 |
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
|
| ... | ... |
@@ -1523,18 +1489,12 @@ func (*MethodOptions) ProtoMessage() {}
|
| 1523 | 1523 |
func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{15} }
|
| 1524 | 1524 |
|
| 1525 | 1525 |
var extRange_MethodOptions = []proto.ExtensionRange{
|
| 1526 |
- {1000, 536870911},
|
|
| 1526 |
+ {Start: 1000, End: 536870911},
|
|
| 1527 | 1527 |
} |
| 1528 | 1528 |
|
| 1529 | 1529 |
func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
| 1530 | 1530 |
return extRange_MethodOptions |
| 1531 | 1531 |
} |
| 1532 |
-func (m *MethodOptions) ExtensionMap() map[int32]proto.Extension {
|
|
| 1533 |
- if m.XXX_extensions == nil {
|
|
| 1534 |
- m.XXX_extensions = make(map[int32]proto.Extension) |
|
| 1535 |
- } |
|
| 1536 |
- return m.XXX_extensions |
|
| 1537 |
-} |
|
| 1538 | 1532 |
|
| 1539 | 1533 |
const Default_MethodOptions_Deprecated bool = false |
| 1540 | 1534 |
|
| ... | ... |
@@ -1875,143 +1835,147 @@ func init() {
|
| 1875 | 1875 |
proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
|
| 1876 | 1876 |
} |
| 1877 | 1877 |
|
| 1878 |
+func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) }
|
|
| 1879 |
+ |
|
| 1878 | 1880 |
var fileDescriptorDescriptor = []byte{
|
| 1879 |
- // 2192 bytes of a gzipped FileDescriptorProto |
|
| 1880 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x73, 0xdb, 0xd6, |
|
| 1881 |
- 0x11, 0x2f, 0xff, 0x8a, 0x5c, 0x52, 0x24, 0xf4, 0xac, 0xd8, 0xb4, 0x62, 0xc7, 0x31, 0x63, 0xc7, |
|
| 1882 |
- 0x8e, 0xd3, 0xd2, 0x19, 0xb7, 0x49, 0x5c, 0xa5, 0x93, 0x0e, 0x45, 0xc2, 0x0a, 0x3d, 0x94, 0xc8, |
|
| 1883 |
- 0x3e, 0x92, 0xad, 0x93, 0x0b, 0x06, 0x02, 0x1f, 0x29, 0xd8, 0x20, 0xc0, 0x02, 0xa0, 0x6d, 0xe5, |
|
| 1884 |
- 0xd4, 0x99, 0x9e, 0xfa, 0x0d, 0x3a, 0x6d, 0xa7, 0x87, 0x5c, 0x32, 0xd3, 0x0f, 0xd0, 0x43, 0xef, |
|
| 1885 |
- 0xbd, 0xf6, 0xd0, 0x73, 0x8f, 0x9d, 0x69, 0xbf, 0x41, 0xaf, 0xdd, 0xf7, 0x1e, 0x00, 0x02, 0x24, |
|
| 1886 |
- 0x15, 0xab, 0x99, 0x49, 0x13, 0x5d, 0xc4, 0xb7, 0xfb, 0xdb, 0xc5, 0xbe, 0x7d, 0xbf, 0xb7, 0xbb, |
|
| 1887 |
- 0x00, 0x28, 0x63, 0xe6, 0x19, 0xae, 0x39, 0xf7, 0x1d, 0xb7, 0x31, 0x77, 0x1d, 0xdf, 0x21, 0xd5, |
|
| 1888 |
- 0xa9, 0xe3, 0x4c, 0x2d, 0x26, 0x57, 0x27, 0x8b, 0x49, 0xfd, 0x08, 0x76, 0x1e, 0x99, 0x16, 0x6b, |
|
| 1889 |
- 0x47, 0xc0, 0x01, 0xf3, 0xc9, 0x43, 0xc8, 0x4e, 0x50, 0x58, 0x4b, 0xbd, 0x99, 0xb9, 0x5b, 0x7a, |
|
| 1890 |
- 0x70, 0xab, 0xb1, 0x62, 0xd4, 0x48, 0x5a, 0xf4, 0xb9, 0x98, 0x0a, 0x8b, 0xfa, 0x3f, 0xb3, 0x70, |
|
| 1891 |
- 0x69, 0x83, 0x96, 0x10, 0xc8, 0xda, 0xfa, 0x8c, 0x7b, 0x4c, 0xdd, 0x2d, 0x52, 0xf1, 0x9b, 0xd4, |
|
| 1892 |
- 0x60, 0x6b, 0xae, 0x1b, 0xcf, 0xf4, 0x29, 0xab, 0xa5, 0x85, 0x38, 0x5c, 0x92, 0x37, 0x00, 0xc6, |
|
| 1893 |
- 0x6c, 0xce, 0xec, 0x31, 0xb3, 0x8d, 0xb3, 0x5a, 0x06, 0xa3, 0x28, 0xd2, 0x98, 0x84, 0xbc, 0x0b, |
|
| 1894 |
- 0x3b, 0xf3, 0xc5, 0x89, 0x65, 0x1a, 0x5a, 0x0c, 0x06, 0x08, 0xcb, 0x51, 0x45, 0x2a, 0xda, 0x4b, |
|
| 1895 |
- 0xf0, 0x1d, 0xa8, 0xbe, 0x60, 0xfa, 0xb3, 0x38, 0xb4, 0x24, 0xa0, 0x15, 0x2e, 0x8e, 0x01, 0x5b, |
|
| 1896 |
- 0x50, 0x9e, 0x31, 0xcf, 0xc3, 0x00, 0x34, 0xff, 0x6c, 0xce, 0x6a, 0x59, 0xb1, 0xfb, 0x37, 0xd7, |
|
| 1897 |
- 0x76, 0xbf, 0xba, 0xf3, 0x52, 0x60, 0x35, 0x44, 0x23, 0xd2, 0x84, 0x22, 0xb3, 0x17, 0x33, 0xe9, |
|
| 1898 |
- 0x21, 0x77, 0x4e, 0xfe, 0x54, 0x44, 0xac, 0x7a, 0x29, 0x70, 0xb3, 0xc0, 0xc5, 0x96, 0xc7, 0xdc, |
|
| 1899 |
- 0xe7, 0xa6, 0xc1, 0x6a, 0x79, 0xe1, 0xe0, 0xce, 0x9a, 0x83, 0x81, 0xd4, 0xaf, 0xfa, 0x08, 0xed, |
|
| 1900 |
- 0x70, 0x2b, 0x45, 0xf6, 0xd2, 0x67, 0xb6, 0x67, 0x3a, 0x76, 0x6d, 0x4b, 0x38, 0xb9, 0xbd, 0xe1, |
|
| 1901 |
- 0x14, 0x99, 0x35, 0x5e, 0x75, 0xb1, 0xb4, 0x23, 0x1f, 0xc0, 0x96, 0x33, 0xf7, 0xf1, 0x97, 0x57, |
|
| 1902 |
- 0x2b, 0xe0, 0xf9, 0x94, 0x1e, 0x5c, 0xdb, 0x48, 0x84, 0x9e, 0xc4, 0xd0, 0x10, 0x4c, 0x3a, 0xa0, |
|
| 1903 |
- 0x78, 0xce, 0xc2, 0x35, 0x98, 0x66, 0x38, 0x63, 0xa6, 0x99, 0xf6, 0xc4, 0xa9, 0x15, 0x85, 0x83, |
|
| 1904 |
- 0x1b, 0xeb, 0x1b, 0x11, 0xc0, 0x16, 0xe2, 0x3a, 0x08, 0xa3, 0x15, 0x2f, 0xb1, 0x26, 0x97, 0x21, |
|
| 1905 |
- 0xef, 0x9d, 0xd9, 0xbe, 0xfe, 0xb2, 0x56, 0x16, 0x0c, 0x09, 0x56, 0xf5, 0xff, 0xe4, 0xa0, 0x7a, |
|
| 1906 |
- 0x11, 0x8a, 0x7d, 0x04, 0xb9, 0x09, 0xdf, 0x25, 0x12, 0xec, 0x7f, 0xc8, 0x81, 0xb4, 0x49, 0x26, |
|
| 1907 |
- 0x31, 0xff, 0x35, 0x93, 0xd8, 0x84, 0x92, 0xcd, 0x3c, 0x9f, 0x8d, 0x25, 0x23, 0x32, 0x17, 0xe4, |
|
| 1908 |
- 0x14, 0x48, 0xa3, 0x75, 0x4a, 0x65, 0xbf, 0x16, 0xa5, 0x9e, 0x40, 0x35, 0x0a, 0x49, 0x73, 0x75, |
|
| 1909 |
- 0x7b, 0x1a, 0x72, 0xf3, 0xfe, 0xab, 0x22, 0x69, 0xa8, 0xa1, 0x1d, 0xe5, 0x66, 0xb4, 0xc2, 0x12, |
|
| 1910 |
- 0x6b, 0xd2, 0x06, 0x70, 0x6c, 0xe6, 0x4c, 0xf0, 0x7a, 0x19, 0x16, 0xf2, 0x64, 0x73, 0x96, 0x7a, |
|
| 1911 |
- 0x1c, 0xb2, 0x96, 0x25, 0x47, 0x4a, 0x0d, 0x8b, 0xfc, 0x78, 0x49, 0xb5, 0xad, 0x73, 0x98, 0x72, |
|
| 1912 |
- 0x24, 0x2f, 0xd9, 0x1a, 0xdb, 0x46, 0x50, 0x71, 0x19, 0xe7, 0x3d, 0xa6, 0x58, 0xee, 0xac, 0x28, |
|
| 1913 |
- 0x82, 0x68, 0xbc, 0x72, 0x67, 0x34, 0x30, 0x93, 0x1b, 0xdb, 0x76, 0xe3, 0x4b, 0xf2, 0x16, 0x44, |
|
| 1914 |
- 0x02, 0x4d, 0xd0, 0x0a, 0x44, 0x15, 0x2a, 0x87, 0xc2, 0x63, 0x94, 0xed, 0x3d, 0x84, 0x4a, 0x32, |
|
| 1915 |
- 0x3d, 0x64, 0x17, 0x72, 0x9e, 0xaf, 0xbb, 0xbe, 0x60, 0x61, 0x8e, 0xca, 0x05, 0x51, 0x20, 0x83, |
|
| 1916 |
- 0x45, 0x46, 0x54, 0xb9, 0x1c, 0xe5, 0x3f, 0xf7, 0x3e, 0x84, 0xed, 0xc4, 0xe3, 0x2f, 0x6a, 0x58, |
|
| 1917 |
- 0xff, 0x6d, 0x1e, 0x76, 0x37, 0x71, 0x6e, 0x23, 0xfd, 0xf1, 0xfa, 0x20, 0x03, 0x4e, 0x98, 0x8b, |
|
| 1918 |
- 0xbc, 0xe3, 0x1e, 0x82, 0x15, 0x32, 0x2a, 0x67, 0xe9, 0x27, 0xcc, 0x42, 0x36, 0xa5, 0xee, 0x56, |
|
| 1919 |
- 0x1e, 0xbc, 0x7b, 0x21, 0x56, 0x37, 0xba, 0xdc, 0x84, 0x4a, 0x4b, 0xf2, 0x31, 0x64, 0x83, 0x12, |
|
| 1920 |
- 0xc7, 0x3d, 0xdc, 0xbb, 0x98, 0x07, 0xce, 0x45, 0x2a, 0xec, 0xc8, 0xeb, 0x50, 0xe4, 0xff, 0x65, |
|
| 1921 |
- 0x6e, 0xf3, 0x22, 0xe6, 0x02, 0x17, 0xf0, 0xbc, 0x92, 0x3d, 0x28, 0x08, 0x9a, 0x8d, 0x59, 0xd8, |
|
| 1922 |
- 0x1a, 0xa2, 0x35, 0x3f, 0x98, 0x31, 0x9b, 0xe8, 0x0b, 0xcb, 0xd7, 0x9e, 0xeb, 0xd6, 0x82, 0x09, |
|
| 1923 |
- 0xc2, 0xe0, 0xc1, 0x04, 0xc2, 0x9f, 0x73, 0x19, 0xb9, 0x01, 0x25, 0xc9, 0x4a, 0x13, 0x6d, 0x5e, |
|
| 1924 |
- 0x8a, 0xea, 0x93, 0xa3, 0x92, 0xa8, 0x1d, 0x2e, 0xe1, 0x8f, 0x7f, 0xea, 0xe1, 0x5d, 0x08, 0x8e, |
|
| 1925 |
- 0x56, 0x3c, 0x82, 0x0b, 0xc4, 0xe3, 0x3f, 0x5c, 0x2d, 0x7c, 0xd7, 0x37, 0x6f, 0x6f, 0x95, 0x8b, |
|
| 1926 |
- 0xf5, 0x3f, 0xa7, 0x21, 0x2b, 0xee, 0x5b, 0x15, 0x4a, 0xc3, 0x4f, 0xfb, 0xaa, 0xd6, 0xee, 0x8d, |
|
| 1927 |
- 0x0e, 0xba, 0xaa, 0x92, 0x22, 0x15, 0x00, 0x21, 0x78, 0xd4, 0xed, 0x35, 0x87, 0x4a, 0x3a, 0x5a, |
|
| 1928 |
- 0x77, 0x8e, 0x87, 0x1f, 0xfc, 0x48, 0xc9, 0x44, 0x06, 0x23, 0x29, 0xc8, 0xc6, 0x01, 0x3f, 0x7c, |
|
| 1929 |
- 0xa0, 0xe4, 0x90, 0x09, 0x65, 0xe9, 0xa0, 0xf3, 0x44, 0x6d, 0x23, 0x22, 0x9f, 0x94, 0x20, 0x66, |
|
| 1930 |
- 0x8b, 0x6c, 0x43, 0x51, 0x48, 0x0e, 0x7a, 0xbd, 0xae, 0x52, 0x88, 0x7c, 0x0e, 0x86, 0xb4, 0x73, |
|
| 1931 |
- 0x7c, 0xa8, 0x14, 0x23, 0x9f, 0x87, 0xb4, 0x37, 0xea, 0x2b, 0x10, 0x79, 0x38, 0x52, 0x07, 0x83, |
|
| 1932 |
- 0xe6, 0xa1, 0xaa, 0x94, 0x22, 0xc4, 0xc1, 0xa7, 0x43, 0x75, 0xa0, 0x94, 0x13, 0x61, 0xe1, 0x23, |
|
| 1933 |
- 0xb6, 0xa3, 0x47, 0xa8, 0xc7, 0xa3, 0x23, 0xa5, 0x42, 0x76, 0x60, 0x5b, 0x3e, 0x22, 0x0c, 0xa2, |
|
| 1934 |
- 0xba, 0x22, 0xc2, 0x48, 0x95, 0x65, 0x20, 0xd2, 0xcb, 0x4e, 0x42, 0x80, 0x08, 0x52, 0x6f, 0x41, |
|
| 1935 |
- 0x4e, 0xb0, 0x0b, 0x59, 0x5c, 0xe9, 0x36, 0x0f, 0xd4, 0xae, 0xd6, 0xeb, 0x0f, 0x3b, 0xbd, 0xe3, |
|
| 1936 |
- 0x66, 0x17, 0x73, 0x17, 0xc9, 0xa8, 0xfa, 0xb3, 0x51, 0x87, 0xaa, 0x6d, 0xcc, 0x5f, 0x4c, 0xd6, |
|
| 1937 |
- 0x57, 0x9b, 0x43, 0x94, 0x65, 0xea, 0xf7, 0x60, 0x77, 0x53, 0x9d, 0xd9, 0x74, 0x33, 0xea, 0x5f, |
|
| 1938 |
- 0xa4, 0xe0, 0xd2, 0x86, 0x92, 0xb9, 0xf1, 0x16, 0xfd, 0x14, 0x72, 0x92, 0x69, 0xb2, 0x89, 0xbc, |
|
| 1939 |
- 0xb3, 0xb1, 0xf6, 0x0a, 0xde, 0xad, 0x35, 0x12, 0x61, 0x17, 0x6f, 0xa4, 0x99, 0x73, 0x1a, 0x29, |
|
| 1940 |
- 0x77, 0xb1, 0x46, 0xa7, 0x5f, 0xa7, 0xa0, 0x76, 0x9e, 0xef, 0x57, 0xdc, 0xf7, 0x74, 0xe2, 0xbe, |
|
| 1941 |
- 0x7f, 0xb4, 0x1a, 0xc0, 0xcd, 0xf3, 0xf7, 0xb0, 0x16, 0xc5, 0x97, 0x29, 0xb8, 0xbc, 0x79, 0xde, |
|
| 1942 |
- 0xd8, 0x18, 0xc3, 0xc7, 0x90, 0x9f, 0x31, 0xff, 0xd4, 0x09, 0x7b, 0xee, 0xdb, 0x1b, 0x2a, 0x39, |
|
| 1943 |
- 0x57, 0xaf, 0xe6, 0x2a, 0xb0, 0x8a, 0xb7, 0x82, 0xcc, 0x79, 0x43, 0x83, 0x8c, 0x66, 0x2d, 0xd2, |
|
| 1944 |
- 0xdf, 0xa4, 0xe1, 0xb5, 0x8d, 0xce, 0x37, 0x06, 0x7a, 0x1d, 0xc0, 0xb4, 0xe7, 0x0b, 0x5f, 0xf6, |
|
| 1945 |
- 0x55, 0x59, 0x66, 0x8a, 0x42, 0x22, 0xae, 0x30, 0x2f, 0x21, 0x0b, 0x3f, 0xd2, 0x67, 0x84, 0x1e, |
|
| 1946 |
- 0xa4, 0x48, 0x00, 0x1e, 0x2e, 0x03, 0xcd, 0x8a, 0x40, 0xdf, 0x38, 0x67, 0xa7, 0x6b, 0x2d, 0xeb, |
|
| 1947 |
- 0x3d, 0x50, 0x0c, 0xcb, 0x64, 0xb6, 0xaf, 0x79, 0xbe, 0xcb, 0xf4, 0x99, 0x69, 0x4f, 0x45, 0x1d, |
|
| 1948 |
- 0x2d, 0xec, 0xe7, 0x26, 0xba, 0xe5, 0x31, 0x5a, 0x95, 0xea, 0x41, 0xa8, 0xe5, 0x16, 0xa2, 0x59, |
|
| 1949 |
- 0xb8, 0x31, 0x8b, 0x7c, 0xc2, 0x42, 0xaa, 0x23, 0x8b, 0xfa, 0xdf, 0xb7, 0xa0, 0x14, 0x9b, 0xce, |
|
| 1950 |
- 0xc8, 0x4d, 0x28, 0x3f, 0xd5, 0x9f, 0xeb, 0x5a, 0x38, 0x71, 0xcb, 0x4c, 0x94, 0xb8, 0xac, 0x1f, |
|
| 1951 |
- 0x4c, 0xdd, 0xef, 0xc1, 0xae, 0x80, 0xe0, 0x1e, 0xf1, 0x41, 0x86, 0xa5, 0x7b, 0x9e, 0x48, 0x5a, |
|
| 1952 |
- 0x41, 0x40, 0x09, 0xd7, 0xf5, 0xb8, 0xaa, 0x15, 0x6a, 0xc8, 0xfb, 0x70, 0x49, 0x58, 0xcc, 0xb0, |
|
| 1953 |
- 0xf0, 0x9a, 0x73, 0x8b, 0x69, 0xfc, 0x1d, 0xc0, 0x13, 0xf5, 0x34, 0x8a, 0x6c, 0x87, 0x23, 0x8e, |
|
| 1954 |
- 0x02, 0x00, 0x8f, 0xc8, 0x23, 0x87, 0x70, 0x5d, 0x98, 0x4d, 0x99, 0xcd, 0x5c, 0xdd, 0x67, 0x1a, |
|
| 1955 |
- 0xfb, 0xe5, 0x02, 0xb1, 0x9a, 0x6e, 0x8f, 0xb5, 0x53, 0xdd, 0x3b, 0xad, 0xed, 0xc6, 0x1d, 0x5c, |
|
| 1956 |
- 0xe5, 0xd8, 0xc3, 0x00, 0xaa, 0x0a, 0x64, 0xd3, 0x1e, 0x7f, 0x82, 0x38, 0xb2, 0x0f, 0x97, 0x85, |
|
| 1957 |
- 0x23, 0x4c, 0x0a, 0xee, 0x59, 0x33, 0x4e, 0x99, 0xf1, 0x4c, 0x5b, 0xf8, 0x93, 0x87, 0xb5, 0xd7, |
|
| 1958 |
- 0xe3, 0x1e, 0x44, 0x90, 0x03, 0x81, 0x69, 0x71, 0xc8, 0x08, 0x11, 0x64, 0x00, 0x65, 0x7e, 0x1e, |
|
| 1959 |
- 0x33, 0xf3, 0x73, 0x0c, 0xdb, 0x71, 0x45, 0x8f, 0xa8, 0x6c, 0xb8, 0xdc, 0xb1, 0x24, 0x36, 0x7a, |
|
| 1960 |
- 0x81, 0xc1, 0x11, 0xce, 0xa7, 0xfb, 0xb9, 0x41, 0x5f, 0x55, 0xdb, 0xb4, 0x14, 0x7a, 0x79, 0xe4, |
|
| 1961 |
- 0xb8, 0x9c, 0x53, 0x53, 0x27, 0xca, 0x71, 0x49, 0x72, 0x6a, 0xea, 0x84, 0x19, 0xc6, 0x7c, 0x19, |
|
| 1962 |
- 0x86, 0xdc, 0x36, 0xbe, 0xbb, 0x04, 0xc3, 0xba, 0x57, 0x53, 0x12, 0xf9, 0x32, 0x8c, 0x43, 0x09, |
|
| 1963 |
- 0x08, 0x68, 0xee, 0xe1, 0x95, 0x78, 0x6d, 0x99, 0xaf, 0xb8, 0xe1, 0xce, 0xda, 0x2e, 0x57, 0x4d, |
|
| 1964 |
- 0xf1, 0x89, 0xf3, 0xb3, 0x75, 0x43, 0x92, 0x78, 0xe2, 0xfc, 0x6c, 0xd5, 0xec, 0xb6, 0x78, 0x01, |
|
| 1965 |
- 0x73, 0x99, 0x81, 0x29, 0x1f, 0xd7, 0xae, 0xc4, 0xd1, 0x31, 0x05, 0xb9, 0x8f, 0x44, 0x36, 0x34, |
|
| 1966 |
- 0x66, 0xeb, 0x27, 0x78, 0xf6, 0xba, 0x8b, 0x3f, 0xbc, 0xda, 0x8d, 0x38, 0xb8, 0x62, 0x18, 0xaa, |
|
| 1967 |
- 0xd0, 0x36, 0x85, 0x92, 0xdc, 0x83, 0x1d, 0xe7, 0xe4, 0xa9, 0x21, 0xc9, 0xa5, 0xa1, 0x9f, 0x89, |
|
| 1968 |
- 0xf9, 0xb2, 0x76, 0x4b, 0xa4, 0xa9, 0xca, 0x15, 0x82, 0x5a, 0x7d, 0x21, 0x26, 0xef, 0xa0, 0x73, |
|
| 1969 |
- 0xef, 0x54, 0x77, 0xe7, 0xa2, 0x49, 0x7b, 0x98, 0x54, 0x56, 0xbb, 0x2d, 0xa1, 0x52, 0x7e, 0x1c, |
|
| 1970 |
- 0x8a, 0x89, 0x0a, 0x37, 0xf8, 0xe6, 0x6d, 0xdd, 0x76, 0xb4, 0x85, 0xc7, 0xb4, 0x65, 0x88, 0xd1, |
|
| 1971 |
- 0x59, 0xbc, 0xcd, 0xc3, 0xa2, 0xd7, 0x42, 0xd8, 0xc8, 0xc3, 0x62, 0x16, 0x82, 0xc2, 0xe3, 0x79, |
|
| 1972 |
- 0x02, 0xbb, 0x0b, 0xdb, 0xb4, 0x91, 0xe2, 0xa8, 0xe1, 0xc6, 0xf2, 0xc2, 0xd6, 0xfe, 0xb5, 0x75, |
|
| 1973 |
- 0xce, 0xd0, 0x3d, 0x8a, 0xa3, 0x25, 0x49, 0xe8, 0xa5, 0xc5, 0xba, 0xb0, 0xbe, 0x0f, 0xe5, 0x38, |
|
| 1974 |
- 0x77, 0x48, 0x11, 0x24, 0x7b, 0xb0, 0xbb, 0x61, 0x47, 0x6d, 0xf5, 0xda, 0xbc, 0x17, 0x7e, 0xa6, |
|
| 1975 |
- 0x62, 0x63, 0xc3, 0x9e, 0xdc, 0xed, 0x0c, 0x55, 0x8d, 0x8e, 0x8e, 0x87, 0x9d, 0x23, 0x55, 0xc9, |
|
| 1976 |
- 0xdc, 0x2b, 0x16, 0xfe, 0xbd, 0xa5, 0xfc, 0x0a, 0xff, 0xd2, 0xf5, 0xbf, 0xa6, 0xa1, 0x92, 0x9c, |
|
| 1977 |
- 0x83, 0xc9, 0x4f, 0xe0, 0x4a, 0xf8, 0xd2, 0xea, 0x31, 0x5f, 0x7b, 0x61, 0xba, 0x82, 0xce, 0x33, |
|
| 1978 |
- 0x5d, 0x4e, 0x92, 0xd1, 0x49, 0xec, 0x06, 0x28, 0x7c, 0xbd, 0xff, 0x05, 0x62, 0x1e, 0x09, 0x08, |
|
| 1979 |
- 0xe9, 0xc2, 0x0d, 0x4c, 0x19, 0xce, 0x9a, 0xf6, 0x58, 0x77, 0xc7, 0xda, 0xf2, 0x73, 0x81, 0xa6, |
|
| 1980 |
- 0x1b, 0xc8, 0x03, 0xcf, 0x91, 0x9d, 0x24, 0xf2, 0x72, 0xcd, 0x76, 0x06, 0x01, 0x78, 0x59, 0x62, |
|
| 1981 |
- 0x9b, 0x01, 0x74, 0x85, 0x35, 0x99, 0xf3, 0x58, 0x83, 0xb3, 0xd7, 0x4c, 0x9f, 0x23, 0x6d, 0x7c, |
|
| 1982 |
- 0xf7, 0x4c, 0x4c, 0x6f, 0x05, 0x5a, 0x40, 0x81, 0xca, 0xd7, 0xdf, 0xdc, 0x19, 0xc4, 0xf3, 0xf8, |
|
| 1983 |
- 0x8f, 0x0c, 0x94, 0xe3, 0x13, 0x1c, 0x1f, 0x88, 0x0d, 0x51, 0xe6, 0x53, 0xa2, 0x0a, 0xbc, 0xf5, |
|
| 1984 |
- 0x95, 0xf3, 0x5e, 0xa3, 0xc5, 0xeb, 0xff, 0x7e, 0x5e, 0xce, 0x55, 0x54, 0x5a, 0xf2, 0xde, 0xcb, |
|
| 1985 |
- 0xb9, 0xc6, 0xe4, 0xb4, 0x5e, 0xa0, 0xc1, 0x0a, 0x8b, 0x5d, 0xfe, 0xa9, 0x27, 0x7c, 0xe7, 0x85, |
|
| 1986 |
- 0xef, 0x5b, 0x5f, 0xed, 0xfb, 0xf1, 0x40, 0x38, 0x2f, 0x3e, 0x1e, 0x68, 0xc7, 0x3d, 0x7a, 0xd4, |
|
| 1987 |
- 0xec, 0xd2, 0xc0, 0x9c, 0x5c, 0x85, 0xac, 0xa5, 0x7f, 0x7e, 0x96, 0xec, 0x14, 0x42, 0x74, 0xd1, |
|
| 1988 |
- 0xc4, 0xa3, 0x07, 0xfe, 0xc9, 0x23, 0x59, 0x9f, 0x85, 0xe8, 0x1b, 0xa4, 0xfe, 0x7d, 0xc8, 0x89, |
|
| 1989 |
- 0x7c, 0x11, 0x80, 0x20, 0x63, 0xca, 0xf7, 0x48, 0x01, 0xb2, 0xad, 0x1e, 0xe5, 0xf4, 0x47, 0xbe, |
|
| 1990 |
- 0x4b, 0xa9, 0xd6, 0xef, 0xa8, 0x2d, 0xbc, 0x01, 0xf5, 0xf7, 0x21, 0x2f, 0x93, 0xc0, 0xaf, 0x46, |
|
| 1991 |
- 0x94, 0x06, 0x34, 0x92, 0xcb, 0xc0, 0x47, 0x2a, 0xd4, 0x8e, 0x8e, 0x0e, 0x54, 0xaa, 0xa4, 0xe3, |
|
| 1992 |
- 0xc7, 0xfb, 0x97, 0x14, 0x94, 0x62, 0x03, 0x15, 0x6f, 0xe5, 0xba, 0x65, 0x39, 0x2f, 0x34, 0xdd, |
|
| 1993 |
- 0x32, 0xb1, 0x42, 0xc9, 0xf3, 0x01, 0x21, 0x6a, 0x72, 0xc9, 0x45, 0xf3, 0xf7, 0x7f, 0xe1, 0xe6, |
|
| 1994 |
- 0x1f, 0x53, 0xa0, 0xac, 0x0e, 0x63, 0x2b, 0x01, 0xa6, 0xbe, 0xd5, 0x00, 0xff, 0x90, 0x82, 0x4a, |
|
| 1995 |
- 0x72, 0x02, 0x5b, 0x09, 0xef, 0xe6, 0xb7, 0x1a, 0xde, 0xef, 0x53, 0xb0, 0x9d, 0x98, 0xbb, 0xbe, |
|
| 1996 |
- 0x53, 0xd1, 0xfd, 0x2e, 0x03, 0x97, 0x36, 0xd8, 0x61, 0x01, 0x92, 0x03, 0xaa, 0x9c, 0x99, 0x7f, |
|
| 1997 |
- 0x70, 0x91, 0x67, 0x35, 0x78, 0xff, 0xeb, 0xeb, 0xae, 0x1f, 0xcc, 0xb3, 0xd8, 0x2f, 0xcd, 0x31, |
|
| 1998 |
- 0x16, 0x55, 0x73, 0x62, 0xe2, 0xf8, 0x26, 0xdf, 0x58, 0xe4, 0xd4, 0x5a, 0x5d, 0xca, 0xe5, 0xeb, |
|
| 1999 |
- 0xf1, 0xf7, 0x81, 0xcc, 0x1d, 0xcf, 0xf4, 0xcd, 0xe7, 0xfc, 0xf3, 0x5c, 0xf8, 0x22, 0xcd, 0xa7, |
|
| 2000 |
- 0xd8, 0x2c, 0x55, 0x42, 0x4d, 0xc7, 0xf6, 0x23, 0xb4, 0xcd, 0xa6, 0xfa, 0x0a, 0x9a, 0x97, 0xa1, |
|
| 2001 |
- 0x0c, 0x55, 0x42, 0x4d, 0x84, 0xc6, 0x41, 0x73, 0xec, 0x2c, 0xf8, 0x40, 0x20, 0x71, 0xbc, 0xea, |
|
| 2002 |
- 0xa5, 0x68, 0x49, 0xca, 0x22, 0x48, 0x30, 0xb1, 0x2d, 0xdf, 0xe0, 0xcb, 0xb4, 0x24, 0x65, 0x12, |
|
| 2003 |
- 0x72, 0x07, 0xaa, 0xfa, 0x74, 0xea, 0x72, 0xe7, 0xa1, 0x23, 0x39, 0x86, 0x56, 0x22, 0xb1, 0x00, |
|
| 2004 |
- 0xee, 0x3d, 0x86, 0x42, 0x98, 0x07, 0xde, 0x58, 0x78, 0x26, 0xb0, 0xe7, 0x8b, 0xef, 0x28, 0x69, |
|
| 2005 |
- 0xfe, 0x52, 0x6f, 0x87, 0x4a, 0x7c, 0xa8, 0xe9, 0x69, 0xcb, 0x0f, 0x7a, 0x69, 0xd4, 0x17, 0x68, |
|
| 2006 |
- 0xc9, 0xf4, 0xa2, 0x2f, 0x38, 0xf5, 0x2f, 0xb1, 0xbd, 0x26, 0x3f, 0x48, 0x92, 0x36, 0x14, 0x2c, |
|
| 2007 |
- 0x07, 0xf9, 0xc1, 0x2d, 0xe4, 0xd7, 0xf0, 0xbb, 0xaf, 0xf8, 0x86, 0xd9, 0xe8, 0x06, 0x78, 0x1a, |
|
| 2008 |
- 0x59, 0xee, 0xfd, 0x2d, 0x05, 0x85, 0x50, 0x8c, 0x8d, 0x22, 0x3b, 0xd7, 0xfd, 0x53, 0xe1, 0x2e, |
|
| 2009 |
- 0x77, 0x90, 0x56, 0x52, 0x54, 0xac, 0xb9, 0x1c, 0xa7, 0x19, 0x5b, 0x50, 0x20, 0x90, 0xf3, 0x35, |
|
| 2010 |
- 0x3f, 0x57, 0x8b, 0xe9, 0x63, 0x31, 0xe0, 0x3a, 0xb3, 0x19, 0x9e, 0xa4, 0x17, 0x9e, 0x6b, 0x20, |
|
| 2011 |
- 0x6f, 0x05, 0x62, 0xfe, 0x5d, 0xdc, 0x77, 0x75, 0xd3, 0x4a, 0x60, 0xb3, 0x02, 0xab, 0x84, 0x8a, |
|
| 2012 |
- 0x08, 0xbc, 0x0f, 0x57, 0x43, 0xbf, 0x63, 0xe6, 0xeb, 0x38, 0x3c, 0x8f, 0x97, 0x46, 0x79, 0xf1, |
|
| 2013 |
- 0xb5, 0xeb, 0x4a, 0x00, 0x68, 0x07, 0xfa, 0xd0, 0xf6, 0xe0, 0x09, 0x0e, 0xb2, 0xce, 0x6c, 0x35, |
|
| 2014 |
- 0x13, 0x07, 0xca, 0xca, 0x7b, 0x97, 0xf7, 0x49, 0xea, 0x33, 0x58, 0x0e, 0x15, 0x5f, 0xa4, 0x33, |
|
| 2015 |
- 0x87, 0xfd, 0x83, 0x3f, 0xa5, 0xf7, 0x0e, 0xa5, 0x5d, 0x3f, 0xcc, 0x20, 0x65, 0x13, 0x8b, 0x19, |
|
| 2016 |
- 0x3c, 0x3b, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x78, 0x42, 0x69, 0x71, 0xb3, 0x18, 0x00, 0x00, |
|
| 1881 |
+ // 2211 bytes of a gzipped FileDescriptorProto |
|
| 1882 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x73, 0xdb, 0xc6, |
|
| 1883 |
+ 0x15, 0x0f, 0xf8, 0x4f, 0xe4, 0x23, 0x45, 0xad, 0x56, 0x8a, 0x03, 0xcb, 0x76, 0x2c, 0x33, 0x76, |
|
| 1884 |
+ 0x2c, 0xdb, 0xad, 0x9c, 0x91, 0xff, 0x44, 0x51, 0x3a, 0xe9, 0x50, 0x24, 0xac, 0xd0, 0x43, 0x89, |
|
| 1885 |
+ 0x2c, 0x28, 0xb6, 0x4e, 0x2e, 0x98, 0x15, 0xb0, 0xa4, 0x60, 0x83, 0x0b, 0x14, 0x00, 0x6d, 0x2b, |
|
| 1886 |
+ 0x27, 0xcf, 0xf4, 0xd4, 0x6f, 0xd0, 0x69, 0x3b, 0x3d, 0xe4, 0x92, 0x99, 0x7e, 0x80, 0x1e, 0x7a, |
|
| 1887 |
+ 0xef, 0xb5, 0x87, 0x9e, 0x7b, 0xec, 0x4c, 0xfb, 0x0d, 0x7a, 0xed, 0xec, 0x2e, 0x00, 0x82, 0x7f, |
|
| 1888 |
+ 0x14, 0xab, 0x99, 0x49, 0xd3, 0x93, 0xb4, 0xbf, 0xf7, 0x7b, 0x8f, 0x6f, 0xdf, 0xfe, 0xb0, 0xef, |
|
| 1889 |
+ 0x01, 0x80, 0x2c, 0x1a, 0x98, 0xbe, 0xed, 0x85, 0xae, 0xbf, 0xed, 0xf9, 0x6e, 0xe8, 0xe2, 0x95, |
|
| 1890 |
+ 0xa1, 0xeb, 0x0e, 0x1d, 0x2a, 0x57, 0x27, 0xe3, 0x41, 0xed, 0x10, 0x56, 0x9f, 0xd8, 0x0e, 0x6d, |
|
| 1891 |
+ 0x26, 0xc4, 0x1e, 0x0d, 0xf1, 0x2e, 0xe4, 0x06, 0xb6, 0x43, 0x55, 0x65, 0x33, 0xbb, 0x55, 0xde, |
|
| 1892 |
+ 0xb9, 0xb9, 0x3d, 0xe3, 0xb4, 0x3d, 0xed, 0xd1, 0xe5, 0xb0, 0x2e, 0x3c, 0x6a, 0xff, 0xc8, 0xc1, |
|
| 1893 |
+ 0xda, 0x02, 0x2b, 0xc6, 0x90, 0x63, 0x64, 0xc4, 0x23, 0x2a, 0x5b, 0x25, 0x5d, 0xfc, 0x8f, 0x55, |
|
| 1894 |
+ 0x58, 0xf2, 0x88, 0xf9, 0x82, 0x0c, 0xa9, 0x9a, 0x11, 0x70, 0xbc, 0xc4, 0xef, 0x03, 0x58, 0xd4, |
|
| 1895 |
+ 0xa3, 0xcc, 0xa2, 0xcc, 0x3c, 0x53, 0xb3, 0x9b, 0xd9, 0xad, 0x92, 0x9e, 0x42, 0xf0, 0x3d, 0x58, |
|
| 1896 |
+ 0xf5, 0xc6, 0x27, 0x8e, 0x6d, 0x1a, 0x29, 0x1a, 0x6c, 0x66, 0xb7, 0xf2, 0x3a, 0x92, 0x86, 0xe6, |
|
| 1897 |
+ 0x84, 0x7c, 0x1b, 0x56, 0x5e, 0x51, 0xf2, 0x22, 0x4d, 0x2d, 0x0b, 0x6a, 0x95, 0xc3, 0x29, 0x62, |
|
| 1898 |
+ 0x03, 0x2a, 0x23, 0x1a, 0x04, 0x64, 0x48, 0x8d, 0xf0, 0xcc, 0xa3, 0x6a, 0x4e, 0xec, 0x7e, 0x73, |
|
| 1899 |
+ 0x6e, 0xf7, 0xb3, 0x3b, 0x2f, 0x47, 0x5e, 0xc7, 0x67, 0x1e, 0xc5, 0x75, 0x28, 0x51, 0x36, 0x1e, |
|
| 1900 |
+ 0xc9, 0x08, 0xf9, 0x73, 0xea, 0xa7, 0xb1, 0xf1, 0x68, 0x36, 0x4a, 0x91, 0xbb, 0x45, 0x21, 0x96, |
|
| 1901 |
+ 0x02, 0xea, 0xbf, 0xb4, 0x4d, 0xaa, 0x16, 0x44, 0x80, 0xdb, 0x73, 0x01, 0x7a, 0xd2, 0x3e, 0x1b, |
|
| 1902 |
+ 0x23, 0xf6, 0xc3, 0x0d, 0x28, 0xd1, 0xd7, 0x21, 0x65, 0x81, 0xed, 0x32, 0x75, 0x49, 0x04, 0xb9, |
|
| 1903 |
+ 0xb5, 0xe0, 0x14, 0xa9, 0x63, 0xcd, 0x86, 0x98, 0xf8, 0xe1, 0xc7, 0xb0, 0xe4, 0x7a, 0xa1, 0xed, |
|
| 1904 |
+ 0xb2, 0x40, 0x2d, 0x6e, 0x2a, 0x5b, 0xe5, 0x9d, 0xab, 0x0b, 0x85, 0xd0, 0x91, 0x1c, 0x3d, 0x26, |
|
| 1905 |
+ 0xe3, 0x16, 0xa0, 0xc0, 0x1d, 0xfb, 0x26, 0x35, 0x4c, 0xd7, 0xa2, 0x86, 0xcd, 0x06, 0xae, 0x5a, |
|
| 1906 |
+ 0x12, 0x01, 0xae, 0xcf, 0x6f, 0x44, 0x10, 0x1b, 0xae, 0x45, 0x5b, 0x6c, 0xe0, 0xea, 0xd5, 0x60, |
|
| 1907 |
+ 0x6a, 0x8d, 0x2f, 0x41, 0x21, 0x38, 0x63, 0x21, 0x79, 0xad, 0x56, 0x84, 0x42, 0xa2, 0x55, 0xed, |
|
| 1908 |
+ 0xdf, 0x79, 0x58, 0xb9, 0x88, 0xc4, 0x3e, 0x85, 0xfc, 0x80, 0xef, 0x52, 0xcd, 0xfc, 0x37, 0x35, |
|
| 1909 |
+ 0x90, 0x3e, 0xd3, 0x45, 0x2c, 0x7c, 0xc7, 0x22, 0xd6, 0xa1, 0xcc, 0x68, 0x10, 0x52, 0x4b, 0x2a, |
|
| 1910 |
+ 0x22, 0x7b, 0x41, 0x4d, 0x81, 0x74, 0x9a, 0x97, 0x54, 0xee, 0x3b, 0x49, 0xea, 0x19, 0xac, 0x24, |
|
| 1911 |
+ 0x29, 0x19, 0x3e, 0x61, 0xc3, 0x58, 0x9b, 0xf7, 0xdf, 0x96, 0xc9, 0xb6, 0x16, 0xfb, 0xe9, 0xdc, |
|
| 1912 |
+ 0x4d, 0xaf, 0xd2, 0xa9, 0x35, 0x6e, 0x02, 0xb8, 0x8c, 0xba, 0x03, 0xc3, 0xa2, 0xa6, 0xa3, 0x16, |
|
| 1913 |
+ 0xcf, 0xa9, 0x52, 0x87, 0x53, 0xe6, 0xaa, 0xe4, 0x4a, 0xd4, 0x74, 0xf0, 0x27, 0x13, 0xa9, 0x2d, |
|
| 1914 |
+ 0x9d, 0xa3, 0x94, 0x43, 0xf9, 0x90, 0xcd, 0xa9, 0xad, 0x0f, 0x55, 0x9f, 0x72, 0xdd, 0x53, 0x2b, |
|
| 1915 |
+ 0xda, 0x59, 0x49, 0x24, 0xb1, 0xfd, 0xd6, 0x9d, 0xe9, 0x91, 0x9b, 0xdc, 0xd8, 0xb2, 0x9f, 0x5e, |
|
| 1916 |
+ 0xe2, 0x0f, 0x20, 0x01, 0x0c, 0x21, 0x2b, 0x10, 0xb7, 0x50, 0x25, 0x06, 0x8f, 0xc8, 0x88, 0x6e, |
|
| 1917 |
+ 0xec, 0x42, 0x75, 0xba, 0x3c, 0x78, 0x1d, 0xf2, 0x41, 0x48, 0xfc, 0x50, 0xa8, 0x30, 0xaf, 0xcb, |
|
| 1918 |
+ 0x05, 0x46, 0x90, 0xa5, 0xcc, 0x12, 0xb7, 0x5c, 0x5e, 0xe7, 0xff, 0x6e, 0x7c, 0x0c, 0xcb, 0x53, |
|
| 1919 |
+ 0x3f, 0x7f, 0x51, 0xc7, 0xda, 0x6f, 0x0a, 0xb0, 0xbe, 0x48, 0x73, 0x0b, 0xe5, 0x7f, 0x09, 0x0a, |
|
| 1920 |
+ 0x6c, 0x3c, 0x3a, 0xa1, 0xbe, 0x9a, 0x15, 0x11, 0xa2, 0x15, 0xae, 0x43, 0xde, 0x21, 0x27, 0xd4, |
|
| 1921 |
+ 0x51, 0x73, 0x9b, 0xca, 0x56, 0x75, 0xe7, 0xde, 0x85, 0x54, 0xbd, 0xdd, 0xe6, 0x2e, 0xba, 0xf4, |
|
| 1922 |
+ 0xc4, 0x9f, 0x41, 0x2e, 0xba, 0xe2, 0x78, 0x84, 0xbb, 0x17, 0x8b, 0xc0, 0xb5, 0xa8, 0x0b, 0x3f, |
|
| 1923 |
+ 0x7c, 0x05, 0x4a, 0xfc, 0xaf, 0xac, 0x6d, 0x41, 0xe4, 0x5c, 0xe4, 0x00, 0xaf, 0x2b, 0xde, 0x80, |
|
| 1924 |
+ 0xa2, 0x90, 0x99, 0x45, 0xe3, 0xd6, 0x90, 0xac, 0xf9, 0xc1, 0x58, 0x74, 0x40, 0xc6, 0x4e, 0x68, |
|
| 1925 |
+ 0xbc, 0x24, 0xce, 0x98, 0x0a, 0xc1, 0x94, 0xf4, 0x4a, 0x04, 0xfe, 0x9c, 0x63, 0xf8, 0x3a, 0x94, |
|
| 1926 |
+ 0xa5, 0x2a, 0x6d, 0x66, 0xd1, 0xd7, 0xe2, 0xf6, 0xc9, 0xeb, 0x52, 0xa8, 0x2d, 0x8e, 0xf0, 0x9f, |
|
| 1927 |
+ 0x7f, 0x1e, 0xb8, 0x2c, 0x3e, 0x5a, 0xf1, 0x13, 0x1c, 0x10, 0x3f, 0xff, 0xf1, 0xec, 0xc5, 0x77, |
|
| 1928 |
+ 0x6d, 0xf1, 0xf6, 0x66, 0xb5, 0x58, 0xfb, 0x53, 0x06, 0x72, 0xe2, 0x79, 0x5b, 0x81, 0xf2, 0xf1, |
|
| 1929 |
+ 0x17, 0x5d, 0xcd, 0x68, 0x76, 0xfa, 0xfb, 0x6d, 0x0d, 0x29, 0xb8, 0x0a, 0x20, 0x80, 0x27, 0xed, |
|
| 1930 |
+ 0x4e, 0xfd, 0x18, 0x65, 0x92, 0x75, 0xeb, 0xe8, 0xf8, 0xf1, 0x43, 0x94, 0x4d, 0x1c, 0xfa, 0x12, |
|
| 1931 |
+ 0xc8, 0xa5, 0x09, 0x0f, 0x76, 0x50, 0x1e, 0x23, 0xa8, 0xc8, 0x00, 0xad, 0x67, 0x5a, 0xf3, 0xf1, |
|
| 1932 |
+ 0x43, 0x54, 0x98, 0x46, 0x1e, 0xec, 0xa0, 0x25, 0xbc, 0x0c, 0x25, 0x81, 0xec, 0x77, 0x3a, 0x6d, |
|
| 1933 |
+ 0x54, 0x4c, 0x62, 0xf6, 0x8e, 0xf5, 0xd6, 0xd1, 0x01, 0x2a, 0x25, 0x31, 0x0f, 0xf4, 0x4e, 0xbf, |
|
| 1934 |
+ 0x8b, 0x20, 0x89, 0x70, 0xa8, 0xf5, 0x7a, 0xf5, 0x03, 0x0d, 0x95, 0x13, 0xc6, 0xfe, 0x17, 0xc7, |
|
| 1935 |
+ 0x5a, 0x0f, 0x55, 0xa6, 0xd2, 0x7a, 0xb0, 0x83, 0x96, 0x93, 0x9f, 0xd0, 0x8e, 0xfa, 0x87, 0xa8, |
|
| 1936 |
+ 0x8a, 0x57, 0x61, 0x59, 0xfe, 0x44, 0x9c, 0xc4, 0xca, 0x0c, 0xf4, 0xf8, 0x21, 0x42, 0x93, 0x44, |
|
| 1937 |
+ 0x64, 0x94, 0xd5, 0x29, 0xe0, 0xf1, 0x43, 0x84, 0x6b, 0x0d, 0xc8, 0x0b, 0x75, 0x61, 0x0c, 0xd5, |
|
| 1938 |
+ 0x76, 0x7d, 0x5f, 0x6b, 0x1b, 0x9d, 0xee, 0x71, 0xab, 0x73, 0x54, 0x6f, 0x23, 0x65, 0x82, 0xe9, |
|
| 1939 |
+ 0xda, 0xcf, 0xfa, 0x2d, 0x5d, 0x6b, 0xa2, 0x4c, 0x1a, 0xeb, 0x6a, 0xf5, 0x63, 0xad, 0x89, 0xb2, |
|
| 1940 |
+ 0xb5, 0xbb, 0xb0, 0xbe, 0xe8, 0x9e, 0x59, 0xf4, 0x64, 0xd4, 0xbe, 0x56, 0x60, 0x6d, 0xc1, 0x95, |
|
| 1941 |
+ 0xb9, 0xf0, 0x29, 0xfa, 0x29, 0xe4, 0xa5, 0xd2, 0x64, 0x13, 0xb9, 0xb3, 0xf0, 0xee, 0x15, 0xba, |
|
| 1942 |
+ 0x9b, 0x6b, 0x24, 0xc2, 0x2f, 0xdd, 0x48, 0xb3, 0xe7, 0x34, 0x52, 0x1e, 0x62, 0x4e, 0x4e, 0xbf, |
|
| 1943 |
+ 0x52, 0x40, 0x3d, 0x2f, 0xf6, 0x5b, 0x9e, 0xf7, 0xcc, 0xd4, 0xf3, 0xfe, 0xe9, 0x6c, 0x02, 0x37, |
|
| 1944 |
+ 0xce, 0xdf, 0xc3, 0x5c, 0x16, 0xdf, 0x28, 0x70, 0x69, 0xf1, 0xbc, 0xb1, 0x30, 0x87, 0xcf, 0xa0, |
|
| 1945 |
+ 0x30, 0xa2, 0xe1, 0xa9, 0x1b, 0xf7, 0xdc, 0x0f, 0x17, 0xdc, 0xe4, 0xdc, 0x3c, 0x5b, 0xab, 0xc8, |
|
| 1946 |
+ 0x2b, 0xdd, 0x0a, 0xb2, 0xe7, 0x0d, 0x0d, 0x32, 0x9b, 0xb9, 0x4c, 0x7f, 0x9d, 0x81, 0x77, 0x17, |
|
| 1947 |
+ 0x06, 0x5f, 0x98, 0xe8, 0x35, 0x00, 0x9b, 0x79, 0xe3, 0x50, 0xf6, 0x55, 0x79, 0xcd, 0x94, 0x04, |
|
| 1948 |
+ 0x22, 0x1e, 0x61, 0x7e, 0x85, 0x8c, 0xc3, 0xc4, 0x9e, 0x15, 0x76, 0x90, 0x90, 0x20, 0xec, 0x4e, |
|
| 1949 |
+ 0x12, 0xcd, 0x89, 0x44, 0xdf, 0x3f, 0x67, 0xa7, 0x73, 0x2d, 0xeb, 0x23, 0x40, 0xa6, 0x63, 0x53, |
|
| 1950 |
+ 0x16, 0x1a, 0x41, 0xe8, 0x53, 0x32, 0xb2, 0xd9, 0x50, 0xdc, 0xa3, 0xc5, 0xbd, 0xfc, 0x80, 0x38, |
|
| 1951 |
+ 0x01, 0xd5, 0x57, 0xa4, 0xb9, 0x17, 0x5b, 0xb9, 0x87, 0x68, 0x16, 0x7e, 0xca, 0xa3, 0x30, 0xe5, |
|
| 1952 |
+ 0x21, 0xcd, 0x89, 0x47, 0xed, 0x6f, 0x4b, 0x50, 0x4e, 0x4d, 0x67, 0xf8, 0x06, 0x54, 0x9e, 0x93, |
|
| 1953 |
+ 0x97, 0xc4, 0x88, 0x27, 0x6e, 0x59, 0x89, 0x32, 0xc7, 0xba, 0xd1, 0xd4, 0xfd, 0x11, 0xac, 0x0b, |
|
| 1954 |
+ 0x8a, 0x3b, 0x0e, 0xa9, 0x6f, 0x98, 0x0e, 0x09, 0x02, 0x51, 0xb4, 0xa2, 0xa0, 0x62, 0x6e, 0xeb, |
|
| 1955 |
+ 0x70, 0x53, 0x23, 0xb6, 0xe0, 0x47, 0xb0, 0x26, 0x3c, 0x46, 0x63, 0x27, 0xb4, 0x3d, 0x87, 0x1a, |
|
| 1956 |
+ 0xfc, 0x1d, 0x20, 0x10, 0xf7, 0x69, 0x92, 0xd9, 0x2a, 0x67, 0x1c, 0x46, 0x04, 0x9e, 0x51, 0x80, |
|
| 1957 |
+ 0x0f, 0xe0, 0x9a, 0x70, 0x1b, 0x52, 0x46, 0x7d, 0x12, 0x52, 0x83, 0xfe, 0x72, 0x4c, 0x9c, 0xc0, |
|
| 1958 |
+ 0x20, 0xcc, 0x32, 0x4e, 0x49, 0x70, 0xaa, 0xae, 0xa7, 0x03, 0x5c, 0xe6, 0xdc, 0x83, 0x88, 0xaa, |
|
| 1959 |
+ 0x09, 0x66, 0x9d, 0x59, 0x9f, 0x93, 0xe0, 0x14, 0xef, 0xc1, 0x25, 0x11, 0x28, 0x08, 0x7d, 0x9b, |
|
| 1960 |
+ 0x0d, 0x0d, 0xf3, 0x94, 0x9a, 0x2f, 0x8c, 0x71, 0x38, 0xd8, 0x55, 0xaf, 0xa4, 0x23, 0x88, 0x24, |
|
| 1961 |
+ 0x7b, 0x82, 0xd3, 0xe0, 0x94, 0x7e, 0x38, 0xd8, 0xc5, 0x3d, 0xa8, 0xf0, 0xf3, 0x18, 0xd9, 0x5f, |
|
| 1962 |
+ 0x51, 0x63, 0xe0, 0xfa, 0xa2, 0x47, 0x54, 0x17, 0x3c, 0xdc, 0xa9, 0x22, 0x6e, 0x77, 0x22, 0x87, |
|
| 1963 |
+ 0x43, 0xd7, 0xa2, 0x7b, 0xf9, 0x5e, 0x57, 0xd3, 0x9a, 0x7a, 0x39, 0x8e, 0xf2, 0xc4, 0xf5, 0xb9, |
|
| 1964 |
+ 0xa6, 0x86, 0x6e, 0x52, 0xe3, 0xb2, 0xd4, 0xd4, 0xd0, 0x8d, 0x2b, 0xfc, 0x08, 0xd6, 0x4c, 0x53, |
|
| 1965 |
+ 0x6e, 0xdb, 0x36, 0x8d, 0x68, 0x58, 0x0f, 0x54, 0x34, 0x55, 0x2f, 0xd3, 0x3c, 0x90, 0x84, 0x48, |
|
| 1966 |
+ 0xe6, 0x01, 0xfe, 0x04, 0xde, 0x9d, 0xd4, 0x2b, 0xed, 0xb8, 0x3a, 0xb7, 0xcb, 0x59, 0xd7, 0x47, |
|
| 1967 |
+ 0xb0, 0xe6, 0x9d, 0xcd, 0x3b, 0xe2, 0xa9, 0x5f, 0xf4, 0xce, 0x66, 0xdd, 0x6e, 0x89, 0x17, 0x30, |
|
| 1968 |
+ 0x9f, 0x9a, 0x24, 0xa4, 0x96, 0xfa, 0x5e, 0x9a, 0x9d, 0x32, 0xe0, 0xfb, 0x80, 0x4c, 0xd3, 0xa0, |
|
| 1969 |
+ 0x8c, 0x9c, 0x38, 0xd4, 0x20, 0x3e, 0x65, 0x24, 0x50, 0xaf, 0xa7, 0xc9, 0x55, 0xd3, 0xd4, 0x84, |
|
| 1970 |
+ 0xb5, 0x2e, 0x8c, 0xf8, 0x2e, 0xac, 0xba, 0x27, 0xcf, 0x4d, 0x29, 0x2e, 0xc3, 0xf3, 0xe9, 0xc0, |
|
| 1971 |
+ 0x7e, 0xad, 0xde, 0x14, 0x65, 0x5a, 0xe1, 0x06, 0x21, 0xad, 0xae, 0x80, 0xf1, 0x1d, 0x40, 0x66, |
|
| 1972 |
+ 0x70, 0x4a, 0x7c, 0x4f, 0x34, 0xe9, 0xc0, 0x23, 0x26, 0x55, 0x6f, 0x49, 0xaa, 0xc4, 0x8f, 0x62, |
|
| 1973 |
+ 0x18, 0x6b, 0x70, 0x9d, 0x6f, 0x9e, 0x11, 0xe6, 0x1a, 0xe3, 0x80, 0x1a, 0x93, 0x14, 0x93, 0xb3, |
|
| 1974 |
+ 0xf8, 0x90, 0xa7, 0xa5, 0x5f, 0x8d, 0x69, 0xfd, 0x80, 0x36, 0x13, 0x52, 0x7c, 0x3c, 0xcf, 0x60, |
|
| 1975 |
+ 0x7d, 0xcc, 0x6c, 0x16, 0x52, 0xdf, 0xf3, 0x29, 0x77, 0x96, 0x0f, 0xac, 0xfa, 0xcf, 0xa5, 0x73, |
|
| 1976 |
+ 0x86, 0xee, 0x7e, 0x9a, 0x2d, 0x45, 0xa2, 0xaf, 0x8d, 0xe7, 0xc1, 0xda, 0x1e, 0x54, 0xd2, 0xda, |
|
| 1977 |
+ 0xc1, 0x25, 0x90, 0xea, 0x41, 0x0a, 0xef, 0xa8, 0x8d, 0x4e, 0x93, 0xf7, 0xc2, 0x2f, 0x35, 0x94, |
|
| 1978 |
+ 0xe1, 0x3d, 0xb9, 0xdd, 0x3a, 0xd6, 0x0c, 0xbd, 0x7f, 0x74, 0xdc, 0x3a, 0xd4, 0x50, 0xf6, 0x6e, |
|
| 1979 |
+ 0xa9, 0xf8, 0xaf, 0x25, 0xf4, 0xe6, 0xcd, 0x9b, 0x37, 0x99, 0xda, 0x5f, 0x32, 0x50, 0x9d, 0x9e, |
|
| 1980 |
+ 0x83, 0xf1, 0x4f, 0xe0, 0xbd, 0xf8, 0xa5, 0x35, 0xa0, 0xa1, 0xf1, 0xca, 0xf6, 0x85, 0x9c, 0x47, |
|
| 1981 |
+ 0x44, 0x4e, 0x92, 0xc9, 0x49, 0xac, 0x47, 0xac, 0x1e, 0x0d, 0x7f, 0x61, 0xfb, 0x5c, 0xac, 0x23, |
|
| 1982 |
+ 0x12, 0xe2, 0x36, 0x5c, 0x67, 0xae, 0x11, 0x84, 0x84, 0x59, 0xc4, 0xb7, 0x8c, 0xc9, 0xe7, 0x02, |
|
| 1983 |
+ 0x83, 0x98, 0x26, 0x0d, 0x02, 0x57, 0x76, 0x92, 0x24, 0xca, 0x55, 0xe6, 0xf6, 0x22, 0xf2, 0xe4, |
|
| 1984 |
+ 0x8a, 0xad, 0x47, 0xd4, 0x19, 0xd5, 0x64, 0xcf, 0x53, 0xcd, 0x15, 0x28, 0x8d, 0x88, 0x67, 0x50, |
|
| 1985 |
+ 0x16, 0xfa, 0x67, 0x62, 0x7a, 0x2b, 0xea, 0xc5, 0x11, 0xf1, 0x34, 0xbe, 0xfe, 0xfe, 0xce, 0x20, |
|
| 1986 |
+ 0x5d, 0xc7, 0xbf, 0x67, 0xa1, 0x92, 0x9e, 0xe0, 0xf8, 0x40, 0x6c, 0x8a, 0x6b, 0x5e, 0x11, 0xb7, |
|
| 1987 |
+ 0xc0, 0x07, 0xdf, 0x3a, 0xef, 0x6d, 0x37, 0xf8, 0xfd, 0xbf, 0x57, 0x90, 0x73, 0x95, 0x2e, 0x3d, |
|
| 1988 |
+ 0x79, 0xef, 0xe5, 0x5a, 0xa3, 0x72, 0x5a, 0x2f, 0xea, 0xd1, 0x0a, 0x1f, 0x40, 0xe1, 0x79, 0x20, |
|
| 1989 |
+ 0x62, 0x17, 0x44, 0xec, 0x9b, 0xdf, 0x1e, 0xfb, 0x69, 0x4f, 0x04, 0x2f, 0x3d, 0xed, 0x19, 0x47, |
|
| 1990 |
+ 0x1d, 0xfd, 0xb0, 0xde, 0xd6, 0x23, 0x77, 0x7c, 0x19, 0x72, 0x0e, 0xf9, 0xea, 0x6c, 0xba, 0x53, |
|
| 1991 |
+ 0x08, 0xe8, 0xa2, 0x85, 0xbf, 0x0c, 0xb9, 0x57, 0x94, 0xbc, 0x98, 0xbe, 0x9f, 0x05, 0xf4, 0x3d, |
|
| 1992 |
+ 0x4a, 0xff, 0x3e, 0xe4, 0x45, 0xbd, 0x30, 0x40, 0x54, 0x31, 0xf4, 0x0e, 0x2e, 0x42, 0xae, 0xd1, |
|
| 1993 |
+ 0xd1, 0xb9, 0xfc, 0x11, 0x54, 0x24, 0x6a, 0x74, 0x5b, 0x5a, 0x43, 0x43, 0x99, 0xda, 0x23, 0x28, |
|
| 1994 |
+ 0xc8, 0x22, 0xf0, 0x47, 0x23, 0x29, 0x03, 0x7a, 0x27, 0x5a, 0x46, 0x31, 0x94, 0xd8, 0xda, 0x3f, |
|
| 1995 |
+ 0xdc, 0xd7, 0x74, 0x94, 0x49, 0x1f, 0xef, 0x9f, 0x15, 0x28, 0xa7, 0x06, 0x2a, 0xde, 0xca, 0x89, |
|
| 1996 |
+ 0xe3, 0xb8, 0xaf, 0x0c, 0xe2, 0xd8, 0x24, 0x88, 0xce, 0x07, 0x04, 0x54, 0xe7, 0xc8, 0x45, 0xeb, |
|
| 1997 |
+ 0xf7, 0x3f, 0xd1, 0xe6, 0x1f, 0x14, 0x40, 0xb3, 0xc3, 0xd8, 0x4c, 0x82, 0xca, 0x0f, 0x9a, 0xe0, |
|
| 1998 |
+ 0xef, 0x15, 0xa8, 0x4e, 0x4f, 0x60, 0x33, 0xe9, 0xdd, 0xf8, 0x41, 0xd3, 0xfb, 0x9d, 0x02, 0xcb, |
|
| 1999 |
+ 0x53, 0x73, 0xd7, 0xff, 0x55, 0x76, 0xbf, 0xcd, 0xc2, 0xda, 0x02, 0x3f, 0x5c, 0x8f, 0x06, 0x54, |
|
| 2000 |
+ 0x39, 0x33, 0xff, 0xf8, 0x22, 0xbf, 0xb5, 0xcd, 0xfb, 0x5f, 0x97, 0xf8, 0x61, 0x34, 0xcf, 0xde, |
|
| 2001 |
+ 0x01, 0x64, 0x5b, 0x94, 0x85, 0xf6, 0xc0, 0xa6, 0x7e, 0xf4, 0x6e, 0x2c, 0xa7, 0xd6, 0x95, 0x09, |
|
| 2002 |
+ 0x2e, 0x5f, 0x8f, 0x7f, 0x04, 0xd8, 0x73, 0x03, 0x3b, 0xb4, 0x5f, 0x52, 0xc3, 0x66, 0xf1, 0x8b, |
|
| 2003 |
+ 0x34, 0x9f, 0x62, 0x73, 0x3a, 0x8a, 0x2d, 0x2d, 0x16, 0x26, 0x6c, 0x46, 0x87, 0x64, 0x86, 0xcd, |
|
| 2004 |
+ 0xaf, 0xa1, 0xac, 0x8e, 0x62, 0x4b, 0xc2, 0xbe, 0x01, 0x15, 0xcb, 0x1d, 0xf3, 0x81, 0x40, 0xf2, |
|
| 2005 |
+ 0xf8, 0xad, 0xa7, 0xe8, 0x65, 0x89, 0x25, 0x94, 0x68, 0x62, 0x9b, 0xbc, 0xc1, 0x57, 0xf4, 0xb2, |
|
| 2006 |
+ 0xc4, 0x24, 0xe5, 0x36, 0xac, 0x90, 0xe1, 0xd0, 0xe7, 0xc1, 0xe3, 0x40, 0x72, 0x0c, 0xad, 0x26, |
|
| 2007 |
+ 0xb0, 0x20, 0x6e, 0x3c, 0x85, 0x62, 0x5c, 0x07, 0xde, 0x58, 0x78, 0x25, 0x0c, 0x4f, 0x7e, 0x47, |
|
| 2008 |
+ 0xc9, 0xf0, 0x97, 0x7a, 0x16, 0x1b, 0x6f, 0x40, 0xc5, 0x0e, 0x8c, 0xc9, 0x07, 0xbd, 0xcc, 0x66, |
|
| 2009 |
+ 0x66, 0xab, 0xa8, 0x97, 0xed, 0x20, 0xf9, 0x82, 0x53, 0xfb, 0x26, 0x03, 0xd5, 0xe9, 0x0f, 0x92, |
|
| 2010 |
+ 0xb8, 0x09, 0x45, 0xc7, 0x35, 0x89, 0x10, 0x82, 0xfc, 0x1a, 0xbe, 0xf5, 0x96, 0x6f, 0x98, 0xdb, |
|
| 2011 |
+ 0xed, 0x88, 0xaf, 0x27, 0x9e, 0x1b, 0x7f, 0x55, 0xa0, 0x18, 0xc3, 0xf8, 0x12, 0xe4, 0x3c, 0x12, |
|
| 2012 |
+ 0x9e, 0x8a, 0x70, 0xf9, 0xfd, 0x0c, 0x52, 0x74, 0xb1, 0xe6, 0x78, 0xe0, 0x11, 0x26, 0x24, 0x10, |
|
| 2013 |
+ 0xe1, 0x7c, 0xcd, 0xcf, 0xd5, 0xa1, 0xc4, 0x12, 0x03, 0xae, 0x3b, 0x1a, 0x51, 0x16, 0x06, 0xf1, |
|
| 2014 |
+ 0xb9, 0x46, 0x78, 0x23, 0x82, 0xf1, 0x3d, 0x58, 0x0d, 0x7d, 0x62, 0x3b, 0x53, 0xdc, 0x9c, 0xe0, |
|
| 2015 |
+ 0xa2, 0xd8, 0x90, 0x90, 0xf7, 0xe0, 0x72, 0x1c, 0xd7, 0xa2, 0x21, 0x31, 0x4f, 0xa9, 0x35, 0x71, |
|
| 2016 |
+ 0x2a, 0x88, 0xaf, 0x5d, 0xef, 0x45, 0x84, 0x66, 0x64, 0x8f, 0x7d, 0xf7, 0x9f, 0xc1, 0x9a, 0xe9, |
|
| 2017 |
+ 0x8e, 0x66, 0x2b, 0xb1, 0x8f, 0x66, 0xde, 0xbb, 0x82, 0xcf, 0x95, 0x2f, 0x61, 0x32, 0x54, 0x7c, |
|
| 2018 |
+ 0x9d, 0xc9, 0x1e, 0x74, 0xf7, 0xff, 0x98, 0xd9, 0x38, 0x90, 0x7e, 0xdd, 0xb8, 0x82, 0x3a, 0x1d, |
|
| 2019 |
+ 0x38, 0xd4, 0xe4, 0xd5, 0xf9, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x42, 0x69, 0x71, 0xb3, |
|
| 2020 |
+ 0x18, 0x00, 0x00, |
|
| 2017 | 2021 |
} |
| 2018 | 2022 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,658 @@ |
| 0 |
+// Code generated by protoc-gen-gogo. |
|
| 1 |
+// source: descriptor.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+Package descriptor is a generated protocol buffer package. |
|
| 6 |
+ |
|
| 7 |
+It is generated from these files: |
|
| 8 |
+ descriptor.proto |
|
| 9 |
+ |
|
| 10 |
+It has these top-level messages: |
|
| 11 |
+ FileDescriptorSet |
|
| 12 |
+ FileDescriptorProto |
|
| 13 |
+ DescriptorProto |
|
| 14 |
+ FieldDescriptorProto |
|
| 15 |
+ OneofDescriptorProto |
|
| 16 |
+ EnumDescriptorProto |
|
| 17 |
+ EnumValueDescriptorProto |
|
| 18 |
+ ServiceDescriptorProto |
|
| 19 |
+ MethodDescriptorProto |
|
| 20 |
+ FileOptions |
|
| 21 |
+ MessageOptions |
|
| 22 |
+ FieldOptions |
|
| 23 |
+ EnumOptions |
|
| 24 |
+ EnumValueOptions |
|
| 25 |
+ ServiceOptions |
|
| 26 |
+ MethodOptions |
|
| 27 |
+ UninterpretedOption |
|
| 28 |
+ SourceCodeInfo |
|
| 29 |
+*/ |
|
| 30 |
+package descriptor |
|
| 31 |
+ |
|
| 32 |
+import fmt "fmt" |
|
| 33 |
+import strings "strings" |
|
| 34 |
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 35 |
+import sort "sort" |
|
| 36 |
+import strconv "strconv" |
|
| 37 |
+import reflect "reflect" |
|
| 38 |
+import proto "github.com/gogo/protobuf/proto" |
|
| 39 |
+import math "math" |
|
| 40 |
+ |
|
| 41 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 42 |
+var _ = proto.Marshal |
|
| 43 |
+var _ = fmt.Errorf |
|
| 44 |
+var _ = math.Inf |
|
| 45 |
+ |
|
| 46 |
+func (this *FileDescriptorSet) GoString() string {
|
|
| 47 |
+ if this == nil {
|
|
| 48 |
+ return "nil" |
|
| 49 |
+ } |
|
| 50 |
+ s := make([]string, 0, 5) |
|
| 51 |
+ s = append(s, "&descriptor.FileDescriptorSet{")
|
|
| 52 |
+ if this.File != nil {
|
|
| 53 |
+ s = append(s, "File: "+fmt.Sprintf("%#v", this.File)+",\n")
|
|
| 54 |
+ } |
|
| 55 |
+ if this.XXX_unrecognized != nil {
|
|
| 56 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 57 |
+ } |
|
| 58 |
+ s = append(s, "}") |
|
| 59 |
+ return strings.Join(s, "") |
|
| 60 |
+} |
|
| 61 |
+func (this *FileDescriptorProto) GoString() string {
|
|
| 62 |
+ if this == nil {
|
|
| 63 |
+ return "nil" |
|
| 64 |
+ } |
|
| 65 |
+ s := make([]string, 0, 16) |
|
| 66 |
+ s = append(s, "&descriptor.FileDescriptorProto{")
|
|
| 67 |
+ if this.Name != nil {
|
|
| 68 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 69 |
+ } |
|
| 70 |
+ if this.Package != nil {
|
|
| 71 |
+ s = append(s, "Package: "+valueToGoStringDescriptor(this.Package, "string")+",\n") |
|
| 72 |
+ } |
|
| 73 |
+ if this.Dependency != nil {
|
|
| 74 |
+ s = append(s, "Dependency: "+fmt.Sprintf("%#v", this.Dependency)+",\n")
|
|
| 75 |
+ } |
|
| 76 |
+ if this.PublicDependency != nil {
|
|
| 77 |
+ s = append(s, "PublicDependency: "+fmt.Sprintf("%#v", this.PublicDependency)+",\n")
|
|
| 78 |
+ } |
|
| 79 |
+ if this.WeakDependency != nil {
|
|
| 80 |
+ s = append(s, "WeakDependency: "+fmt.Sprintf("%#v", this.WeakDependency)+",\n")
|
|
| 81 |
+ } |
|
| 82 |
+ if this.MessageType != nil {
|
|
| 83 |
+ s = append(s, "MessageType: "+fmt.Sprintf("%#v", this.MessageType)+",\n")
|
|
| 84 |
+ } |
|
| 85 |
+ if this.EnumType != nil {
|
|
| 86 |
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
|
|
| 87 |
+ } |
|
| 88 |
+ if this.Service != nil {
|
|
| 89 |
+ s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
|
|
| 90 |
+ } |
|
| 91 |
+ if this.Extension != nil {
|
|
| 92 |
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
|
|
| 93 |
+ } |
|
| 94 |
+ if this.Options != nil {
|
|
| 95 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 96 |
+ } |
|
| 97 |
+ if this.SourceCodeInfo != nil {
|
|
| 98 |
+ s = append(s, "SourceCodeInfo: "+fmt.Sprintf("%#v", this.SourceCodeInfo)+",\n")
|
|
| 99 |
+ } |
|
| 100 |
+ if this.Syntax != nil {
|
|
| 101 |
+ s = append(s, "Syntax: "+valueToGoStringDescriptor(this.Syntax, "string")+",\n") |
|
| 102 |
+ } |
|
| 103 |
+ if this.XXX_unrecognized != nil {
|
|
| 104 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 105 |
+ } |
|
| 106 |
+ s = append(s, "}") |
|
| 107 |
+ return strings.Join(s, "") |
|
| 108 |
+} |
|
| 109 |
+func (this *DescriptorProto) GoString() string {
|
|
| 110 |
+ if this == nil {
|
|
| 111 |
+ return "nil" |
|
| 112 |
+ } |
|
| 113 |
+ s := make([]string, 0, 14) |
|
| 114 |
+ s = append(s, "&descriptor.DescriptorProto{")
|
|
| 115 |
+ if this.Name != nil {
|
|
| 116 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 117 |
+ } |
|
| 118 |
+ if this.Field != nil {
|
|
| 119 |
+ s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n")
|
|
| 120 |
+ } |
|
| 121 |
+ if this.Extension != nil {
|
|
| 122 |
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
|
|
| 123 |
+ } |
|
| 124 |
+ if this.NestedType != nil {
|
|
| 125 |
+ s = append(s, "NestedType: "+fmt.Sprintf("%#v", this.NestedType)+",\n")
|
|
| 126 |
+ } |
|
| 127 |
+ if this.EnumType != nil {
|
|
| 128 |
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
|
|
| 129 |
+ } |
|
| 130 |
+ if this.ExtensionRange != nil {
|
|
| 131 |
+ s = append(s, "ExtensionRange: "+fmt.Sprintf("%#v", this.ExtensionRange)+",\n")
|
|
| 132 |
+ } |
|
| 133 |
+ if this.OneofDecl != nil {
|
|
| 134 |
+ s = append(s, "OneofDecl: "+fmt.Sprintf("%#v", this.OneofDecl)+",\n")
|
|
| 135 |
+ } |
|
| 136 |
+ if this.Options != nil {
|
|
| 137 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 138 |
+ } |
|
| 139 |
+ if this.ReservedRange != nil {
|
|
| 140 |
+ s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
|
|
| 141 |
+ } |
|
| 142 |
+ if this.ReservedName != nil {
|
|
| 143 |
+ s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
|
|
| 144 |
+ } |
|
| 145 |
+ if this.XXX_unrecognized != nil {
|
|
| 146 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 147 |
+ } |
|
| 148 |
+ s = append(s, "}") |
|
| 149 |
+ return strings.Join(s, "") |
|
| 150 |
+} |
|
| 151 |
+func (this *DescriptorProto_ExtensionRange) GoString() string {
|
|
| 152 |
+ if this == nil {
|
|
| 153 |
+ return "nil" |
|
| 154 |
+ } |
|
| 155 |
+ s := make([]string, 0, 6) |
|
| 156 |
+ s = append(s, "&descriptor.DescriptorProto_ExtensionRange{")
|
|
| 157 |
+ if this.Start != nil {
|
|
| 158 |
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n") |
|
| 159 |
+ } |
|
| 160 |
+ if this.End != nil {
|
|
| 161 |
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n") |
|
| 162 |
+ } |
|
| 163 |
+ if this.XXX_unrecognized != nil {
|
|
| 164 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 165 |
+ } |
|
| 166 |
+ s = append(s, "}") |
|
| 167 |
+ return strings.Join(s, "") |
|
| 168 |
+} |
|
| 169 |
+func (this *DescriptorProto_ReservedRange) GoString() string {
|
|
| 170 |
+ if this == nil {
|
|
| 171 |
+ return "nil" |
|
| 172 |
+ } |
|
| 173 |
+ s := make([]string, 0, 6) |
|
| 174 |
+ s = append(s, "&descriptor.DescriptorProto_ReservedRange{")
|
|
| 175 |
+ if this.Start != nil {
|
|
| 176 |
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n") |
|
| 177 |
+ } |
|
| 178 |
+ if this.End != nil {
|
|
| 179 |
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n") |
|
| 180 |
+ } |
|
| 181 |
+ if this.XXX_unrecognized != nil {
|
|
| 182 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 183 |
+ } |
|
| 184 |
+ s = append(s, "}") |
|
| 185 |
+ return strings.Join(s, "") |
|
| 186 |
+} |
|
| 187 |
+func (this *FieldDescriptorProto) GoString() string {
|
|
| 188 |
+ if this == nil {
|
|
| 189 |
+ return "nil" |
|
| 190 |
+ } |
|
| 191 |
+ s := make([]string, 0, 14) |
|
| 192 |
+ s = append(s, "&descriptor.FieldDescriptorProto{")
|
|
| 193 |
+ if this.Name != nil {
|
|
| 194 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 195 |
+ } |
|
| 196 |
+ if this.Number != nil {
|
|
| 197 |
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n") |
|
| 198 |
+ } |
|
| 199 |
+ if this.Label != nil {
|
|
| 200 |
+ s = append(s, "Label: "+valueToGoStringDescriptor(this.Label, "descriptor.FieldDescriptorProto_Label")+",\n") |
|
| 201 |
+ } |
|
| 202 |
+ if this.Type != nil {
|
|
| 203 |
+ s = append(s, "Type: "+valueToGoStringDescriptor(this.Type, "descriptor.FieldDescriptorProto_Type")+",\n") |
|
| 204 |
+ } |
|
| 205 |
+ if this.TypeName != nil {
|
|
| 206 |
+ s = append(s, "TypeName: "+valueToGoStringDescriptor(this.TypeName, "string")+",\n") |
|
| 207 |
+ } |
|
| 208 |
+ if this.Extendee != nil {
|
|
| 209 |
+ s = append(s, "Extendee: "+valueToGoStringDescriptor(this.Extendee, "string")+",\n") |
|
| 210 |
+ } |
|
| 211 |
+ if this.DefaultValue != nil {
|
|
| 212 |
+ s = append(s, "DefaultValue: "+valueToGoStringDescriptor(this.DefaultValue, "string")+",\n") |
|
| 213 |
+ } |
|
| 214 |
+ if this.OneofIndex != nil {
|
|
| 215 |
+ s = append(s, "OneofIndex: "+valueToGoStringDescriptor(this.OneofIndex, "int32")+",\n") |
|
| 216 |
+ } |
|
| 217 |
+ if this.JsonName != nil {
|
|
| 218 |
+ s = append(s, "JsonName: "+valueToGoStringDescriptor(this.JsonName, "string")+",\n") |
|
| 219 |
+ } |
|
| 220 |
+ if this.Options != nil {
|
|
| 221 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 222 |
+ } |
|
| 223 |
+ if this.XXX_unrecognized != nil {
|
|
| 224 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 225 |
+ } |
|
| 226 |
+ s = append(s, "}") |
|
| 227 |
+ return strings.Join(s, "") |
|
| 228 |
+} |
|
| 229 |
+func (this *OneofDescriptorProto) GoString() string {
|
|
| 230 |
+ if this == nil {
|
|
| 231 |
+ return "nil" |
|
| 232 |
+ } |
|
| 233 |
+ s := make([]string, 0, 5) |
|
| 234 |
+ s = append(s, "&descriptor.OneofDescriptorProto{")
|
|
| 235 |
+ if this.Name != nil {
|
|
| 236 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 237 |
+ } |
|
| 238 |
+ if this.XXX_unrecognized != nil {
|
|
| 239 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 240 |
+ } |
|
| 241 |
+ s = append(s, "}") |
|
| 242 |
+ return strings.Join(s, "") |
|
| 243 |
+} |
|
| 244 |
+func (this *EnumDescriptorProto) GoString() string {
|
|
| 245 |
+ if this == nil {
|
|
| 246 |
+ return "nil" |
|
| 247 |
+ } |
|
| 248 |
+ s := make([]string, 0, 7) |
|
| 249 |
+ s = append(s, "&descriptor.EnumDescriptorProto{")
|
|
| 250 |
+ if this.Name != nil {
|
|
| 251 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 252 |
+ } |
|
| 253 |
+ if this.Value != nil {
|
|
| 254 |
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
|
|
| 255 |
+ } |
|
| 256 |
+ if this.Options != nil {
|
|
| 257 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 258 |
+ } |
|
| 259 |
+ if this.XXX_unrecognized != nil {
|
|
| 260 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 261 |
+ } |
|
| 262 |
+ s = append(s, "}") |
|
| 263 |
+ return strings.Join(s, "") |
|
| 264 |
+} |
|
| 265 |
+func (this *EnumValueDescriptorProto) GoString() string {
|
|
| 266 |
+ if this == nil {
|
|
| 267 |
+ return "nil" |
|
| 268 |
+ } |
|
| 269 |
+ s := make([]string, 0, 7) |
|
| 270 |
+ s = append(s, "&descriptor.EnumValueDescriptorProto{")
|
|
| 271 |
+ if this.Name != nil {
|
|
| 272 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 273 |
+ } |
|
| 274 |
+ if this.Number != nil {
|
|
| 275 |
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n") |
|
| 276 |
+ } |
|
| 277 |
+ if this.Options != nil {
|
|
| 278 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 279 |
+ } |
|
| 280 |
+ if this.XXX_unrecognized != nil {
|
|
| 281 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 282 |
+ } |
|
| 283 |
+ s = append(s, "}") |
|
| 284 |
+ return strings.Join(s, "") |
|
| 285 |
+} |
|
| 286 |
+func (this *ServiceDescriptorProto) GoString() string {
|
|
| 287 |
+ if this == nil {
|
|
| 288 |
+ return "nil" |
|
| 289 |
+ } |
|
| 290 |
+ s := make([]string, 0, 7) |
|
| 291 |
+ s = append(s, "&descriptor.ServiceDescriptorProto{")
|
|
| 292 |
+ if this.Name != nil {
|
|
| 293 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 294 |
+ } |
|
| 295 |
+ if this.Method != nil {
|
|
| 296 |
+ s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
|
|
| 297 |
+ } |
|
| 298 |
+ if this.Options != nil {
|
|
| 299 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 300 |
+ } |
|
| 301 |
+ if this.XXX_unrecognized != nil {
|
|
| 302 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 303 |
+ } |
|
| 304 |
+ s = append(s, "}") |
|
| 305 |
+ return strings.Join(s, "") |
|
| 306 |
+} |
|
| 307 |
+func (this *MethodDescriptorProto) GoString() string {
|
|
| 308 |
+ if this == nil {
|
|
| 309 |
+ return "nil" |
|
| 310 |
+ } |
|
| 311 |
+ s := make([]string, 0, 10) |
|
| 312 |
+ s = append(s, "&descriptor.MethodDescriptorProto{")
|
|
| 313 |
+ if this.Name != nil {
|
|
| 314 |
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 315 |
+ } |
|
| 316 |
+ if this.InputType != nil {
|
|
| 317 |
+ s = append(s, "InputType: "+valueToGoStringDescriptor(this.InputType, "string")+",\n") |
|
| 318 |
+ } |
|
| 319 |
+ if this.OutputType != nil {
|
|
| 320 |
+ s = append(s, "OutputType: "+valueToGoStringDescriptor(this.OutputType, "string")+",\n") |
|
| 321 |
+ } |
|
| 322 |
+ if this.Options != nil {
|
|
| 323 |
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 324 |
+ } |
|
| 325 |
+ if this.ClientStreaming != nil {
|
|
| 326 |
+ s = append(s, "ClientStreaming: "+valueToGoStringDescriptor(this.ClientStreaming, "bool")+",\n") |
|
| 327 |
+ } |
|
| 328 |
+ if this.ServerStreaming != nil {
|
|
| 329 |
+ s = append(s, "ServerStreaming: "+valueToGoStringDescriptor(this.ServerStreaming, "bool")+",\n") |
|
| 330 |
+ } |
|
| 331 |
+ if this.XXX_unrecognized != nil {
|
|
| 332 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 333 |
+ } |
|
| 334 |
+ s = append(s, "}") |
|
| 335 |
+ return strings.Join(s, "") |
|
| 336 |
+} |
|
| 337 |
+func (this *FileOptions) GoString() string {
|
|
| 338 |
+ if this == nil {
|
|
| 339 |
+ return "nil" |
|
| 340 |
+ } |
|
| 341 |
+ s := make([]string, 0, 20) |
|
| 342 |
+ s = append(s, "&descriptor.FileOptions{")
|
|
| 343 |
+ if this.JavaPackage != nil {
|
|
| 344 |
+ s = append(s, "JavaPackage: "+valueToGoStringDescriptor(this.JavaPackage, "string")+",\n") |
|
| 345 |
+ } |
|
| 346 |
+ if this.JavaOuterClassname != nil {
|
|
| 347 |
+ s = append(s, "JavaOuterClassname: "+valueToGoStringDescriptor(this.JavaOuterClassname, "string")+",\n") |
|
| 348 |
+ } |
|
| 349 |
+ if this.JavaMultipleFiles != nil {
|
|
| 350 |
+ s = append(s, "JavaMultipleFiles: "+valueToGoStringDescriptor(this.JavaMultipleFiles, "bool")+",\n") |
|
| 351 |
+ } |
|
| 352 |
+ if this.JavaGenerateEqualsAndHash != nil {
|
|
| 353 |
+ s = append(s, "JavaGenerateEqualsAndHash: "+valueToGoStringDescriptor(this.JavaGenerateEqualsAndHash, "bool")+",\n") |
|
| 354 |
+ } |
|
| 355 |
+ if this.JavaStringCheckUtf8 != nil {
|
|
| 356 |
+ s = append(s, "JavaStringCheckUtf8: "+valueToGoStringDescriptor(this.JavaStringCheckUtf8, "bool")+",\n") |
|
| 357 |
+ } |
|
| 358 |
+ if this.OptimizeFor != nil {
|
|
| 359 |
+ s = append(s, "OptimizeFor: "+valueToGoStringDescriptor(this.OptimizeFor, "descriptor.FileOptions_OptimizeMode")+",\n") |
|
| 360 |
+ } |
|
| 361 |
+ if this.GoPackage != nil {
|
|
| 362 |
+ s = append(s, "GoPackage: "+valueToGoStringDescriptor(this.GoPackage, "string")+",\n") |
|
| 363 |
+ } |
|
| 364 |
+ if this.CcGenericServices != nil {
|
|
| 365 |
+ s = append(s, "CcGenericServices: "+valueToGoStringDescriptor(this.CcGenericServices, "bool")+",\n") |
|
| 366 |
+ } |
|
| 367 |
+ if this.JavaGenericServices != nil {
|
|
| 368 |
+ s = append(s, "JavaGenericServices: "+valueToGoStringDescriptor(this.JavaGenericServices, "bool")+",\n") |
|
| 369 |
+ } |
|
| 370 |
+ if this.PyGenericServices != nil {
|
|
| 371 |
+ s = append(s, "PyGenericServices: "+valueToGoStringDescriptor(this.PyGenericServices, "bool")+",\n") |
|
| 372 |
+ } |
|
| 373 |
+ if this.Deprecated != nil {
|
|
| 374 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 375 |
+ } |
|
| 376 |
+ if this.CcEnableArenas != nil {
|
|
| 377 |
+ s = append(s, "CcEnableArenas: "+valueToGoStringDescriptor(this.CcEnableArenas, "bool")+",\n") |
|
| 378 |
+ } |
|
| 379 |
+ if this.ObjcClassPrefix != nil {
|
|
| 380 |
+ s = append(s, "ObjcClassPrefix: "+valueToGoStringDescriptor(this.ObjcClassPrefix, "string")+",\n") |
|
| 381 |
+ } |
|
| 382 |
+ if this.CsharpNamespace != nil {
|
|
| 383 |
+ s = append(s, "CsharpNamespace: "+valueToGoStringDescriptor(this.CsharpNamespace, "string")+",\n") |
|
| 384 |
+ } |
|
| 385 |
+ if this.JavananoUseDeprecatedPackage != nil {
|
|
| 386 |
+ s = append(s, "JavananoUseDeprecatedPackage: "+valueToGoStringDescriptor(this.JavananoUseDeprecatedPackage, "bool")+",\n") |
|
| 387 |
+ } |
|
| 388 |
+ if this.UninterpretedOption != nil {
|
|
| 389 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 390 |
+ } |
|
| 391 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 392 |
+ if this.XXX_unrecognized != nil {
|
|
| 393 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 394 |
+ } |
|
| 395 |
+ s = append(s, "}") |
|
| 396 |
+ return strings.Join(s, "") |
|
| 397 |
+} |
|
| 398 |
+func (this *MessageOptions) GoString() string {
|
|
| 399 |
+ if this == nil {
|
|
| 400 |
+ return "nil" |
|
| 401 |
+ } |
|
| 402 |
+ s := make([]string, 0, 9) |
|
| 403 |
+ s = append(s, "&descriptor.MessageOptions{")
|
|
| 404 |
+ if this.MessageSetWireFormat != nil {
|
|
| 405 |
+ s = append(s, "MessageSetWireFormat: "+valueToGoStringDescriptor(this.MessageSetWireFormat, "bool")+",\n") |
|
| 406 |
+ } |
|
| 407 |
+ if this.NoStandardDescriptorAccessor != nil {
|
|
| 408 |
+ s = append(s, "NoStandardDescriptorAccessor: "+valueToGoStringDescriptor(this.NoStandardDescriptorAccessor, "bool")+",\n") |
|
| 409 |
+ } |
|
| 410 |
+ if this.Deprecated != nil {
|
|
| 411 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 412 |
+ } |
|
| 413 |
+ if this.MapEntry != nil {
|
|
| 414 |
+ s = append(s, "MapEntry: "+valueToGoStringDescriptor(this.MapEntry, "bool")+",\n") |
|
| 415 |
+ } |
|
| 416 |
+ if this.UninterpretedOption != nil {
|
|
| 417 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 418 |
+ } |
|
| 419 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 420 |
+ if this.XXX_unrecognized != nil {
|
|
| 421 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 422 |
+ } |
|
| 423 |
+ s = append(s, "}") |
|
| 424 |
+ return strings.Join(s, "") |
|
| 425 |
+} |
|
| 426 |
+func (this *FieldOptions) GoString() string {
|
|
| 427 |
+ if this == nil {
|
|
| 428 |
+ return "nil" |
|
| 429 |
+ } |
|
| 430 |
+ s := make([]string, 0, 11) |
|
| 431 |
+ s = append(s, "&descriptor.FieldOptions{")
|
|
| 432 |
+ if this.Ctype != nil {
|
|
| 433 |
+ s = append(s, "Ctype: "+valueToGoStringDescriptor(this.Ctype, "descriptor.FieldOptions_CType")+",\n") |
|
| 434 |
+ } |
|
| 435 |
+ if this.Packed != nil {
|
|
| 436 |
+ s = append(s, "Packed: "+valueToGoStringDescriptor(this.Packed, "bool")+",\n") |
|
| 437 |
+ } |
|
| 438 |
+ if this.Jstype != nil {
|
|
| 439 |
+ s = append(s, "Jstype: "+valueToGoStringDescriptor(this.Jstype, "descriptor.FieldOptions_JSType")+",\n") |
|
| 440 |
+ } |
|
| 441 |
+ if this.Lazy != nil {
|
|
| 442 |
+ s = append(s, "Lazy: "+valueToGoStringDescriptor(this.Lazy, "bool")+",\n") |
|
| 443 |
+ } |
|
| 444 |
+ if this.Deprecated != nil {
|
|
| 445 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 446 |
+ } |
|
| 447 |
+ if this.Weak != nil {
|
|
| 448 |
+ s = append(s, "Weak: "+valueToGoStringDescriptor(this.Weak, "bool")+",\n") |
|
| 449 |
+ } |
|
| 450 |
+ if this.UninterpretedOption != nil {
|
|
| 451 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 452 |
+ } |
|
| 453 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 454 |
+ if this.XXX_unrecognized != nil {
|
|
| 455 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 456 |
+ } |
|
| 457 |
+ s = append(s, "}") |
|
| 458 |
+ return strings.Join(s, "") |
|
| 459 |
+} |
|
| 460 |
+func (this *EnumOptions) GoString() string {
|
|
| 461 |
+ if this == nil {
|
|
| 462 |
+ return "nil" |
|
| 463 |
+ } |
|
| 464 |
+ s := make([]string, 0, 7) |
|
| 465 |
+ s = append(s, "&descriptor.EnumOptions{")
|
|
| 466 |
+ if this.AllowAlias != nil {
|
|
| 467 |
+ s = append(s, "AllowAlias: "+valueToGoStringDescriptor(this.AllowAlias, "bool")+",\n") |
|
| 468 |
+ } |
|
| 469 |
+ if this.Deprecated != nil {
|
|
| 470 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 471 |
+ } |
|
| 472 |
+ if this.UninterpretedOption != nil {
|
|
| 473 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 474 |
+ } |
|
| 475 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 476 |
+ if this.XXX_unrecognized != nil {
|
|
| 477 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 478 |
+ } |
|
| 479 |
+ s = append(s, "}") |
|
| 480 |
+ return strings.Join(s, "") |
|
| 481 |
+} |
|
| 482 |
+func (this *EnumValueOptions) GoString() string {
|
|
| 483 |
+ if this == nil {
|
|
| 484 |
+ return "nil" |
|
| 485 |
+ } |
|
| 486 |
+ s := make([]string, 0, 6) |
|
| 487 |
+ s = append(s, "&descriptor.EnumValueOptions{")
|
|
| 488 |
+ if this.Deprecated != nil {
|
|
| 489 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 490 |
+ } |
|
| 491 |
+ if this.UninterpretedOption != nil {
|
|
| 492 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 493 |
+ } |
|
| 494 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 495 |
+ if this.XXX_unrecognized != nil {
|
|
| 496 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 497 |
+ } |
|
| 498 |
+ s = append(s, "}") |
|
| 499 |
+ return strings.Join(s, "") |
|
| 500 |
+} |
|
| 501 |
+func (this *ServiceOptions) GoString() string {
|
|
| 502 |
+ if this == nil {
|
|
| 503 |
+ return "nil" |
|
| 504 |
+ } |
|
| 505 |
+ s := make([]string, 0, 6) |
|
| 506 |
+ s = append(s, "&descriptor.ServiceOptions{")
|
|
| 507 |
+ if this.Deprecated != nil {
|
|
| 508 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 509 |
+ } |
|
| 510 |
+ if this.UninterpretedOption != nil {
|
|
| 511 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 512 |
+ } |
|
| 513 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 514 |
+ if this.XXX_unrecognized != nil {
|
|
| 515 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 516 |
+ } |
|
| 517 |
+ s = append(s, "}") |
|
| 518 |
+ return strings.Join(s, "") |
|
| 519 |
+} |
|
| 520 |
+func (this *MethodOptions) GoString() string {
|
|
| 521 |
+ if this == nil {
|
|
| 522 |
+ return "nil" |
|
| 523 |
+ } |
|
| 524 |
+ s := make([]string, 0, 6) |
|
| 525 |
+ s = append(s, "&descriptor.MethodOptions{")
|
|
| 526 |
+ if this.Deprecated != nil {
|
|
| 527 |
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 528 |
+ } |
|
| 529 |
+ if this.UninterpretedOption != nil {
|
|
| 530 |
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 531 |
+ } |
|
| 532 |
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") |
|
| 533 |
+ if this.XXX_unrecognized != nil {
|
|
| 534 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 535 |
+ } |
|
| 536 |
+ s = append(s, "}") |
|
| 537 |
+ return strings.Join(s, "") |
|
| 538 |
+} |
|
| 539 |
+func (this *UninterpretedOption) GoString() string {
|
|
| 540 |
+ if this == nil {
|
|
| 541 |
+ return "nil" |
|
| 542 |
+ } |
|
| 543 |
+ s := make([]string, 0, 11) |
|
| 544 |
+ s = append(s, "&descriptor.UninterpretedOption{")
|
|
| 545 |
+ if this.Name != nil {
|
|
| 546 |
+ s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
|
|
| 547 |
+ } |
|
| 548 |
+ if this.IdentifierValue != nil {
|
|
| 549 |
+ s = append(s, "IdentifierValue: "+valueToGoStringDescriptor(this.IdentifierValue, "string")+",\n") |
|
| 550 |
+ } |
|
| 551 |
+ if this.PositiveIntValue != nil {
|
|
| 552 |
+ s = append(s, "PositiveIntValue: "+valueToGoStringDescriptor(this.PositiveIntValue, "uint64")+",\n") |
|
| 553 |
+ } |
|
| 554 |
+ if this.NegativeIntValue != nil {
|
|
| 555 |
+ s = append(s, "NegativeIntValue: "+valueToGoStringDescriptor(this.NegativeIntValue, "int64")+",\n") |
|
| 556 |
+ } |
|
| 557 |
+ if this.DoubleValue != nil {
|
|
| 558 |
+ s = append(s, "DoubleValue: "+valueToGoStringDescriptor(this.DoubleValue, "float64")+",\n") |
|
| 559 |
+ } |
|
| 560 |
+ if this.StringValue != nil {
|
|
| 561 |
+ s = append(s, "StringValue: "+valueToGoStringDescriptor(this.StringValue, "byte")+",\n") |
|
| 562 |
+ } |
|
| 563 |
+ if this.AggregateValue != nil {
|
|
| 564 |
+ s = append(s, "AggregateValue: "+valueToGoStringDescriptor(this.AggregateValue, "string")+",\n") |
|
| 565 |
+ } |
|
| 566 |
+ if this.XXX_unrecognized != nil {
|
|
| 567 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 568 |
+ } |
|
| 569 |
+ s = append(s, "}") |
|
| 570 |
+ return strings.Join(s, "") |
|
| 571 |
+} |
|
| 572 |
+func (this *UninterpretedOption_NamePart) GoString() string {
|
|
| 573 |
+ if this == nil {
|
|
| 574 |
+ return "nil" |
|
| 575 |
+ } |
|
| 576 |
+ s := make([]string, 0, 6) |
|
| 577 |
+ s = append(s, "&descriptor.UninterpretedOption_NamePart{")
|
|
| 578 |
+ if this.NamePart != nil {
|
|
| 579 |
+ s = append(s, "NamePart: "+valueToGoStringDescriptor(this.NamePart, "string")+",\n") |
|
| 580 |
+ } |
|
| 581 |
+ if this.IsExtension != nil {
|
|
| 582 |
+ s = append(s, "IsExtension: "+valueToGoStringDescriptor(this.IsExtension, "bool")+",\n") |
|
| 583 |
+ } |
|
| 584 |
+ if this.XXX_unrecognized != nil {
|
|
| 585 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 586 |
+ } |
|
| 587 |
+ s = append(s, "}") |
|
| 588 |
+ return strings.Join(s, "") |
|
| 589 |
+} |
|
| 590 |
+func (this *SourceCodeInfo) GoString() string {
|
|
| 591 |
+ if this == nil {
|
|
| 592 |
+ return "nil" |
|
| 593 |
+ } |
|
| 594 |
+ s := make([]string, 0, 5) |
|
| 595 |
+ s = append(s, "&descriptor.SourceCodeInfo{")
|
|
| 596 |
+ if this.Location != nil {
|
|
| 597 |
+ s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n")
|
|
| 598 |
+ } |
|
| 599 |
+ if this.XXX_unrecognized != nil {
|
|
| 600 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 601 |
+ } |
|
| 602 |
+ s = append(s, "}") |
|
| 603 |
+ return strings.Join(s, "") |
|
| 604 |
+} |
|
| 605 |
+func (this *SourceCodeInfo_Location) GoString() string {
|
|
| 606 |
+ if this == nil {
|
|
| 607 |
+ return "nil" |
|
| 608 |
+ } |
|
| 609 |
+ s := make([]string, 0, 9) |
|
| 610 |
+ s = append(s, "&descriptor.SourceCodeInfo_Location{")
|
|
| 611 |
+ if this.Path != nil {
|
|
| 612 |
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
|
|
| 613 |
+ } |
|
| 614 |
+ if this.Span != nil {
|
|
| 615 |
+ s = append(s, "Span: "+fmt.Sprintf("%#v", this.Span)+",\n")
|
|
| 616 |
+ } |
|
| 617 |
+ if this.LeadingComments != nil {
|
|
| 618 |
+ s = append(s, "LeadingComments: "+valueToGoStringDescriptor(this.LeadingComments, "string")+",\n") |
|
| 619 |
+ } |
|
| 620 |
+ if this.TrailingComments != nil {
|
|
| 621 |
+ s = append(s, "TrailingComments: "+valueToGoStringDescriptor(this.TrailingComments, "string")+",\n") |
|
| 622 |
+ } |
|
| 623 |
+ if this.LeadingDetachedComments != nil {
|
|
| 624 |
+ s = append(s, "LeadingDetachedComments: "+fmt.Sprintf("%#v", this.LeadingDetachedComments)+",\n")
|
|
| 625 |
+ } |
|
| 626 |
+ if this.XXX_unrecognized != nil {
|
|
| 627 |
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 628 |
+ } |
|
| 629 |
+ s = append(s, "}") |
|
| 630 |
+ return strings.Join(s, "") |
|
| 631 |
+} |
|
| 632 |
+func valueToGoStringDescriptor(v interface{}, typ string) string {
|
|
| 633 |
+ rv := reflect.ValueOf(v) |
|
| 634 |
+ if rv.IsNil() {
|
|
| 635 |
+ return "nil" |
|
| 636 |
+ } |
|
| 637 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 638 |
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 639 |
+} |
|
| 640 |
+func extensionToGoStringDescriptor(m github_com_gogo_protobuf_proto.Message) string {
|
|
| 641 |
+ e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) |
|
| 642 |
+ if e == nil {
|
|
| 643 |
+ return "nil" |
|
| 644 |
+ } |
|
| 645 |
+ s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"
|
|
| 646 |
+ keys := make([]int, 0, len(e)) |
|
| 647 |
+ for k := range e {
|
|
| 648 |
+ keys = append(keys, int(k)) |
|
| 649 |
+ } |
|
| 650 |
+ sort.Ints(keys) |
|
| 651 |
+ ss := []string{}
|
|
| 652 |
+ for _, k := range keys {
|
|
| 653 |
+ ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 654 |
+ } |
|
| 655 |
+ s += strings.Join(ss, ",") + "})" |
|
| 656 |
+ return s |
|
| 657 |
+} |
| 0 | 658 |
deleted file mode 100644 |
| ... | ... |
@@ -1,635 +0,0 @@ |
| 1 |
-package descriptor |
|
| 2 |
- |
|
| 3 |
-import fmt "fmt" |
|
| 4 |
- |
|
| 5 |
-import strings "strings" |
|
| 6 |
-import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 7 |
-import sort "sort" |
|
| 8 |
-import strconv "strconv" |
|
| 9 |
-import reflect "reflect" |
|
| 10 |
- |
|
| 11 |
-func (this *FileDescriptorSet) GoString() string {
|
|
| 12 |
- if this == nil {
|
|
| 13 |
- return "nil" |
|
| 14 |
- } |
|
| 15 |
- s := make([]string, 0, 5) |
|
| 16 |
- s = append(s, "&descriptor.FileDescriptorSet{")
|
|
| 17 |
- if this.File != nil {
|
|
| 18 |
- s = append(s, "File: "+fmt.Sprintf("%#v", this.File)+",\n")
|
|
| 19 |
- } |
|
| 20 |
- if this.XXX_unrecognized != nil {
|
|
| 21 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 22 |
- } |
|
| 23 |
- s = append(s, "}") |
|
| 24 |
- return strings.Join(s, "") |
|
| 25 |
-} |
|
| 26 |
-func (this *FileDescriptorProto) GoString() string {
|
|
| 27 |
- if this == nil {
|
|
| 28 |
- return "nil" |
|
| 29 |
- } |
|
| 30 |
- s := make([]string, 0, 16) |
|
| 31 |
- s = append(s, "&descriptor.FileDescriptorProto{")
|
|
| 32 |
- if this.Name != nil {
|
|
| 33 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 34 |
- } |
|
| 35 |
- if this.Package != nil {
|
|
| 36 |
- s = append(s, "Package: "+valueToGoStringDescriptor(this.Package, "string")+",\n") |
|
| 37 |
- } |
|
| 38 |
- if this.Dependency != nil {
|
|
| 39 |
- s = append(s, "Dependency: "+fmt.Sprintf("%#v", this.Dependency)+",\n")
|
|
| 40 |
- } |
|
| 41 |
- if this.PublicDependency != nil {
|
|
| 42 |
- s = append(s, "PublicDependency: "+fmt.Sprintf("%#v", this.PublicDependency)+",\n")
|
|
| 43 |
- } |
|
| 44 |
- if this.WeakDependency != nil {
|
|
| 45 |
- s = append(s, "WeakDependency: "+fmt.Sprintf("%#v", this.WeakDependency)+",\n")
|
|
| 46 |
- } |
|
| 47 |
- if this.MessageType != nil {
|
|
| 48 |
- s = append(s, "MessageType: "+fmt.Sprintf("%#v", this.MessageType)+",\n")
|
|
| 49 |
- } |
|
| 50 |
- if this.EnumType != nil {
|
|
| 51 |
- s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
|
|
| 52 |
- } |
|
| 53 |
- if this.Service != nil {
|
|
| 54 |
- s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
|
|
| 55 |
- } |
|
| 56 |
- if this.Extension != nil {
|
|
| 57 |
- s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
|
|
| 58 |
- } |
|
| 59 |
- if this.Options != nil {
|
|
| 60 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 61 |
- } |
|
| 62 |
- if this.SourceCodeInfo != nil {
|
|
| 63 |
- s = append(s, "SourceCodeInfo: "+fmt.Sprintf("%#v", this.SourceCodeInfo)+",\n")
|
|
| 64 |
- } |
|
| 65 |
- if this.Syntax != nil {
|
|
| 66 |
- s = append(s, "Syntax: "+valueToGoStringDescriptor(this.Syntax, "string")+",\n") |
|
| 67 |
- } |
|
| 68 |
- if this.XXX_unrecognized != nil {
|
|
| 69 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 70 |
- } |
|
| 71 |
- s = append(s, "}") |
|
| 72 |
- return strings.Join(s, "") |
|
| 73 |
-} |
|
| 74 |
-func (this *DescriptorProto) GoString() string {
|
|
| 75 |
- if this == nil {
|
|
| 76 |
- return "nil" |
|
| 77 |
- } |
|
| 78 |
- s := make([]string, 0, 14) |
|
| 79 |
- s = append(s, "&descriptor.DescriptorProto{")
|
|
| 80 |
- if this.Name != nil {
|
|
| 81 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 82 |
- } |
|
| 83 |
- if this.Field != nil {
|
|
| 84 |
- s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n")
|
|
| 85 |
- } |
|
| 86 |
- if this.Extension != nil {
|
|
| 87 |
- s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
|
|
| 88 |
- } |
|
| 89 |
- if this.NestedType != nil {
|
|
| 90 |
- s = append(s, "NestedType: "+fmt.Sprintf("%#v", this.NestedType)+",\n")
|
|
| 91 |
- } |
|
| 92 |
- if this.EnumType != nil {
|
|
| 93 |
- s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
|
|
| 94 |
- } |
|
| 95 |
- if this.ExtensionRange != nil {
|
|
| 96 |
- s = append(s, "ExtensionRange: "+fmt.Sprintf("%#v", this.ExtensionRange)+",\n")
|
|
| 97 |
- } |
|
| 98 |
- if this.OneofDecl != nil {
|
|
| 99 |
- s = append(s, "OneofDecl: "+fmt.Sprintf("%#v", this.OneofDecl)+",\n")
|
|
| 100 |
- } |
|
| 101 |
- if this.Options != nil {
|
|
| 102 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 103 |
- } |
|
| 104 |
- if this.ReservedRange != nil {
|
|
| 105 |
- s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
|
|
| 106 |
- } |
|
| 107 |
- if this.ReservedName != nil {
|
|
| 108 |
- s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
|
|
| 109 |
- } |
|
| 110 |
- if this.XXX_unrecognized != nil {
|
|
| 111 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 112 |
- } |
|
| 113 |
- s = append(s, "}") |
|
| 114 |
- return strings.Join(s, "") |
|
| 115 |
-} |
|
| 116 |
-func (this *DescriptorProto_ExtensionRange) GoString() string {
|
|
| 117 |
- if this == nil {
|
|
| 118 |
- return "nil" |
|
| 119 |
- } |
|
| 120 |
- s := make([]string, 0, 6) |
|
| 121 |
- s = append(s, "&descriptor.DescriptorProto_ExtensionRange{")
|
|
| 122 |
- if this.Start != nil {
|
|
| 123 |
- s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n") |
|
| 124 |
- } |
|
| 125 |
- if this.End != nil {
|
|
| 126 |
- s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n") |
|
| 127 |
- } |
|
| 128 |
- if this.XXX_unrecognized != nil {
|
|
| 129 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 130 |
- } |
|
| 131 |
- s = append(s, "}") |
|
| 132 |
- return strings.Join(s, "") |
|
| 133 |
-} |
|
| 134 |
-func (this *DescriptorProto_ReservedRange) GoString() string {
|
|
| 135 |
- if this == nil {
|
|
| 136 |
- return "nil" |
|
| 137 |
- } |
|
| 138 |
- s := make([]string, 0, 6) |
|
| 139 |
- s = append(s, "&descriptor.DescriptorProto_ReservedRange{")
|
|
| 140 |
- if this.Start != nil {
|
|
| 141 |
- s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n") |
|
| 142 |
- } |
|
| 143 |
- if this.End != nil {
|
|
| 144 |
- s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n") |
|
| 145 |
- } |
|
| 146 |
- if this.XXX_unrecognized != nil {
|
|
| 147 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 148 |
- } |
|
| 149 |
- s = append(s, "}") |
|
| 150 |
- return strings.Join(s, "") |
|
| 151 |
-} |
|
| 152 |
-func (this *FieldDescriptorProto) GoString() string {
|
|
| 153 |
- if this == nil {
|
|
| 154 |
- return "nil" |
|
| 155 |
- } |
|
| 156 |
- s := make([]string, 0, 14) |
|
| 157 |
- s = append(s, "&descriptor.FieldDescriptorProto{")
|
|
| 158 |
- if this.Name != nil {
|
|
| 159 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 160 |
- } |
|
| 161 |
- if this.Number != nil {
|
|
| 162 |
- s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n") |
|
| 163 |
- } |
|
| 164 |
- if this.Label != nil {
|
|
| 165 |
- s = append(s, "Label: "+valueToGoStringDescriptor(this.Label, "descriptor.FieldDescriptorProto_Label")+",\n") |
|
| 166 |
- } |
|
| 167 |
- if this.Type != nil {
|
|
| 168 |
- s = append(s, "Type: "+valueToGoStringDescriptor(this.Type, "descriptor.FieldDescriptorProto_Type")+",\n") |
|
| 169 |
- } |
|
| 170 |
- if this.TypeName != nil {
|
|
| 171 |
- s = append(s, "TypeName: "+valueToGoStringDescriptor(this.TypeName, "string")+",\n") |
|
| 172 |
- } |
|
| 173 |
- if this.Extendee != nil {
|
|
| 174 |
- s = append(s, "Extendee: "+valueToGoStringDescriptor(this.Extendee, "string")+",\n") |
|
| 175 |
- } |
|
| 176 |
- if this.DefaultValue != nil {
|
|
| 177 |
- s = append(s, "DefaultValue: "+valueToGoStringDescriptor(this.DefaultValue, "string")+",\n") |
|
| 178 |
- } |
|
| 179 |
- if this.OneofIndex != nil {
|
|
| 180 |
- s = append(s, "OneofIndex: "+valueToGoStringDescriptor(this.OneofIndex, "int32")+",\n") |
|
| 181 |
- } |
|
| 182 |
- if this.JsonName != nil {
|
|
| 183 |
- s = append(s, "JsonName: "+valueToGoStringDescriptor(this.JsonName, "string")+",\n") |
|
| 184 |
- } |
|
| 185 |
- if this.Options != nil {
|
|
| 186 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 187 |
- } |
|
| 188 |
- if this.XXX_unrecognized != nil {
|
|
| 189 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 190 |
- } |
|
| 191 |
- s = append(s, "}") |
|
| 192 |
- return strings.Join(s, "") |
|
| 193 |
-} |
|
| 194 |
-func (this *OneofDescriptorProto) GoString() string {
|
|
| 195 |
- if this == nil {
|
|
| 196 |
- return "nil" |
|
| 197 |
- } |
|
| 198 |
- s := make([]string, 0, 5) |
|
| 199 |
- s = append(s, "&descriptor.OneofDescriptorProto{")
|
|
| 200 |
- if this.Name != nil {
|
|
| 201 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 202 |
- } |
|
| 203 |
- if this.XXX_unrecognized != nil {
|
|
| 204 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 205 |
- } |
|
| 206 |
- s = append(s, "}") |
|
| 207 |
- return strings.Join(s, "") |
|
| 208 |
-} |
|
| 209 |
-func (this *EnumDescriptorProto) GoString() string {
|
|
| 210 |
- if this == nil {
|
|
| 211 |
- return "nil" |
|
| 212 |
- } |
|
| 213 |
- s := make([]string, 0, 7) |
|
| 214 |
- s = append(s, "&descriptor.EnumDescriptorProto{")
|
|
| 215 |
- if this.Name != nil {
|
|
| 216 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 217 |
- } |
|
| 218 |
- if this.Value != nil {
|
|
| 219 |
- s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
|
|
| 220 |
- } |
|
| 221 |
- if this.Options != nil {
|
|
| 222 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 223 |
- } |
|
| 224 |
- if this.XXX_unrecognized != nil {
|
|
| 225 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 226 |
- } |
|
| 227 |
- s = append(s, "}") |
|
| 228 |
- return strings.Join(s, "") |
|
| 229 |
-} |
|
| 230 |
-func (this *EnumValueDescriptorProto) GoString() string {
|
|
| 231 |
- if this == nil {
|
|
| 232 |
- return "nil" |
|
| 233 |
- } |
|
| 234 |
- s := make([]string, 0, 7) |
|
| 235 |
- s = append(s, "&descriptor.EnumValueDescriptorProto{")
|
|
| 236 |
- if this.Name != nil {
|
|
| 237 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 238 |
- } |
|
| 239 |
- if this.Number != nil {
|
|
| 240 |
- s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n") |
|
| 241 |
- } |
|
| 242 |
- if this.Options != nil {
|
|
| 243 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 244 |
- } |
|
| 245 |
- if this.XXX_unrecognized != nil {
|
|
| 246 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 247 |
- } |
|
| 248 |
- s = append(s, "}") |
|
| 249 |
- return strings.Join(s, "") |
|
| 250 |
-} |
|
| 251 |
-func (this *ServiceDescriptorProto) GoString() string {
|
|
| 252 |
- if this == nil {
|
|
| 253 |
- return "nil" |
|
| 254 |
- } |
|
| 255 |
- s := make([]string, 0, 7) |
|
| 256 |
- s = append(s, "&descriptor.ServiceDescriptorProto{")
|
|
| 257 |
- if this.Name != nil {
|
|
| 258 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 259 |
- } |
|
| 260 |
- if this.Method != nil {
|
|
| 261 |
- s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
|
|
| 262 |
- } |
|
| 263 |
- if this.Options != nil {
|
|
| 264 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 265 |
- } |
|
| 266 |
- if this.XXX_unrecognized != nil {
|
|
| 267 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 268 |
- } |
|
| 269 |
- s = append(s, "}") |
|
| 270 |
- return strings.Join(s, "") |
|
| 271 |
-} |
|
| 272 |
-func (this *MethodDescriptorProto) GoString() string {
|
|
| 273 |
- if this == nil {
|
|
| 274 |
- return "nil" |
|
| 275 |
- } |
|
| 276 |
- s := make([]string, 0, 10) |
|
| 277 |
- s = append(s, "&descriptor.MethodDescriptorProto{")
|
|
| 278 |
- if this.Name != nil {
|
|
| 279 |
- s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n") |
|
| 280 |
- } |
|
| 281 |
- if this.InputType != nil {
|
|
| 282 |
- s = append(s, "InputType: "+valueToGoStringDescriptor(this.InputType, "string")+",\n") |
|
| 283 |
- } |
|
| 284 |
- if this.OutputType != nil {
|
|
| 285 |
- s = append(s, "OutputType: "+valueToGoStringDescriptor(this.OutputType, "string")+",\n") |
|
| 286 |
- } |
|
| 287 |
- if this.Options != nil {
|
|
| 288 |
- s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
|
|
| 289 |
- } |
|
| 290 |
- if this.ClientStreaming != nil {
|
|
| 291 |
- s = append(s, "ClientStreaming: "+valueToGoStringDescriptor(this.ClientStreaming, "bool")+",\n") |
|
| 292 |
- } |
|
| 293 |
- if this.ServerStreaming != nil {
|
|
| 294 |
- s = append(s, "ServerStreaming: "+valueToGoStringDescriptor(this.ServerStreaming, "bool")+",\n") |
|
| 295 |
- } |
|
| 296 |
- if this.XXX_unrecognized != nil {
|
|
| 297 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 298 |
- } |
|
| 299 |
- s = append(s, "}") |
|
| 300 |
- return strings.Join(s, "") |
|
| 301 |
-} |
|
| 302 |
-func (this *FileOptions) GoString() string {
|
|
| 303 |
- if this == nil {
|
|
| 304 |
- return "nil" |
|
| 305 |
- } |
|
| 306 |
- s := make([]string, 0, 20) |
|
| 307 |
- s = append(s, "&descriptor.FileOptions{")
|
|
| 308 |
- if this.JavaPackage != nil {
|
|
| 309 |
- s = append(s, "JavaPackage: "+valueToGoStringDescriptor(this.JavaPackage, "string")+",\n") |
|
| 310 |
- } |
|
| 311 |
- if this.JavaOuterClassname != nil {
|
|
| 312 |
- s = append(s, "JavaOuterClassname: "+valueToGoStringDescriptor(this.JavaOuterClassname, "string")+",\n") |
|
| 313 |
- } |
|
| 314 |
- if this.JavaMultipleFiles != nil {
|
|
| 315 |
- s = append(s, "JavaMultipleFiles: "+valueToGoStringDescriptor(this.JavaMultipleFiles, "bool")+",\n") |
|
| 316 |
- } |
|
| 317 |
- if this.JavaGenerateEqualsAndHash != nil {
|
|
| 318 |
- s = append(s, "JavaGenerateEqualsAndHash: "+valueToGoStringDescriptor(this.JavaGenerateEqualsAndHash, "bool")+",\n") |
|
| 319 |
- } |
|
| 320 |
- if this.JavaStringCheckUtf8 != nil {
|
|
| 321 |
- s = append(s, "JavaStringCheckUtf8: "+valueToGoStringDescriptor(this.JavaStringCheckUtf8, "bool")+",\n") |
|
| 322 |
- } |
|
| 323 |
- if this.OptimizeFor != nil {
|
|
| 324 |
- s = append(s, "OptimizeFor: "+valueToGoStringDescriptor(this.OptimizeFor, "descriptor.FileOptions_OptimizeMode")+",\n") |
|
| 325 |
- } |
|
| 326 |
- if this.GoPackage != nil {
|
|
| 327 |
- s = append(s, "GoPackage: "+valueToGoStringDescriptor(this.GoPackage, "string")+",\n") |
|
| 328 |
- } |
|
| 329 |
- if this.CcGenericServices != nil {
|
|
| 330 |
- s = append(s, "CcGenericServices: "+valueToGoStringDescriptor(this.CcGenericServices, "bool")+",\n") |
|
| 331 |
- } |
|
| 332 |
- if this.JavaGenericServices != nil {
|
|
| 333 |
- s = append(s, "JavaGenericServices: "+valueToGoStringDescriptor(this.JavaGenericServices, "bool")+",\n") |
|
| 334 |
- } |
|
| 335 |
- if this.PyGenericServices != nil {
|
|
| 336 |
- s = append(s, "PyGenericServices: "+valueToGoStringDescriptor(this.PyGenericServices, "bool")+",\n") |
|
| 337 |
- } |
|
| 338 |
- if this.Deprecated != nil {
|
|
| 339 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 340 |
- } |
|
| 341 |
- if this.CcEnableArenas != nil {
|
|
| 342 |
- s = append(s, "CcEnableArenas: "+valueToGoStringDescriptor(this.CcEnableArenas, "bool")+",\n") |
|
| 343 |
- } |
|
| 344 |
- if this.ObjcClassPrefix != nil {
|
|
| 345 |
- s = append(s, "ObjcClassPrefix: "+valueToGoStringDescriptor(this.ObjcClassPrefix, "string")+",\n") |
|
| 346 |
- } |
|
| 347 |
- if this.CsharpNamespace != nil {
|
|
| 348 |
- s = append(s, "CsharpNamespace: "+valueToGoStringDescriptor(this.CsharpNamespace, "string")+",\n") |
|
| 349 |
- } |
|
| 350 |
- if this.JavananoUseDeprecatedPackage != nil {
|
|
| 351 |
- s = append(s, "JavananoUseDeprecatedPackage: "+valueToGoStringDescriptor(this.JavananoUseDeprecatedPackage, "bool")+",\n") |
|
| 352 |
- } |
|
| 353 |
- if this.UninterpretedOption != nil {
|
|
| 354 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 355 |
- } |
|
| 356 |
- if this.XXX_extensions != nil {
|
|
| 357 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 358 |
- } |
|
| 359 |
- if this.XXX_unrecognized != nil {
|
|
| 360 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 361 |
- } |
|
| 362 |
- s = append(s, "}") |
|
| 363 |
- return strings.Join(s, "") |
|
| 364 |
-} |
|
| 365 |
-func (this *MessageOptions) GoString() string {
|
|
| 366 |
- if this == nil {
|
|
| 367 |
- return "nil" |
|
| 368 |
- } |
|
| 369 |
- s := make([]string, 0, 9) |
|
| 370 |
- s = append(s, "&descriptor.MessageOptions{")
|
|
| 371 |
- if this.MessageSetWireFormat != nil {
|
|
| 372 |
- s = append(s, "MessageSetWireFormat: "+valueToGoStringDescriptor(this.MessageSetWireFormat, "bool")+",\n") |
|
| 373 |
- } |
|
| 374 |
- if this.NoStandardDescriptorAccessor != nil {
|
|
| 375 |
- s = append(s, "NoStandardDescriptorAccessor: "+valueToGoStringDescriptor(this.NoStandardDescriptorAccessor, "bool")+",\n") |
|
| 376 |
- } |
|
| 377 |
- if this.Deprecated != nil {
|
|
| 378 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 379 |
- } |
|
| 380 |
- if this.MapEntry != nil {
|
|
| 381 |
- s = append(s, "MapEntry: "+valueToGoStringDescriptor(this.MapEntry, "bool")+",\n") |
|
| 382 |
- } |
|
| 383 |
- if this.UninterpretedOption != nil {
|
|
| 384 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 385 |
- } |
|
| 386 |
- if this.XXX_extensions != nil {
|
|
| 387 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 388 |
- } |
|
| 389 |
- if this.XXX_unrecognized != nil {
|
|
| 390 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 391 |
- } |
|
| 392 |
- s = append(s, "}") |
|
| 393 |
- return strings.Join(s, "") |
|
| 394 |
-} |
|
| 395 |
-func (this *FieldOptions) GoString() string {
|
|
| 396 |
- if this == nil {
|
|
| 397 |
- return "nil" |
|
| 398 |
- } |
|
| 399 |
- s := make([]string, 0, 11) |
|
| 400 |
- s = append(s, "&descriptor.FieldOptions{")
|
|
| 401 |
- if this.Ctype != nil {
|
|
| 402 |
- s = append(s, "Ctype: "+valueToGoStringDescriptor(this.Ctype, "descriptor.FieldOptions_CType")+",\n") |
|
| 403 |
- } |
|
| 404 |
- if this.Packed != nil {
|
|
| 405 |
- s = append(s, "Packed: "+valueToGoStringDescriptor(this.Packed, "bool")+",\n") |
|
| 406 |
- } |
|
| 407 |
- if this.Jstype != nil {
|
|
| 408 |
- s = append(s, "Jstype: "+valueToGoStringDescriptor(this.Jstype, "descriptor.FieldOptions_JSType")+",\n") |
|
| 409 |
- } |
|
| 410 |
- if this.Lazy != nil {
|
|
| 411 |
- s = append(s, "Lazy: "+valueToGoStringDescriptor(this.Lazy, "bool")+",\n") |
|
| 412 |
- } |
|
| 413 |
- if this.Deprecated != nil {
|
|
| 414 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 415 |
- } |
|
| 416 |
- if this.Weak != nil {
|
|
| 417 |
- s = append(s, "Weak: "+valueToGoStringDescriptor(this.Weak, "bool")+",\n") |
|
| 418 |
- } |
|
| 419 |
- if this.UninterpretedOption != nil {
|
|
| 420 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 421 |
- } |
|
| 422 |
- if this.XXX_extensions != nil {
|
|
| 423 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 424 |
- } |
|
| 425 |
- if this.XXX_unrecognized != nil {
|
|
| 426 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 427 |
- } |
|
| 428 |
- s = append(s, "}") |
|
| 429 |
- return strings.Join(s, "") |
|
| 430 |
-} |
|
| 431 |
-func (this *EnumOptions) GoString() string {
|
|
| 432 |
- if this == nil {
|
|
| 433 |
- return "nil" |
|
| 434 |
- } |
|
| 435 |
- s := make([]string, 0, 7) |
|
| 436 |
- s = append(s, "&descriptor.EnumOptions{")
|
|
| 437 |
- if this.AllowAlias != nil {
|
|
| 438 |
- s = append(s, "AllowAlias: "+valueToGoStringDescriptor(this.AllowAlias, "bool")+",\n") |
|
| 439 |
- } |
|
| 440 |
- if this.Deprecated != nil {
|
|
| 441 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 442 |
- } |
|
| 443 |
- if this.UninterpretedOption != nil {
|
|
| 444 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 445 |
- } |
|
| 446 |
- if this.XXX_extensions != nil {
|
|
| 447 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 448 |
- } |
|
| 449 |
- if this.XXX_unrecognized != nil {
|
|
| 450 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 451 |
- } |
|
| 452 |
- s = append(s, "}") |
|
| 453 |
- return strings.Join(s, "") |
|
| 454 |
-} |
|
| 455 |
-func (this *EnumValueOptions) GoString() string {
|
|
| 456 |
- if this == nil {
|
|
| 457 |
- return "nil" |
|
| 458 |
- } |
|
| 459 |
- s := make([]string, 0, 6) |
|
| 460 |
- s = append(s, "&descriptor.EnumValueOptions{")
|
|
| 461 |
- if this.Deprecated != nil {
|
|
| 462 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 463 |
- } |
|
| 464 |
- if this.UninterpretedOption != nil {
|
|
| 465 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 466 |
- } |
|
| 467 |
- if this.XXX_extensions != nil {
|
|
| 468 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 469 |
- } |
|
| 470 |
- if this.XXX_unrecognized != nil {
|
|
| 471 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 472 |
- } |
|
| 473 |
- s = append(s, "}") |
|
| 474 |
- return strings.Join(s, "") |
|
| 475 |
-} |
|
| 476 |
-func (this *ServiceOptions) GoString() string {
|
|
| 477 |
- if this == nil {
|
|
| 478 |
- return "nil" |
|
| 479 |
- } |
|
| 480 |
- s := make([]string, 0, 6) |
|
| 481 |
- s = append(s, "&descriptor.ServiceOptions{")
|
|
| 482 |
- if this.Deprecated != nil {
|
|
| 483 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 484 |
- } |
|
| 485 |
- if this.UninterpretedOption != nil {
|
|
| 486 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 487 |
- } |
|
| 488 |
- if this.XXX_extensions != nil {
|
|
| 489 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 490 |
- } |
|
| 491 |
- if this.XXX_unrecognized != nil {
|
|
| 492 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 493 |
- } |
|
| 494 |
- s = append(s, "}") |
|
| 495 |
- return strings.Join(s, "") |
|
| 496 |
-} |
|
| 497 |
-func (this *MethodOptions) GoString() string {
|
|
| 498 |
- if this == nil {
|
|
| 499 |
- return "nil" |
|
| 500 |
- } |
|
| 501 |
- s := make([]string, 0, 6) |
|
| 502 |
- s = append(s, "&descriptor.MethodOptions{")
|
|
| 503 |
- if this.Deprecated != nil {
|
|
| 504 |
- s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n") |
|
| 505 |
- } |
|
| 506 |
- if this.UninterpretedOption != nil {
|
|
| 507 |
- s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
|
|
| 508 |
- } |
|
| 509 |
- if this.XXX_extensions != nil {
|
|
| 510 |
- s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") |
|
| 511 |
- } |
|
| 512 |
- if this.XXX_unrecognized != nil {
|
|
| 513 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 514 |
- } |
|
| 515 |
- s = append(s, "}") |
|
| 516 |
- return strings.Join(s, "") |
|
| 517 |
-} |
|
| 518 |
-func (this *UninterpretedOption) GoString() string {
|
|
| 519 |
- if this == nil {
|
|
| 520 |
- return "nil" |
|
| 521 |
- } |
|
| 522 |
- s := make([]string, 0, 11) |
|
| 523 |
- s = append(s, "&descriptor.UninterpretedOption{")
|
|
| 524 |
- if this.Name != nil {
|
|
| 525 |
- s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
|
|
| 526 |
- } |
|
| 527 |
- if this.IdentifierValue != nil {
|
|
| 528 |
- s = append(s, "IdentifierValue: "+valueToGoStringDescriptor(this.IdentifierValue, "string")+",\n") |
|
| 529 |
- } |
|
| 530 |
- if this.PositiveIntValue != nil {
|
|
| 531 |
- s = append(s, "PositiveIntValue: "+valueToGoStringDescriptor(this.PositiveIntValue, "uint64")+",\n") |
|
| 532 |
- } |
|
| 533 |
- if this.NegativeIntValue != nil {
|
|
| 534 |
- s = append(s, "NegativeIntValue: "+valueToGoStringDescriptor(this.NegativeIntValue, "int64")+",\n") |
|
| 535 |
- } |
|
| 536 |
- if this.DoubleValue != nil {
|
|
| 537 |
- s = append(s, "DoubleValue: "+valueToGoStringDescriptor(this.DoubleValue, "float64")+",\n") |
|
| 538 |
- } |
|
| 539 |
- if this.StringValue != nil {
|
|
| 540 |
- s = append(s, "StringValue: "+valueToGoStringDescriptor(this.StringValue, "byte")+",\n") |
|
| 541 |
- } |
|
| 542 |
- if this.AggregateValue != nil {
|
|
| 543 |
- s = append(s, "AggregateValue: "+valueToGoStringDescriptor(this.AggregateValue, "string")+",\n") |
|
| 544 |
- } |
|
| 545 |
- if this.XXX_unrecognized != nil {
|
|
| 546 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 547 |
- } |
|
| 548 |
- s = append(s, "}") |
|
| 549 |
- return strings.Join(s, "") |
|
| 550 |
-} |
|
| 551 |
-func (this *UninterpretedOption_NamePart) GoString() string {
|
|
| 552 |
- if this == nil {
|
|
| 553 |
- return "nil" |
|
| 554 |
- } |
|
| 555 |
- s := make([]string, 0, 6) |
|
| 556 |
- s = append(s, "&descriptor.UninterpretedOption_NamePart{")
|
|
| 557 |
- if this.NamePart != nil {
|
|
| 558 |
- s = append(s, "NamePart: "+valueToGoStringDescriptor(this.NamePart, "string")+",\n") |
|
| 559 |
- } |
|
| 560 |
- if this.IsExtension != nil {
|
|
| 561 |
- s = append(s, "IsExtension: "+valueToGoStringDescriptor(this.IsExtension, "bool")+",\n") |
|
| 562 |
- } |
|
| 563 |
- if this.XXX_unrecognized != nil {
|
|
| 564 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 565 |
- } |
|
| 566 |
- s = append(s, "}") |
|
| 567 |
- return strings.Join(s, "") |
|
| 568 |
-} |
|
| 569 |
-func (this *SourceCodeInfo) GoString() string {
|
|
| 570 |
- if this == nil {
|
|
| 571 |
- return "nil" |
|
| 572 |
- } |
|
| 573 |
- s := make([]string, 0, 5) |
|
| 574 |
- s = append(s, "&descriptor.SourceCodeInfo{")
|
|
| 575 |
- if this.Location != nil {
|
|
| 576 |
- s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n")
|
|
| 577 |
- } |
|
| 578 |
- if this.XXX_unrecognized != nil {
|
|
| 579 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 580 |
- } |
|
| 581 |
- s = append(s, "}") |
|
| 582 |
- return strings.Join(s, "") |
|
| 583 |
-} |
|
| 584 |
-func (this *SourceCodeInfo_Location) GoString() string {
|
|
| 585 |
- if this == nil {
|
|
| 586 |
- return "nil" |
|
| 587 |
- } |
|
| 588 |
- s := make([]string, 0, 9) |
|
| 589 |
- s = append(s, "&descriptor.SourceCodeInfo_Location{")
|
|
| 590 |
- if this.Path != nil {
|
|
| 591 |
- s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
|
|
| 592 |
- } |
|
| 593 |
- if this.Span != nil {
|
|
| 594 |
- s = append(s, "Span: "+fmt.Sprintf("%#v", this.Span)+",\n")
|
|
| 595 |
- } |
|
| 596 |
- if this.LeadingComments != nil {
|
|
| 597 |
- s = append(s, "LeadingComments: "+valueToGoStringDescriptor(this.LeadingComments, "string")+",\n") |
|
| 598 |
- } |
|
| 599 |
- if this.TrailingComments != nil {
|
|
| 600 |
- s = append(s, "TrailingComments: "+valueToGoStringDescriptor(this.TrailingComments, "string")+",\n") |
|
| 601 |
- } |
|
| 602 |
- if this.LeadingDetachedComments != nil {
|
|
| 603 |
- s = append(s, "LeadingDetachedComments: "+fmt.Sprintf("%#v", this.LeadingDetachedComments)+",\n")
|
|
| 604 |
- } |
|
| 605 |
- if this.XXX_unrecognized != nil {
|
|
| 606 |
- s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
|
|
| 607 |
- } |
|
| 608 |
- s = append(s, "}") |
|
| 609 |
- return strings.Join(s, "") |
|
| 610 |
-} |
|
| 611 |
-func valueToGoStringDescriptor(v interface{}, typ string) string {
|
|
| 612 |
- rv := reflect.ValueOf(v) |
|
| 613 |
- if rv.IsNil() {
|
|
| 614 |
- return "nil" |
|
| 615 |
- } |
|
| 616 |
- pv := reflect.Indirect(rv).Interface() |
|
| 617 |
- return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 618 |
-} |
|
| 619 |
-func extensionToGoStringDescriptor(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
|
|
| 620 |
- if e == nil {
|
|
| 621 |
- return "nil" |
|
| 622 |
- } |
|
| 623 |
- s := "map[int32]proto.Extension{"
|
|
| 624 |
- keys := make([]int, 0, len(e)) |
|
| 625 |
- for k := range e {
|
|
| 626 |
- keys = append(keys, int(k)) |
|
| 627 |
- } |
|
| 628 |
- sort.Ints(keys) |
|
| 629 |
- ss := []string{}
|
|
| 630 |
- for _, k := range keys {
|
|
| 631 |
- ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 632 |
- } |
|
| 633 |
- s += strings.Join(ss, ",") + "}" |
|
| 634 |
- return s |
|
| 635 |
-} |
| ... | ... |
@@ -1,4 +1,6 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 2 | 4 |
// http://github.com/gogo/protobuf |
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| ... | ... |
@@ -1,4 +1,6 @@ |
| 1 |
-// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. |
|
| 1 |
+// Protocol Buffers for Go with Gadgets |
|
| 2 |
+// |
|
| 3 |
+// Copyright (c) 2013, The GoGo Authors. All rights reserved. |
|
| 2 | 4 |
// http://github.com/gogo/protobuf |
| 3 | 5 |
// |
| 4 | 6 |
// Redistribution and use in source and binary forms, with or without |
| ... | ... |
@@ -39,5 +39,5 @@ test: install generate-test-pbs |
| 39 | 39 |
generate-test-pbs: |
| 40 | 40 |
make install |
| 41 | 41 |
make -C testdata |
| 42 |
- protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto |
|
| 42 |
+ protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto |
|
| 43 | 43 |
make |
| ... | ... |
@@ -84,9 +84,15 @@ func mergeStruct(out, in reflect.Value) {
|
| 84 | 84 |
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
- if emIn, ok := in.Addr().Interface().(extendableProto); ok {
|
|
| 88 |
- emOut := out.Addr().Interface().(extendableProto) |
|
| 89 |
- mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) |
|
| 87 |
+ if emIn, ok := extendable(in.Addr().Interface()); ok {
|
|
| 88 |
+ emOut, _ := extendable(out.Addr().Interface()) |
|
| 89 |
+ mIn, muIn := emIn.extensionsRead() |
|
| 90 |
+ if mIn != nil {
|
|
| 91 |
+ mOut := emOut.extensionsWrite() |
|
| 92 |
+ muIn.Lock() |
|
| 93 |
+ mergeExtension(mOut, mIn) |
|
| 94 |
+ muIn.Unlock() |
|
| 95 |
+ } |
|
| 90 | 96 |
} |
| 91 | 97 |
|
| 92 | 98 |
uf := in.FieldByName("XXX_unrecognized")
|
| ... | ... |
@@ -378,6 +378,11 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group |
| 378 | 378 |
wire := int(u & 0x7) |
| 379 | 379 |
if wire == WireEndGroup {
|
| 380 | 380 |
if is_group {
|
| 381 |
+ if required > 0 {
|
|
| 382 |
+ // Not enough information to determine the exact field. |
|
| 383 |
+ // (See below.) |
|
| 384 |
+ return &RequiredNotSetError{"{Unknown}"}
|
|
| 385 |
+ } |
|
| 381 | 386 |
return nil // input is satisfied |
| 382 | 387 |
} |
| 383 | 388 |
return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
|
| ... | ... |
@@ -390,11 +395,12 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group |
| 390 | 390 |
if !ok {
|
| 391 | 391 |
// Maybe it's an extension? |
| 392 | 392 |
if prop.extendable {
|
| 393 |
- if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) {
|
|
| 393 |
+ if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
|
|
| 394 | 394 |
if err = o.skip(st, tag, wire); err == nil {
|
| 395 |
- ext := e.ExtensionMap()[int32(tag)] // may be missing |
|
| 395 |
+ extmap := e.extensionsWrite() |
|
| 396 |
+ ext := extmap[int32(tag)] // may be missing |
|
| 396 | 397 |
ext.enc = append(ext.enc, o.buf[oi:o.index]...) |
| 397 |
- e.ExtensionMap()[int32(tag)] = ext |
|
| 398 |
+ extmap[int32(tag)] = ext |
|
| 398 | 399 |
} |
| 399 | 400 |
continue |
| 400 | 401 |
} |
| ... | ... |
@@ -768,10 +774,11 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
|
| 768 | 768 |
} |
| 769 | 769 |
} |
| 770 | 770 |
keyelem, valelem := keyptr.Elem(), valptr.Elem() |
| 771 |
- if !keyelem.IsValid() || !valelem.IsValid() {
|
|
| 772 |
- // We did not decode the key or the value in the map entry. |
|
| 773 |
- // Either way, it's an invalid map entry. |
|
| 774 |
- return fmt.Errorf("proto: bad map data: missing key/val")
|
|
| 771 |
+ if !keyelem.IsValid() {
|
|
| 772 |
+ keyelem = reflect.Zero(p.mtype.Key()) |
|
| 773 |
+ } |
|
| 774 |
+ if !valelem.IsValid() {
|
|
| 775 |
+ valelem = reflect.Zero(p.mtype.Elem()) |
|
| 775 | 776 |
} |
| 776 | 777 |
|
| 777 | 778 |
v.SetMapIndex(keyelem, valelem) |
| ... | ... |
@@ -64,8 +64,16 @@ var ( |
| 64 | 64 |
// a struct with a repeated field containing a nil element. |
| 65 | 65 |
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
| 66 | 66 |
|
| 67 |
+ // errOneofHasNil is the error returned if Marshal is called with |
|
| 68 |
+ // a struct with a oneof field containing a nil element. |
|
| 69 |
+ errOneofHasNil = errors.New("proto: oneof field has nil value")
|
|
| 70 |
+ |
|
| 67 | 71 |
// ErrNil is the error returned if Marshal is called with nil. |
| 68 | 72 |
ErrNil = errors.New("proto: Marshal called with nil")
|
| 73 |
+ |
|
| 74 |
+ // ErrTooLarge is the error returned if Marshal is called with a |
|
| 75 |
+ // message that encodes to >2GB. |
|
| 76 |
+ ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
|
| 69 | 77 |
) |
| 70 | 78 |
|
| 71 | 79 |
// The fundamental encoders that put bytes on the wire. |
| ... | ... |
@@ -74,6 +82,10 @@ var ( |
| 74 | 74 |
|
| 75 | 75 |
const maxVarintBytes = 10 // maximum length of a varint |
| 76 | 76 |
|
| 77 |
+// maxMarshalSize is the largest allowed size of an encoded protobuf, |
|
| 78 |
+// since C++ and Java use signed int32s for the size. |
|
| 79 |
+const maxMarshalSize = 1<<31 - 1 |
|
| 80 |
+ |
|
| 77 | 81 |
// EncodeVarint returns the varint encoding of x. |
| 78 | 82 |
// This is the format for the |
| 79 | 83 |
// int32, int64, uint32, uint64, bool, and enum |
| ... | ... |
@@ -273,6 +285,9 @@ func (p *Buffer) Marshal(pb Message) error {
|
| 273 | 273 |
stats.Encode++ |
| 274 | 274 |
} |
| 275 | 275 |
|
| 276 |
+ if len(p.buf) > maxMarshalSize {
|
|
| 277 |
+ return ErrTooLarge |
|
| 278 |
+ } |
|
| 276 | 279 |
return err |
| 277 | 280 |
} |
| 278 | 281 |
|
| ... | ... |
@@ -1058,10 +1073,25 @@ func size_slice_struct_group(p *Properties, base structPointer) (n int) {
|
| 1058 | 1058 |
|
| 1059 | 1059 |
// Encode an extension map. |
| 1060 | 1060 |
func (o *Buffer) enc_map(p *Properties, base structPointer) error {
|
| 1061 |
- v := *structPointer_ExtMap(base, p.field) |
|
| 1062 |
- if err := encodeExtensionMap(v); err != nil {
|
|
| 1061 |
+ exts := structPointer_ExtMap(base, p.field) |
|
| 1062 |
+ if err := encodeExtensionsMap(*exts); err != nil {
|
|
| 1063 |
+ return err |
|
| 1064 |
+ } |
|
| 1065 |
+ |
|
| 1066 |
+ return o.enc_map_body(*exts) |
|
| 1067 |
+} |
|
| 1068 |
+ |
|
| 1069 |
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
|
|
| 1070 |
+ exts := structPointer_Extensions(base, p.field) |
|
| 1071 |
+ if err := encodeExtensions(exts); err != nil {
|
|
| 1063 | 1072 |
return err |
| 1064 | 1073 |
} |
| 1074 |
+ v, _ := exts.extensionsRead() |
|
| 1075 |
+ |
|
| 1076 |
+ return o.enc_map_body(v) |
|
| 1077 |
+} |
|
| 1078 |
+ |
|
| 1079 |
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
|
|
| 1065 | 1080 |
// Fast-path for common cases: zero or one extensions. |
| 1066 | 1081 |
if len(v) <= 1 {
|
| 1067 | 1082 |
for _, e := range v {
|
| ... | ... |
@@ -1084,8 +1114,13 @@ func (o *Buffer) enc_map(p *Properties, base structPointer) error {
|
| 1084 | 1084 |
} |
| 1085 | 1085 |
|
| 1086 | 1086 |
func size_map(p *Properties, base structPointer) int {
|
| 1087 |
- v := *structPointer_ExtMap(base, p.field) |
|
| 1088 |
- return sizeExtensionMap(v) |
|
| 1087 |
+ v := structPointer_ExtMap(base, p.field) |
|
| 1088 |
+ return extensionsMapSize(*v) |
|
| 1089 |
+} |
|
| 1090 |
+ |
|
| 1091 |
+func size_exts(p *Properties, base structPointer) int {
|
|
| 1092 |
+ v := structPointer_Extensions(base, p.field) |
|
| 1093 |
+ return extensionsSize(v) |
|
| 1089 | 1094 |
} |
| 1090 | 1095 |
|
| 1091 | 1096 |
// Encode a map field. |
| ... | ... |
@@ -1114,7 +1149,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
|
| 1114 | 1114 |
if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
|
| 1115 | 1115 |
return err |
| 1116 | 1116 |
} |
| 1117 |
- if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil {
|
|
| 1117 |
+ if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
|
|
| 1118 | 1118 |
return err |
| 1119 | 1119 |
} |
| 1120 | 1120 |
return nil |
| ... | ... |
@@ -1124,11 +1159,6 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
|
| 1124 | 1124 |
for _, key := range v.MapKeys() {
|
| 1125 | 1125 |
val := v.MapIndex(key) |
| 1126 | 1126 |
|
| 1127 |
- // The only illegal map entry values are nil message pointers. |
|
| 1128 |
- if val.Kind() == reflect.Ptr && val.IsNil() {
|
|
| 1129 |
- return errors.New("proto: map has nil element")
|
|
| 1130 |
- } |
|
| 1131 |
- |
|
| 1132 | 1127 |
keycopy.Set(key) |
| 1133 | 1128 |
valcopy.Set(val) |
| 1134 | 1129 |
|
| ... | ... |
@@ -1216,13 +1246,18 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
| 1216 | 1216 |
return err |
| 1217 | 1217 |
} |
| 1218 | 1218 |
} |
| 1219 |
+ if len(o.buf) > maxMarshalSize {
|
|
| 1220 |
+ return ErrTooLarge |
|
| 1221 |
+ } |
|
| 1219 | 1222 |
} |
| 1220 | 1223 |
} |
| 1221 | 1224 |
|
| 1222 | 1225 |
// Do oneof fields. |
| 1223 | 1226 |
if prop.oneofMarshaler != nil {
|
| 1224 | 1227 |
m := structPointer_Interface(base, prop.stype).(Message) |
| 1225 |
- if err := prop.oneofMarshaler(m, o); err != nil {
|
|
| 1228 |
+ if err := prop.oneofMarshaler(m, o); err == ErrNil {
|
|
| 1229 |
+ return errOneofHasNil |
|
| 1230 |
+ } else if err != nil {
|
|
| 1226 | 1231 |
return err |
| 1227 | 1232 |
} |
| 1228 | 1233 |
} |
| ... | ... |
@@ -1230,6 +1265,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
| 1230 | 1230 |
// Add unrecognized fields at the end. |
| 1231 | 1231 |
if prop.unrecField.IsValid() {
|
| 1232 | 1232 |
v := *structPointer_Bytes(base, prop.unrecField) |
| 1233 |
+ if len(o.buf)+len(v) > maxMarshalSize {
|
|
| 1234 |
+ return ErrTooLarge |
|
| 1235 |
+ } |
|
| 1233 | 1236 |
if len(v) > 0 {
|
| 1234 | 1237 |
o.buf = append(o.buf, v...) |
| 1235 | 1238 |
} |
| ... | ... |
@@ -54,13 +54,17 @@ Equality is defined in this way: |
| 54 | 54 |
in a proto3 .proto file, fields are not "set"; specifically, |
| 55 | 55 |
zero length proto3 "bytes" fields are equal (nil == {}).
|
| 56 | 56 |
- Two repeated fields are equal iff their lengths are the same, |
| 57 |
- and their corresponding elements are equal (a "bytes" field, |
|
| 58 |
- although represented by []byte, is not a repeated field) |
|
| 57 |
+ and their corresponding elements are equal. Note a "bytes" field, |
|
| 58 |
+ although represented by []byte, is not a repeated field and the |
|
| 59 |
+ rule for the scalar fields described above applies. |
|
| 59 | 60 |
- Two unset fields are equal. |
| 60 | 61 |
- Two unknown field sets are equal if their current |
| 61 | 62 |
encoded state is equal. |
| 62 | 63 |
- Two extension sets are equal iff they have corresponding |
| 63 | 64 |
elements that are pairwise equal. |
| 65 |
+ - Two map fields are equal iff their lengths are the same, |
|
| 66 |
+ and they contain the same set of elements. Zero-length map |
|
| 67 |
+ fields are equal. |
|
| 64 | 68 |
- Every other combination of things are not equal. |
| 65 | 69 |
|
| 66 | 70 |
The return value is undefined if a and b are not protocol buffers. |
| ... | ... |
@@ -121,9 +125,16 @@ func equalStruct(v1, v2 reflect.Value) bool {
|
| 121 | 121 |
} |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 |
+ if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
|
|
| 125 |
+ em2 := v2.FieldByName("XXX_InternalExtensions")
|
|
| 126 |
+ if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
|
|
| 127 |
+ return false |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 124 | 131 |
if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
|
| 125 | 132 |
em2 := v2.FieldByName("XXX_extensions")
|
| 126 |
- if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
| 133 |
+ if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
| 127 | 134 |
return false |
| 128 | 135 |
} |
| 129 | 136 |
} |
| ... | ... |
@@ -184,6 +195,13 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
| 184 | 184 |
} |
| 185 | 185 |
return true |
| 186 | 186 |
case reflect.Ptr: |
| 187 |
+ // Maps may have nil values in them, so check for nil. |
|
| 188 |
+ if v1.IsNil() && v2.IsNil() {
|
|
| 189 |
+ return true |
|
| 190 |
+ } |
|
| 191 |
+ if v1.IsNil() != v2.IsNil() {
|
|
| 192 |
+ return false |
|
| 193 |
+ } |
|
| 187 | 194 |
return equalAny(v1.Elem(), v2.Elem(), prop) |
| 188 | 195 |
case reflect.Slice: |
| 189 | 196 |
if v1.Type().Elem().Kind() == reflect.Uint8 {
|
| ... | ... |
@@ -223,8 +241,14 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 | 225 |
// base is the struct type that the extensions are based on. |
| 226 |
-// em1 and em2 are extension maps. |
|
| 227 |
-func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
| 226 |
+// x1 and x2 are InternalExtensions. |
|
| 227 |
+func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
|
|
| 228 |
+ em1, _ := x1.extensionsRead() |
|
| 229 |
+ em2, _ := x2.extensionsRead() |
|
| 230 |
+ return equalExtMap(base, em1, em2) |
|
| 231 |
+} |
|
| 232 |
+ |
|
| 233 |
+func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
| 228 | 234 |
if len(em1) != len(em2) {
|
| 229 | 235 |
return false |
| 230 | 236 |
} |
| ... | ... |
@@ -52,14 +52,99 @@ type ExtensionRange struct {
|
| 52 | 52 |
Start, End int32 // both inclusive |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
-// extendableProto is an interface implemented by any protocol buffer that may be extended. |
|
| 55 |
+// extendableProto is an interface implemented by any protocol buffer generated by the current |
|
| 56 |
+// proto compiler that may be extended. |
|
| 56 | 57 |
type extendableProto interface {
|
| 57 | 58 |
Message |
| 58 | 59 |
ExtensionRangeArray() []ExtensionRange |
| 60 |
+ extensionsWrite() map[int32]Extension |
|
| 61 |
+ extensionsRead() (map[int32]Extension, sync.Locker) |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous |
|
| 65 |
+// version of the proto compiler that may be extended. |
|
| 66 |
+type extendableProtoV1 interface {
|
|
| 67 |
+ Message |
|
| 68 |
+ ExtensionRangeArray() []ExtensionRange |
|
| 59 | 69 |
ExtensionMap() map[int32]Extension |
| 60 | 70 |
} |
| 61 | 71 |
|
| 72 |
+// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. |
|
| 73 |
+type extensionAdapter struct {
|
|
| 74 |
+ extendableProtoV1 |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+func (e extensionAdapter) extensionsWrite() map[int32]Extension {
|
|
| 78 |
+ return e.ExtensionMap() |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
| 82 |
+ return e.ExtensionMap(), notLocker{}
|
|
| 83 |
+} |
|
| 84 |
+ |
|
| 85 |
+// notLocker is a sync.Locker whose Lock and Unlock methods are nops. |
|
| 86 |
+type notLocker struct{}
|
|
| 87 |
+ |
|
| 88 |
+func (n notLocker) Lock() {}
|
|
| 89 |
+func (n notLocker) Unlock() {}
|
|
| 90 |
+ |
|
| 91 |
+// extendable returns the extendableProto interface for the given generated proto message. |
|
| 92 |
+// If the proto message has the old extension format, it returns a wrapper that implements |
|
| 93 |
+// the extendableProto interface. |
|
| 94 |
+func extendable(p interface{}) (extendableProto, bool) {
|
|
| 95 |
+ if ep, ok := p.(extendableProto); ok {
|
|
| 96 |
+ return ep, ok |
|
| 97 |
+ } |
|
| 98 |
+ if ep, ok := p.(extendableProtoV1); ok {
|
|
| 99 |
+ return extensionAdapter{ep}, ok
|
|
| 100 |
+ } |
|
| 101 |
+ return nil, false |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+// XXX_InternalExtensions is an internal representation of proto extensions. |
|
| 105 |
+// |
|
| 106 |
+// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, |
|
| 107 |
+// thus gaining the unexported 'extensions' method, which can be called only from the proto package. |
|
| 108 |
+// |
|
| 109 |
+// The methods of XXX_InternalExtensions are not concurrency safe in general, |
|
| 110 |
+// but calls to logically read-only methods such as has and get may be executed concurrently. |
|
| 111 |
+type XXX_InternalExtensions struct {
|
|
| 112 |
+ // The struct must be indirect so that if a user inadvertently copies a |
|
| 113 |
+ // generated message and its embedded XXX_InternalExtensions, they |
|
| 114 |
+ // avoid the mayhem of a copied mutex. |
|
| 115 |
+ // |
|
| 116 |
+ // The mutex serializes all logically read-only operations to p.extensionMap. |
|
| 117 |
+ // It is up to the client to ensure that write operations to p.extensionMap are |
|
| 118 |
+ // mutually exclusive with other accesses. |
|
| 119 |
+ p *struct {
|
|
| 120 |
+ mu sync.Mutex |
|
| 121 |
+ extensionMap map[int32]Extension |
|
| 122 |
+ } |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+// extensionsWrite returns the extension map, creating it on first use. |
|
| 126 |
+func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
|
|
| 127 |
+ if e.p == nil {
|
|
| 128 |
+ e.p = new(struct {
|
|
| 129 |
+ mu sync.Mutex |
|
| 130 |
+ extensionMap map[int32]Extension |
|
| 131 |
+ }) |
|
| 132 |
+ e.p.extensionMap = make(map[int32]Extension) |
|
| 133 |
+ } |
|
| 134 |
+ return e.p.extensionMap |
|
| 135 |
+} |
|
| 136 |
+ |
|
| 137 |
+// extensionsRead returns the extensions map for read-only use. It may be nil. |
|
| 138 |
+// The caller must hold the returned mutex's lock when accessing Elements within the map. |
|
| 139 |
+func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
| 140 |
+ if e.p == nil {
|
|
| 141 |
+ return nil, nil |
|
| 142 |
+ } |
|
| 143 |
+ return e.p.extensionMap, &e.p.mu |
|
| 144 |
+} |
|
| 145 |
+ |
|
| 62 | 146 |
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() |
| 147 |
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() |
|
| 63 | 148 |
|
| 64 | 149 |
// ExtensionDesc represents an extension specification. |
| 65 | 150 |
// Used in generated code from the protocol compiler. |
| ... | ... |
@@ -92,8 +177,13 @@ type Extension struct {
|
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 | 94 |
// SetRawExtension is for testing only. |
| 95 |
-func SetRawExtension(base extendableProto, id int32, b []byte) {
|
|
| 96 |
- base.ExtensionMap()[id] = Extension{enc: b}
|
|
| 95 |
+func SetRawExtension(base Message, id int32, b []byte) {
|
|
| 96 |
+ epb, ok := extendable(base) |
|
| 97 |
+ if !ok {
|
|
| 98 |
+ return |
|
| 99 |
+ } |
|
| 100 |
+ extmap := epb.extensionsWrite() |
|
| 101 |
+ extmap[id] = Extension{enc: b}
|
|
| 97 | 102 |
} |
| 98 | 103 |
|
| 99 | 104 |
// isExtensionField returns true iff the given field number is in an extension range. |
| ... | ... |
@@ -108,8 +198,12 @@ func isExtensionField(pb extendableProto, field int32) bool {
|
| 108 | 108 |
|
| 109 | 109 |
// checkExtensionTypes checks that the given extension is valid for pb. |
| 110 | 110 |
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
|
| 111 |
+ var pbi interface{} = pb
|
|
| 111 | 112 |
// Check the extended type. |
| 112 |
- if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
|
|
| 113 |
+ if ea, ok := pbi.(extensionAdapter); ok {
|
|
| 114 |
+ pbi = ea.extendableProtoV1 |
|
| 115 |
+ } |
|
| 116 |
+ if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
|
|
| 113 | 117 |
return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
|
| 114 | 118 |
} |
| 115 | 119 |
// Check the range. |
| ... | ... |
@@ -155,8 +249,19 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
|
| 155 | 155 |
return prop |
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 |
-// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. |
|
| 159 |
-func encodeExtensionMap(m map[int32]Extension) error {
|
|
| 158 |
+// encode encodes any unmarshaled (unencoded) extensions in e. |
|
| 159 |
+func encodeExtensions(e *XXX_InternalExtensions) error {
|
|
| 160 |
+ m, mu := e.extensionsRead() |
|
| 161 |
+ if m == nil {
|
|
| 162 |
+ return nil // fast path |
|
| 163 |
+ } |
|
| 164 |
+ mu.Lock() |
|
| 165 |
+ defer mu.Unlock() |
|
| 166 |
+ return encodeExtensionsMap(m) |
|
| 167 |
+} |
|
| 168 |
+ |
|
| 169 |
+// encode encodes any unmarshaled (unencoded) extensions in e. |
|
| 170 |
+func encodeExtensionsMap(m map[int32]Extension) error {
|
|
| 160 | 171 |
for k, e := range m {
|
| 161 | 172 |
if e.value == nil || e.desc == nil {
|
| 162 | 173 |
// Extension is only in its encoded form. |
| ... | ... |
@@ -184,7 +289,17 @@ func encodeExtensionMap(m map[int32]Extension) error {
|
| 184 | 184 |
return nil |
| 185 | 185 |
} |
| 186 | 186 |
|
| 187 |
-func sizeExtensionMap(m map[int32]Extension) (n int) {
|
|
| 187 |
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
|
|
| 188 |
+ m, mu := e.extensionsRead() |
|
| 189 |
+ if m == nil {
|
|
| 190 |
+ return 0 |
|
| 191 |
+ } |
|
| 192 |
+ mu.Lock() |
|
| 193 |
+ defer mu.Unlock() |
|
| 194 |
+ return extensionsMapSize(m) |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+func extensionsMapSize(m map[int32]Extension) (n int) {
|
|
| 188 | 198 |
for _, e := range m {
|
| 189 | 199 |
if e.value == nil || e.desc == nil {
|
| 190 | 200 |
// Extension is only in its encoded form. |
| ... | ... |
@@ -209,26 +324,51 @@ func sizeExtensionMap(m map[int32]Extension) (n int) {
|
| 209 | 209 |
} |
| 210 | 210 |
|
| 211 | 211 |
// HasExtension returns whether the given extension is present in pb. |
| 212 |
-func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
|
|
| 212 |
+func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
|
| 213 | 213 |
// TODO: Check types, field numbers, etc.? |
| 214 |
- _, ok := pb.ExtensionMap()[extension.Field] |
|
| 214 |
+ epb, ok := extendable(pb) |
|
| 215 |
+ if !ok {
|
|
| 216 |
+ return false |
|
| 217 |
+ } |
|
| 218 |
+ extmap, mu := epb.extensionsRead() |
|
| 219 |
+ if extmap == nil {
|
|
| 220 |
+ return false |
|
| 221 |
+ } |
|
| 222 |
+ mu.Lock() |
|
| 223 |
+ _, ok = extmap[extension.Field] |
|
| 224 |
+ mu.Unlock() |
|
| 215 | 225 |
return ok |
| 216 | 226 |
} |
| 217 | 227 |
|
| 218 | 228 |
// ClearExtension removes the given extension from pb. |
| 219 |
-func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
|
|
| 229 |
+func ClearExtension(pb Message, extension *ExtensionDesc) {
|
|
| 230 |
+ epb, ok := extendable(pb) |
|
| 231 |
+ if !ok {
|
|
| 232 |
+ return |
|
| 233 |
+ } |
|
| 220 | 234 |
// TODO: Check types, field numbers, etc.? |
| 221 |
- delete(pb.ExtensionMap(), extension.Field) |
|
| 235 |
+ extmap := epb.extensionsWrite() |
|
| 236 |
+ delete(extmap, extension.Field) |
|
| 222 | 237 |
} |
| 223 | 238 |
|
| 224 | 239 |
// GetExtension parses and returns the given extension of pb. |
| 225 | 240 |
// If the extension is not present and has no default value it returns ErrMissingExtension. |
| 226 |
-func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
|
|
| 227 |
- if err := checkExtensionTypes(pb, extension); err != nil {
|
|
| 241 |
+func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|
| 242 |
+ epb, ok := extendable(pb) |
|
| 243 |
+ if !ok {
|
|
| 244 |
+ return nil, errors.New("proto: not an extendable proto")
|
|
| 245 |
+ } |
|
| 246 |
+ |
|
| 247 |
+ if err := checkExtensionTypes(epb, extension); err != nil {
|
|
| 228 | 248 |
return nil, err |
| 229 | 249 |
} |
| 230 | 250 |
|
| 231 |
- emap := pb.ExtensionMap() |
|
| 251 |
+ emap, mu := epb.extensionsRead() |
|
| 252 |
+ if emap == nil {
|
|
| 253 |
+ return defaultExtensionValue(extension) |
|
| 254 |
+ } |
|
| 255 |
+ mu.Lock() |
|
| 256 |
+ defer mu.Unlock() |
|
| 232 | 257 |
e, ok := emap[extension.Field] |
| 233 | 258 |
if !ok {
|
| 234 | 259 |
// defaultExtensionValue returns the default value or |
| ... | ... |
@@ -332,10 +472,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
| 332 | 332 |
// GetExtensions returns a slice of the extensions present in pb that are also listed in es. |
| 333 | 333 |
// The returned slice has the same length as es; missing extensions will appear as nil elements. |
| 334 | 334 |
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
|
| 335 |
- epb, ok := pb.(extendableProto) |
|
| 335 |
+ epb, ok := extendable(pb) |
|
| 336 | 336 |
if !ok {
|
| 337 |
- err = errors.New("proto: not an extendable proto")
|
|
| 338 |
- return |
|
| 337 |
+ return nil, errors.New("proto: not an extendable proto")
|
|
| 339 | 338 |
} |
| 340 | 339 |
extensions = make([]interface{}, len(es))
|
| 341 | 340 |
for i, e := range es {
|
| ... | ... |
@@ -350,9 +489,44 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
|
| 350 | 350 |
return |
| 351 | 351 |
} |
| 352 | 352 |
|
| 353 |
+// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. |
|
| 354 |
+// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing |
|
| 355 |
+// just the Field field, which defines the extension's field number. |
|
| 356 |
+func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
|
| 357 |
+ epb, ok := extendable(pb) |
|
| 358 |
+ if !ok {
|
|
| 359 |
+ return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
|
|
| 360 |
+ } |
|
| 361 |
+ registeredExtensions := RegisteredExtensions(pb) |
|
| 362 |
+ |
|
| 363 |
+ emap, mu := epb.extensionsRead() |
|
| 364 |
+ if emap == nil {
|
|
| 365 |
+ return nil, nil |
|
| 366 |
+ } |
|
| 367 |
+ mu.Lock() |
|
| 368 |
+ defer mu.Unlock() |
|
| 369 |
+ extensions := make([]*ExtensionDesc, 0, len(emap)) |
|
| 370 |
+ for extid, e := range emap {
|
|
| 371 |
+ desc := e.desc |
|
| 372 |
+ if desc == nil {
|
|
| 373 |
+ desc = registeredExtensions[extid] |
|
| 374 |
+ if desc == nil {
|
|
| 375 |
+ desc = &ExtensionDesc{Field: extid}
|
|
| 376 |
+ } |
|
| 377 |
+ } |
|
| 378 |
+ |
|
| 379 |
+ extensions = append(extensions, desc) |
|
| 380 |
+ } |
|
| 381 |
+ return extensions, nil |
|
| 382 |
+} |
|
| 383 |
+ |
|
| 353 | 384 |
// SetExtension sets the specified extension of pb to the specified value. |
| 354 |
-func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error {
|
|
| 355 |
- if err := checkExtensionTypes(pb, extension); err != nil {
|
|
| 385 |
+func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
|
|
| 386 |
+ epb, ok := extendable(pb) |
|
| 387 |
+ if !ok {
|
|
| 388 |
+ return errors.New("proto: not an extendable proto")
|
|
| 389 |
+ } |
|
| 390 |
+ if err := checkExtensionTypes(epb, extension); err != nil {
|
|
| 356 | 391 |
return err |
| 357 | 392 |
} |
| 358 | 393 |
typ := reflect.TypeOf(extension.ExtensionType) |
| ... | ... |
@@ -368,10 +542,23 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
|
| 368 | 368 |
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
|
| 369 | 369 |
} |
| 370 | 370 |
|
| 371 |
- pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
|
|
| 371 |
+ extmap := epb.extensionsWrite() |
|
| 372 |
+ extmap[extension.Field] = Extension{desc: extension, value: value}
|
|
| 372 | 373 |
return nil |
| 373 | 374 |
} |
| 374 | 375 |
|
| 376 |
+// ClearAllExtensions clears all extensions from pb. |
|
| 377 |
+func ClearAllExtensions(pb Message) {
|
|
| 378 |
+ epb, ok := extendable(pb) |
|
| 379 |
+ if !ok {
|
|
| 380 |
+ return |
|
| 381 |
+ } |
|
| 382 |
+ m := epb.extensionsWrite() |
|
| 383 |
+ for k := range m {
|
|
| 384 |
+ delete(m, k) |
|
| 385 |
+ } |
|
| 386 |
+} |
|
| 387 |
+ |
|
| 375 | 388 |
// A global registry of extensions. |
| 376 | 389 |
// The generated code will register the generated descriptors by calling RegisterExtension. |
| 377 | 390 |
|
| ... | ... |
@@ -308,7 +308,7 @@ func GetStats() Stats { return stats }
|
| 308 | 308 |
// temporary Buffer and are fine for most applications. |
| 309 | 309 |
type Buffer struct {
|
| 310 | 310 |
buf []byte // encode/decode byte stream |
| 311 |
- index int // write point |
|
| 311 |
+ index int // read point |
|
| 312 | 312 |
|
| 313 | 313 |
// pools of basic types to amortize allocation. |
| 314 | 314 |
bools []bool |
| ... | ... |
@@ -889,6 +889,10 @@ func isProto3Zero(v reflect.Value) bool {
|
| 889 | 889 |
return false |
| 890 | 890 |
} |
| 891 | 891 |
|
| 892 |
+// ProtoPackageIsVersion2 is referenced from generated protocol buffer files |
|
| 893 |
+// to assert that that code is compatible with this version of the proto package. |
|
| 894 |
+const ProtoPackageIsVersion2 = true |
|
| 895 |
+ |
|
| 892 | 896 |
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files |
| 893 | 897 |
// to assert that that code is compatible with this version of the proto package. |
| 894 | 898 |
const ProtoPackageIsVersion1 = true |
| ... | ... |
@@ -149,9 +149,21 @@ func skipVarint(buf []byte) []byte {
|
| 149 | 149 |
|
| 150 | 150 |
// MarshalMessageSet encodes the extension map represented by m in the message set wire format. |
| 151 | 151 |
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. |
| 152 |
-func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
|
|
| 153 |
- if err := encodeExtensionMap(m); err != nil {
|
|
| 154 |
- return nil, err |
|
| 152 |
+func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
|
| 153 |
+ var m map[int32]Extension |
|
| 154 |
+ switch exts := exts.(type) {
|
|
| 155 |
+ case *XXX_InternalExtensions: |
|
| 156 |
+ if err := encodeExtensions(exts); err != nil {
|
|
| 157 |
+ return nil, err |
|
| 158 |
+ } |
|
| 159 |
+ m, _ = exts.extensionsRead() |
|
| 160 |
+ case map[int32]Extension: |
|
| 161 |
+ if err := encodeExtensionsMap(exts); err != nil {
|
|
| 162 |
+ return nil, err |
|
| 163 |
+ } |
|
| 164 |
+ m = exts |
|
| 165 |
+ default: |
|
| 166 |
+ return nil, errors.New("proto: not an extension map")
|
|
| 155 | 167 |
} |
| 156 | 168 |
|
| 157 | 169 |
// Sort extension IDs to provide a deterministic encoding. |
| ... | ... |
@@ -178,7 +190,17 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
|
| 178 | 178 |
|
| 179 | 179 |
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. |
| 180 | 180 |
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. |
| 181 |
-func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
|
|
| 181 |
+func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
|
| 182 |
+ var m map[int32]Extension |
|
| 183 |
+ switch exts := exts.(type) {
|
|
| 184 |
+ case *XXX_InternalExtensions: |
|
| 185 |
+ m = exts.extensionsWrite() |
|
| 186 |
+ case map[int32]Extension: |
|
| 187 |
+ m = exts |
|
| 188 |
+ default: |
|
| 189 |
+ return errors.New("proto: not an extension map")
|
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 182 | 192 |
ms := new(messageSet) |
| 183 | 193 |
if err := Unmarshal(buf, ms); err != nil {
|
| 184 | 194 |
return err |
| ... | ... |
@@ -209,7 +231,16 @@ func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
|
| 209 | 209 |
|
| 210 | 210 |
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. |
| 211 | 211 |
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. |
| 212 |
-func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) {
|
|
| 212 |
+func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
|
| 213 |
+ var m map[int32]Extension |
|
| 214 |
+ switch exts := exts.(type) {
|
|
| 215 |
+ case *XXX_InternalExtensions: |
|
| 216 |
+ m, _ = exts.extensionsRead() |
|
| 217 |
+ case map[int32]Extension: |
|
| 218 |
+ m = exts |
|
| 219 |
+ default: |
|
| 220 |
+ return nil, errors.New("proto: not an extension map")
|
|
| 221 |
+ } |
|
| 213 | 222 |
var b bytes.Buffer |
| 214 | 223 |
b.WriteByte('{')
|
| 215 | 224 |
|
| ... | ... |
@@ -252,7 +283,7 @@ func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) {
|
| 252 | 252 |
|
| 253 | 253 |
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. |
| 254 | 254 |
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. |
| 255 |
-func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error {
|
|
| 255 |
+func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
|
|
| 256 | 256 |
// Common-case fast path. |
| 257 | 257 |
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
|
| 258 | 258 |
return nil |
| ... | ... |
@@ -29,7 +29,7 @@ |
| 29 | 29 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | 30 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | 31 |
|
| 32 |
-// +build appengine |
|
| 32 |
+// +build appengine js |
|
| 33 | 33 |
|
| 34 | 34 |
// This file contains an implementation of proto field accesses using package reflect. |
| 35 | 35 |
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can |
| ... | ... |
@@ -139,6 +139,11 @@ func structPointer_StringSlice(p structPointer, f field) *[]string {
|
| 139 | 139 |
return structPointer_ifield(p, f).(*[]string) |
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 |
+// Extensions returns the address of an extension map field in the struct. |
|
| 143 |
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
| 144 |
+ return structPointer_ifield(p, f).(*XXX_InternalExtensions) |
|
| 145 |
+} |
|
| 146 |
+ |
|
| 142 | 147 |
// ExtMap returns the address of an extension map field in the struct. |
| 143 | 148 |
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
| 144 | 149 |
return structPointer_ifield(p, f).(*map[int32]Extension) |
| ... | ... |
@@ -29,7 +29,7 @@ |
| 29 | 29 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | 30 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | 31 |
|
| 32 |
-// +build !appengine |
|
| 32 |
+// +build !appengine,!js |
|
| 33 | 33 |
|
| 34 | 34 |
// This file contains the implementation of the proto field accesses using package unsafe. |
| 35 | 35 |
|
| ... | ... |
@@ -126,6 +126,10 @@ func structPointer_StringSlice(p structPointer, f field) *[]string {
|
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
// ExtMap returns the address of an extension map field in the struct. |
| 129 |
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
| 130 |
+ return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 129 | 133 |
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
| 130 | 134 |
return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 131 | 135 |
} |
| ... | ... |
@@ -473,17 +473,13 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock |
| 473 | 473 |
p.dec = (*Buffer).dec_slice_int64 |
| 474 | 474 |
p.packedDec = (*Buffer).dec_slice_packed_int64 |
| 475 | 475 |
case reflect.Uint8: |
| 476 |
- p.enc = (*Buffer).enc_slice_byte |
|
| 477 | 476 |
p.dec = (*Buffer).dec_slice_byte |
| 478 |
- p.size = size_slice_byte |
|
| 479 |
- // This is a []byte, which is either a bytes field, |
|
| 480 |
- // or the value of a map field. In the latter case, |
|
| 481 |
- // we always encode an empty []byte, so we should not |
|
| 482 |
- // use the proto3 enc/size funcs. |
|
| 483 |
- // f == nil iff this is the key/value of a map field. |
|
| 484 |
- if p.proto3 && f != nil {
|
|
| 477 |
+ if p.proto3 {
|
|
| 485 | 478 |
p.enc = (*Buffer).enc_proto3_slice_byte |
| 486 | 479 |
p.size = size_proto3_slice_byte |
| 480 |
+ } else {
|
|
| 481 |
+ p.enc = (*Buffer).enc_slice_byte |
|
| 482 |
+ p.size = size_slice_byte |
|
| 487 | 483 |
} |
| 488 | 484 |
case reflect.Float32, reflect.Float64: |
| 489 | 485 |
switch t2.Bits() {
|
| ... | ... |
@@ -682,7 +678,8 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 682 | 682 |
propertiesMap[t] = prop |
| 683 | 683 |
|
| 684 | 684 |
// build properties |
| 685 |
- prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) |
|
| 685 |
+ prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || |
|
| 686 |
+ reflect.PtrTo(t).Implements(extendableProtoV1Type) |
|
| 686 | 687 |
prop.unrecField = invalidField |
| 687 | 688 |
prop.Prop = make([]*Properties, t.NumField()) |
| 688 | 689 |
prop.order = make([]int, t.NumField()) |
| ... | ... |
@@ -693,15 +690,22 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 693 | 693 |
name := f.Name |
| 694 | 694 |
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
| 695 | 695 |
|
| 696 |
- if f.Name == "XXX_extensions" { // special case
|
|
| 696 |
+ if f.Name == "XXX_InternalExtensions" { // special case
|
|
| 697 |
+ p.enc = (*Buffer).enc_exts |
|
| 698 |
+ p.dec = nil // not needed |
|
| 699 |
+ p.size = size_exts |
|
| 700 |
+ } else if f.Name == "XXX_extensions" { // special case
|
|
| 697 | 701 |
p.enc = (*Buffer).enc_map |
| 698 | 702 |
p.dec = nil // not needed |
| 699 | 703 |
p.size = size_map |
| 700 |
- } |
|
| 701 |
- if f.Name == "XXX_unrecognized" { // special case
|
|
| 704 |
+ } else if f.Name == "XXX_unrecognized" { // special case
|
|
| 702 | 705 |
prop.unrecField = toField(&f) |
| 703 | 706 |
} |
| 704 |
- oneof := f.Tag.Get("protobuf_oneof") != "" // special case
|
|
| 707 |
+ oneof := f.Tag.Get("protobuf_oneof") // special case
|
|
| 708 |
+ if oneof != "" {
|
|
| 709 |
+ // Oneof fields don't use the traditional protobuf tag. |
|
| 710 |
+ p.OrigName = oneof |
|
| 711 |
+ } |
|
| 705 | 712 |
prop.Prop[i] = p |
| 706 | 713 |
prop.order[i] = i |
| 707 | 714 |
if debug {
|
| ... | ... |
@@ -711,7 +715,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
| 711 | 711 |
} |
| 712 | 712 |
print("\n")
|
| 713 | 713 |
} |
| 714 |
- if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
|
|
| 714 |
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
|
|
| 715 | 715 |
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") |
| 716 | 716 |
} |
| 717 | 717 |
} |
| ... | ... |
@@ -840,7 +844,29 @@ func RegisterType(x Message, name string) {
|
| 840 | 840 |
} |
| 841 | 841 |
|
| 842 | 842 |
// MessageName returns the fully-qualified proto name for the given message type. |
| 843 |
-func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
|
|
| 843 |
+func MessageName(x Message) string {
|
|
| 844 |
+ type xname interface {
|
|
| 845 |
+ XXX_MessageName() string |
|
| 846 |
+ } |
|
| 847 |
+ if m, ok := x.(xname); ok {
|
|
| 848 |
+ return m.XXX_MessageName() |
|
| 849 |
+ } |
|
| 850 |
+ return revProtoTypes[reflect.TypeOf(x)] |
|
| 851 |
+} |
|
| 844 | 852 |
|
| 845 | 853 |
// MessageType returns the message type (pointer to struct) for a named message. |
| 846 | 854 |
func MessageType(name string) reflect.Type { return protoTypes[name] }
|
| 855 |
+ |
|
| 856 |
+// A registry of all linked proto files. |
|
| 857 |
+var ( |
|
| 858 |
+ protoFiles = make(map[string][]byte) // file name => fileDescriptor |
|
| 859 |
+) |
|
| 860 |
+ |
|
| 861 |
+// RegisterFile is called from generated code and maps from the |
|
| 862 |
+// full file name of a .proto file to its compressed FileDescriptorProto. |
|
| 863 |
+func RegisterFile(filename string, fileDescriptor []byte) {
|
|
| 864 |
+ protoFiles[filename] = fileDescriptor |
|
| 865 |
+} |
|
| 866 |
+ |
|
| 867 |
+// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. |
|
| 868 |
+func FileDescriptor(filename string) []byte { return protoFiles[filename] }
|
| ... | ... |
@@ -154,7 +154,7 @@ func (w *textWriter) indent() { w.ind++ }
|
| 154 | 154 |
|
| 155 | 155 |
func (w *textWriter) unindent() {
|
| 156 | 156 |
if w.ind == 0 {
|
| 157 |
- log.Printf("proto: textWriter unindented too far")
|
|
| 157 |
+ log.Print("proto: textWriter unindented too far")
|
|
| 158 | 158 |
return |
| 159 | 159 |
} |
| 160 | 160 |
w.ind-- |
| ... | ... |
@@ -175,7 +175,93 @@ type raw interface {
|
| 175 | 175 |
Bytes() []byte |
| 176 | 176 |
} |
| 177 | 177 |
|
| 178 |
-func writeStruct(w *textWriter, sv reflect.Value) error {
|
|
| 178 |
+func requiresQuotes(u string) bool {
|
|
| 179 |
+ // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. |
|
| 180 |
+ for _, ch := range u {
|
|
| 181 |
+ switch {
|
|
| 182 |
+ case ch == '.' || ch == '/' || ch == '_': |
|
| 183 |
+ continue |
|
| 184 |
+ case '0' <= ch && ch <= '9': |
|
| 185 |
+ continue |
|
| 186 |
+ case 'A' <= ch && ch <= 'Z': |
|
| 187 |
+ continue |
|
| 188 |
+ case 'a' <= ch && ch <= 'z': |
|
| 189 |
+ continue |
|
| 190 |
+ default: |
|
| 191 |
+ return true |
|
| 192 |
+ } |
|
| 193 |
+ } |
|
| 194 |
+ return false |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+// isAny reports whether sv is a google.protobuf.Any message |
|
| 198 |
+func isAny(sv reflect.Value) bool {
|
|
| 199 |
+ type wkt interface {
|
|
| 200 |
+ XXX_WellKnownType() string |
|
| 201 |
+ } |
|
| 202 |
+ t, ok := sv.Addr().Interface().(wkt) |
|
| 203 |
+ return ok && t.XXX_WellKnownType() == "Any" |
|
| 204 |
+} |
|
| 205 |
+ |
|
| 206 |
+// writeProto3Any writes an expanded google.protobuf.Any message. |
|
| 207 |
+// |
|
| 208 |
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because |
|
| 209 |
+// required messages are not linked in). |
|
| 210 |
+// |
|
| 211 |
+// It returns (true, error) when sv was written in expanded format or an error |
|
| 212 |
+// was encountered. |
|
| 213 |
+func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
|
|
| 214 |
+ turl := sv.FieldByName("TypeUrl")
|
|
| 215 |
+ val := sv.FieldByName("Value")
|
|
| 216 |
+ if !turl.IsValid() || !val.IsValid() {
|
|
| 217 |
+ return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
| 218 |
+ } |
|
| 219 |
+ |
|
| 220 |
+ b, ok := val.Interface().([]byte) |
|
| 221 |
+ if !ok {
|
|
| 222 |
+ return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
| 223 |
+ } |
|
| 224 |
+ |
|
| 225 |
+ parts := strings.Split(turl.String(), "/") |
|
| 226 |
+ mt := MessageType(parts[len(parts)-1]) |
|
| 227 |
+ if mt == nil {
|
|
| 228 |
+ return false, nil |
|
| 229 |
+ } |
|
| 230 |
+ m := reflect.New(mt.Elem()) |
|
| 231 |
+ if err := Unmarshal(b, m.Interface().(Message)); err != nil {
|
|
| 232 |
+ return false, nil |
|
| 233 |
+ } |
|
| 234 |
+ w.Write([]byte("["))
|
|
| 235 |
+ u := turl.String() |
|
| 236 |
+ if requiresQuotes(u) {
|
|
| 237 |
+ writeString(w, u) |
|
| 238 |
+ } else {
|
|
| 239 |
+ w.Write([]byte(u)) |
|
| 240 |
+ } |
|
| 241 |
+ if w.compact {
|
|
| 242 |
+ w.Write([]byte("]:<"))
|
|
| 243 |
+ } else {
|
|
| 244 |
+ w.Write([]byte("]: <\n"))
|
|
| 245 |
+ w.ind++ |
|
| 246 |
+ } |
|
| 247 |
+ if err := tm.writeStruct(w, m.Elem()); err != nil {
|
|
| 248 |
+ return true, err |
|
| 249 |
+ } |
|
| 250 |
+ if w.compact {
|
|
| 251 |
+ w.Write([]byte("> "))
|
|
| 252 |
+ } else {
|
|
| 253 |
+ w.ind-- |
|
| 254 |
+ w.Write([]byte(">\n"))
|
|
| 255 |
+ } |
|
| 256 |
+ return true, nil |
|
| 257 |
+} |
|
| 258 |
+ |
|
| 259 |
+func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|
| 260 |
+ if tm.ExpandAny && isAny(sv) {
|
|
| 261 |
+ if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
|
|
| 262 |
+ return err |
|
| 263 |
+ } |
|
| 264 |
+ } |
|
| 179 | 265 |
st := sv.Type() |
| 180 | 266 |
sprops := GetProperties(st) |
| 181 | 267 |
for i := 0; i < sv.NumField(); i++ {
|
| ... | ... |
@@ -227,7 +313,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 227 | 227 |
} |
| 228 | 228 |
continue |
| 229 | 229 |
} |
| 230 |
- if err := writeAny(w, v, props); err != nil {
|
|
| 230 |
+ if err := tm.writeAny(w, v, props); err != nil {
|
|
| 231 | 231 |
return err |
| 232 | 232 |
} |
| 233 | 233 |
if err := w.WriteByte('\n'); err != nil {
|
| ... | ... |
@@ -269,7 +355,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 269 | 269 |
return err |
| 270 | 270 |
} |
| 271 | 271 |
} |
| 272 |
- if err := writeAny(w, key, props.mkeyprop); err != nil {
|
|
| 272 |
+ if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
|
|
| 273 | 273 |
return err |
| 274 | 274 |
} |
| 275 | 275 |
if err := w.WriteByte('\n'); err != nil {
|
| ... | ... |
@@ -286,7 +372,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 286 | 286 |
return err |
| 287 | 287 |
} |
| 288 | 288 |
} |
| 289 |
- if err := writeAny(w, val, props.mvalprop); err != nil {
|
|
| 289 |
+ if err := tm.writeAny(w, val, props.mvalprop); err != nil {
|
|
| 290 | 290 |
return err |
| 291 | 291 |
} |
| 292 | 292 |
if err := w.WriteByte('\n'); err != nil {
|
| ... | ... |
@@ -358,7 +444,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 358 | 358 |
} |
| 359 | 359 |
|
| 360 | 360 |
// Enums have a String method, so writeAny will work fine. |
| 361 |
- if err := writeAny(w, fv, props); err != nil {
|
|
| 361 |
+ if err := tm.writeAny(w, fv, props); err != nil {
|
|
| 362 | 362 |
return err |
| 363 | 363 |
} |
| 364 | 364 |
|
| ... | ... |
@@ -369,8 +455,8 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
|
| 369 | 369 |
|
| 370 | 370 |
// Extensions (the XXX_extensions field). |
| 371 | 371 |
pv := sv.Addr() |
| 372 |
- if pv.Type().Implements(extendableProtoType) {
|
|
| 373 |
- if err := writeExtensions(w, pv); err != nil {
|
|
| 372 |
+ if _, ok := extendable(pv.Interface()); ok {
|
|
| 373 |
+ if err := tm.writeExtensions(w, pv); err != nil {
|
|
| 374 | 374 |
return err |
| 375 | 375 |
} |
| 376 | 376 |
} |
| ... | ... |
@@ -400,7 +486,7 @@ func writeRaw(w *textWriter, b []byte) error {
|
| 400 | 400 |
} |
| 401 | 401 |
|
| 402 | 402 |
// writeAny writes an arbitrary field. |
| 403 |
-func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
|
| 403 |
+func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
|
| 404 | 404 |
v = reflect.Indirect(v) |
| 405 | 405 |
|
| 406 | 406 |
// Floats have special cases. |
| ... | ... |
@@ -427,7 +513,7 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
| 427 | 427 |
switch v.Kind() {
|
| 428 | 428 |
case reflect.Slice: |
| 429 | 429 |
// Should only be a []byte; repeated fields are handled in writeStruct. |
| 430 |
- if err := writeString(w, string(v.Interface().([]byte))); err != nil {
|
|
| 430 |
+ if err := writeString(w, string(v.Bytes())); err != nil {
|
|
| 431 | 431 |
return err |
| 432 | 432 |
} |
| 433 | 433 |
case reflect.String: |
| ... | ... |
@@ -449,15 +535,15 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
| 449 | 449 |
} |
| 450 | 450 |
} |
| 451 | 451 |
w.indent() |
| 452 |
- if tm, ok := v.Interface().(encoding.TextMarshaler); ok {
|
|
| 453 |
- text, err := tm.MarshalText() |
|
| 452 |
+ if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
|
|
| 453 |
+ text, err := etm.MarshalText() |
|
| 454 | 454 |
if err != nil {
|
| 455 | 455 |
return err |
| 456 | 456 |
} |
| 457 | 457 |
if _, err = w.Write(text); err != nil {
|
| 458 | 458 |
return err |
| 459 | 459 |
} |
| 460 |
- } else if err := writeStruct(w, v); err != nil {
|
|
| 460 |
+ } else if err := tm.writeStruct(w, v); err != nil {
|
|
| 461 | 461 |
return err |
| 462 | 462 |
} |
| 463 | 463 |
w.unindent() |
| ... | ... |
@@ -601,19 +687,24 @@ func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
| 601 | 601 |
|
| 602 | 602 |
// writeExtensions writes all the extensions in pv. |
| 603 | 603 |
// pv is assumed to be a pointer to a protocol message struct that is extendable. |
| 604 |
-func writeExtensions(w *textWriter, pv reflect.Value) error {
|
|
| 604 |
+func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
|
|
| 605 | 605 |
emap := extensionMaps[pv.Type().Elem()] |
| 606 |
- ep := pv.Interface().(extendableProto) |
|
| 606 |
+ ep, _ := extendable(pv.Interface()) |
|
| 607 | 607 |
|
| 608 | 608 |
// Order the extensions by ID. |
| 609 | 609 |
// This isn't strictly necessary, but it will give us |
| 610 | 610 |
// canonical output, which will also make testing easier. |
| 611 |
- m := ep.ExtensionMap() |
|
| 611 |
+ m, mu := ep.extensionsRead() |
|
| 612 |
+ if m == nil {
|
|
| 613 |
+ return nil |
|
| 614 |
+ } |
|
| 615 |
+ mu.Lock() |
|
| 612 | 616 |
ids := make([]int32, 0, len(m)) |
| 613 | 617 |
for id := range m {
|
| 614 | 618 |
ids = append(ids, id) |
| 615 | 619 |
} |
| 616 | 620 |
sort.Sort(int32Slice(ids)) |
| 621 |
+ mu.Unlock() |
|
| 617 | 622 |
|
| 618 | 623 |
for _, extNum := range ids {
|
| 619 | 624 |
ext := m[extNum] |
| ... | ... |
@@ -636,13 +727,13 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
|
| 636 | 636 |
|
| 637 | 637 |
// Repeated extensions will appear as a slice. |
| 638 | 638 |
if !desc.repeated() {
|
| 639 |
- if err := writeExtension(w, desc.Name, pb); err != nil {
|
|
| 639 |
+ if err := tm.writeExtension(w, desc.Name, pb); err != nil {
|
|
| 640 | 640 |
return err |
| 641 | 641 |
} |
| 642 | 642 |
} else {
|
| 643 | 643 |
v := reflect.ValueOf(pb) |
| 644 | 644 |
for i := 0; i < v.Len(); i++ {
|
| 645 |
- if err := writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
|
|
| 645 |
+ if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
|
|
| 646 | 646 |
return err |
| 647 | 647 |
} |
| 648 | 648 |
} |
| ... | ... |
@@ -651,7 +742,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
|
| 651 | 651 |
return nil |
| 652 | 652 |
} |
| 653 | 653 |
|
| 654 |
-func writeExtension(w *textWriter, name string, pb interface{}) error {
|
|
| 654 |
+func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
|
|
| 655 | 655 |
if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
|
| 656 | 656 |
return err |
| 657 | 657 |
} |
| ... | ... |
@@ -660,7 +751,7 @@ func writeExtension(w *textWriter, name string, pb interface{}) error {
|
| 660 | 660 |
return err |
| 661 | 661 |
} |
| 662 | 662 |
} |
| 663 |
- if err := writeAny(w, reflect.ValueOf(pb), nil); err != nil {
|
|
| 663 |
+ if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
|
|
| 664 | 664 |
return err |
| 665 | 665 |
} |
| 666 | 666 |
if err := w.WriteByte('\n'); err != nil {
|
| ... | ... |
@@ -687,12 +778,13 @@ func (w *textWriter) writeIndent() {
|
| 687 | 687 |
|
| 688 | 688 |
// TextMarshaler is a configurable text format marshaler. |
| 689 | 689 |
type TextMarshaler struct {
|
| 690 |
- Compact bool // use compact text format (one line). |
|
| 690 |
+ Compact bool // use compact text format (one line). |
|
| 691 |
+ ExpandAny bool // expand google.protobuf.Any messages of known types |
|
| 691 | 692 |
} |
| 692 | 693 |
|
| 693 | 694 |
// Marshal writes a given protocol buffer in text format. |
| 694 | 695 |
// The only errors returned are from w. |
| 695 |
-func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
|
| 696 |
+func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
|
| 696 | 697 |
val := reflect.ValueOf(pb) |
| 697 | 698 |
if pb == nil || val.IsNil() {
|
| 698 | 699 |
w.Write([]byte("<nil>"))
|
| ... | ... |
@@ -707,11 +799,11 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
| 707 | 707 |
aw := &textWriter{
|
| 708 | 708 |
w: ww, |
| 709 | 709 |
complete: true, |
| 710 |
- compact: m.Compact, |
|
| 710 |
+ compact: tm.Compact, |
|
| 711 | 711 |
} |
| 712 | 712 |
|
| 713 |
- if tm, ok := pb.(encoding.TextMarshaler); ok {
|
|
| 714 |
- text, err := tm.MarshalText() |
|
| 713 |
+ if etm, ok := pb.(encoding.TextMarshaler); ok {
|
|
| 714 |
+ text, err := etm.MarshalText() |
|
| 715 | 715 |
if err != nil {
|
| 716 | 716 |
return err |
| 717 | 717 |
} |
| ... | ... |
@@ -725,7 +817,7 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
| 725 | 725 |
} |
| 726 | 726 |
// Dereference the received pointer so we don't have outer < and >. |
| 727 | 727 |
v := reflect.Indirect(val) |
| 728 |
- if err := writeStruct(aw, v); err != nil {
|
|
| 728 |
+ if err := tm.writeStruct(aw, v); err != nil {
|
|
| 729 | 729 |
return err |
| 730 | 730 |
} |
| 731 | 731 |
if bw != nil {
|
| ... | ... |
@@ -735,9 +827,9 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
| 735 | 735 |
} |
| 736 | 736 |
|
| 737 | 737 |
// Text is the same as Marshal, but returns the string directly. |
| 738 |
-func (m *TextMarshaler) Text(pb Message) string {
|
|
| 738 |
+func (tm *TextMarshaler) Text(pb Message) string {
|
|
| 739 | 739 |
var buf bytes.Buffer |
| 740 |
- m.Marshal(&buf, pb) |
|
| 740 |
+ tm.Marshal(&buf, pb) |
|
| 741 | 741 |
return buf.String() |
| 742 | 742 |
} |
| 743 | 743 |
|
| ... | ... |
@@ -44,6 +44,9 @@ import ( |
| 44 | 44 |
"unicode/utf8" |
| 45 | 45 |
) |
| 46 | 46 |
|
| 47 |
+// Error string emitted when deserializing Any and fields are already set |
|
| 48 |
+const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" |
|
| 49 |
+ |
|
| 47 | 50 |
type ParseError struct {
|
| 48 | 51 |
Message string |
| 49 | 52 |
Line int // 1-based line number |
| ... | ... |
@@ -163,7 +166,7 @@ func (p *textParser) advance() {
|
| 163 | 163 |
p.cur.offset, p.cur.line = p.offset, p.line |
| 164 | 164 |
p.cur.unquoted = "" |
| 165 | 165 |
switch p.s[0] {
|
| 166 |
- case '<', '>', '{', '}', ':', '[', ']', ';', ',':
|
|
| 166 |
+ case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
|
| 167 | 167 |
// Single symbol |
| 168 | 168 |
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] |
| 169 | 169 |
case '"', '\'': |
| ... | ... |
@@ -451,7 +454,10 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 451 | 451 |
fieldSet := make(map[string]bool) |
| 452 | 452 |
// A struct is a sequence of "name: value", terminated by one of |
| 453 | 453 |
// '>' or '}', or the end of the input. A name may also be |
| 454 |
- // "[extension]". |
|
| 454 |
+ // "[extension]" or "[type/url]". |
|
| 455 |
+ // |
|
| 456 |
+ // The whole struct can also be an expanded Any message, like: |
|
| 457 |
+ // [type/url] < ... struct contents ... > |
|
| 455 | 458 |
for {
|
| 456 | 459 |
tok := p.next() |
| 457 | 460 |
if tok.err != nil {
|
| ... | ... |
@@ -461,33 +467,74 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 461 | 461 |
break |
| 462 | 462 |
} |
| 463 | 463 |
if tok.value == "[" {
|
| 464 |
- // Looks like an extension. |
|
| 464 |
+ // Looks like an extension or an Any. |
|
| 465 | 465 |
// |
| 466 | 466 |
// TODO: Check whether we need to handle |
| 467 | 467 |
// namespace rooted names (e.g. ".something.Foo"). |
| 468 |
- tok = p.next() |
|
| 469 |
- if tok.err != nil {
|
|
| 470 |
- return tok.err |
|
| 468 |
+ extName, err := p.consumeExtName() |
|
| 469 |
+ if err != nil {
|
|
| 470 |
+ return err |
|
| 471 |
+ } |
|
| 472 |
+ |
|
| 473 |
+ if s := strings.LastIndex(extName, "/"); s >= 0 {
|
|
| 474 |
+ // If it contains a slash, it's an Any type URL. |
|
| 475 |
+ messageName := extName[s+1:] |
|
| 476 |
+ mt := MessageType(messageName) |
|
| 477 |
+ if mt == nil {
|
|
| 478 |
+ return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
|
|
| 479 |
+ } |
|
| 480 |
+ tok = p.next() |
|
| 481 |
+ if tok.err != nil {
|
|
| 482 |
+ return tok.err |
|
| 483 |
+ } |
|
| 484 |
+ // consume an optional colon |
|
| 485 |
+ if tok.value == ":" {
|
|
| 486 |
+ tok = p.next() |
|
| 487 |
+ if tok.err != nil {
|
|
| 488 |
+ return tok.err |
|
| 489 |
+ } |
|
| 490 |
+ } |
|
| 491 |
+ var terminator string |
|
| 492 |
+ switch tok.value {
|
|
| 493 |
+ case "<": |
|
| 494 |
+ terminator = ">" |
|
| 495 |
+ case "{":
|
|
| 496 |
+ terminator = "}" |
|
| 497 |
+ default: |
|
| 498 |
+ return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
| 499 |
+ } |
|
| 500 |
+ v := reflect.New(mt.Elem()) |
|
| 501 |
+ if pe := p.readStruct(v.Elem(), terminator); pe != nil {
|
|
| 502 |
+ return pe |
|
| 503 |
+ } |
|
| 504 |
+ b, err := Marshal(v.Interface().(Message)) |
|
| 505 |
+ if err != nil {
|
|
| 506 |
+ return p.errorf("failed to marshal message of type %q: %v", messageName, err)
|
|
| 507 |
+ } |
|
| 508 |
+ if fieldSet["type_url"] {
|
|
| 509 |
+ return p.errorf(anyRepeatedlyUnpacked, "type_url") |
|
| 510 |
+ } |
|
| 511 |
+ if fieldSet["value"] {
|
|
| 512 |
+ return p.errorf(anyRepeatedlyUnpacked, "value") |
|
| 513 |
+ } |
|
| 514 |
+ sv.FieldByName("TypeUrl").SetString(extName)
|
|
| 515 |
+ sv.FieldByName("Value").SetBytes(b)
|
|
| 516 |
+ fieldSet["type_url"] = true |
|
| 517 |
+ fieldSet["value"] = true |
|
| 518 |
+ continue |
|
| 471 | 519 |
} |
| 520 |
+ |
|
| 472 | 521 |
var desc *ExtensionDesc |
| 473 | 522 |
// This could be faster, but it's functional. |
| 474 | 523 |
// TODO: Do something smarter than a linear scan. |
| 475 | 524 |
for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
|
| 476 |
- if d.Name == tok.value {
|
|
| 525 |
+ if d.Name == extName {
|
|
| 477 | 526 |
desc = d |
| 478 | 527 |
break |
| 479 | 528 |
} |
| 480 | 529 |
} |
| 481 | 530 |
if desc == nil {
|
| 482 |
- return p.errorf("unrecognized extension %q", tok.value)
|
|
| 483 |
- } |
|
| 484 |
- // Check the extension terminator. |
|
| 485 |
- tok = p.next() |
|
| 486 |
- if tok.err != nil {
|
|
| 487 |
- return tok.err |
|
| 488 |
- } |
|
| 489 |
- if tok.value != "]" {
|
|
| 490 |
- return p.errorf("unrecognized extension terminator %q", tok.value)
|
|
| 531 |
+ return p.errorf("unrecognized extension %q", extName)
|
|
| 491 | 532 |
} |
| 492 | 533 |
|
| 493 | 534 |
props := &Properties{}
|
| ... | ... |
@@ -514,7 +561,7 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 514 | 514 |
} |
| 515 | 515 |
reqFieldErr = err |
| 516 | 516 |
} |
| 517 |
- ep := sv.Addr().Interface().(extendableProto) |
|
| 517 |
+ ep := sv.Addr().Interface().(Message) |
|
| 518 | 518 |
if !rep {
|
| 519 | 519 |
SetExtension(ep, desc, ext.Interface()) |
| 520 | 520 |
} else {
|
| ... | ... |
@@ -566,8 +613,9 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 566 | 566 |
|
| 567 | 567 |
// The map entry should be this sequence of tokens: |
| 568 | 568 |
// < key : KEY value : VALUE > |
| 569 |
- // Technically the "key" and "value" could come in any order, |
|
| 570 |
- // but in practice they won't. |
|
| 569 |
+ // However, implementations may omit key or value, and technically |
|
| 570 |
+ // we should support them in any order. See b/28924776 for a time |
|
| 571 |
+ // this went wrong. |
|
| 571 | 572 |
|
| 572 | 573 |
tok := p.next() |
| 573 | 574 |
var terminator string |
| ... | ... |
@@ -579,32 +627,39 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 579 | 579 |
default: |
| 580 | 580 |
return p.errorf("expected '{' or '<', found %q", tok.value)
|
| 581 | 581 |
} |
| 582 |
- if err := p.consumeToken("key"); err != nil {
|
|
| 583 |
- return err |
|
| 584 |
- } |
|
| 585 |
- if err := p.consumeToken(":"); err != nil {
|
|
| 586 |
- return err |
|
| 587 |
- } |
|
| 588 |
- if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
| 589 |
- return err |
|
| 590 |
- } |
|
| 591 |
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 592 |
- return err |
|
| 593 |
- } |
|
| 594 |
- if err := p.consumeToken("value"); err != nil {
|
|
| 595 |
- return err |
|
| 596 |
- } |
|
| 597 |
- if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
| 598 |
- return err |
|
| 599 |
- } |
|
| 600 |
- if err := p.readAny(val, props.mvalprop); err != nil {
|
|
| 601 |
- return err |
|
| 602 |
- } |
|
| 603 |
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 604 |
- return err |
|
| 605 |
- } |
|
| 606 |
- if err := p.consumeToken(terminator); err != nil {
|
|
| 607 |
- return err |
|
| 582 |
+ for {
|
|
| 583 |
+ tok := p.next() |
|
| 584 |
+ if tok.err != nil {
|
|
| 585 |
+ return tok.err |
|
| 586 |
+ } |
|
| 587 |
+ if tok.value == terminator {
|
|
| 588 |
+ break |
|
| 589 |
+ } |
|
| 590 |
+ switch tok.value {
|
|
| 591 |
+ case "key": |
|
| 592 |
+ if err := p.consumeToken(":"); err != nil {
|
|
| 593 |
+ return err |
|
| 594 |
+ } |
|
| 595 |
+ if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
| 596 |
+ return err |
|
| 597 |
+ } |
|
| 598 |
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 599 |
+ return err |
|
| 600 |
+ } |
|
| 601 |
+ case "value": |
|
| 602 |
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
| 603 |
+ return err |
|
| 604 |
+ } |
|
| 605 |
+ if err := p.readAny(val, props.mvalprop); err != nil {
|
|
| 606 |
+ return err |
|
| 607 |
+ } |
|
| 608 |
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
| 609 |
+ return err |
|
| 610 |
+ } |
|
| 611 |
+ default: |
|
| 612 |
+ p.back() |
|
| 613 |
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) |
|
| 614 |
+ } |
|
| 608 | 615 |
} |
| 609 | 616 |
|
| 610 | 617 |
dst.SetMapIndex(key, val) |
| ... | ... |
@@ -627,7 +682,8 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 627 | 627 |
return err |
| 628 | 628 |
} |
| 629 | 629 |
reqFieldErr = err |
| 630 |
- } else if props.Required {
|
|
| 630 |
+ } |
|
| 631 |
+ if props.Required {
|
|
| 631 | 632 |
reqCount-- |
| 632 | 633 |
} |
| 633 | 634 |
|
| ... | ... |
@@ -643,6 +699,35 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
| 643 | 643 |
return reqFieldErr |
| 644 | 644 |
} |
| 645 | 645 |
|
| 646 |
+// consumeExtName consumes extension name or expanded Any type URL and the |
|
| 647 |
+// following ']'. It returns the name or URL consumed. |
|
| 648 |
+func (p *textParser) consumeExtName() (string, error) {
|
|
| 649 |
+ tok := p.next() |
|
| 650 |
+ if tok.err != nil {
|
|
| 651 |
+ return "", tok.err |
|
| 652 |
+ } |
|
| 653 |
+ |
|
| 654 |
+ // If extension name or type url is quoted, it's a single token. |
|
| 655 |
+ if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
|
| 656 |
+ name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) |
|
| 657 |
+ if err != nil {
|
|
| 658 |
+ return "", err |
|
| 659 |
+ } |
|
| 660 |
+ return name, p.consumeToken("]")
|
|
| 661 |
+ } |
|
| 662 |
+ |
|
| 663 |
+ // Consume everything up to "]" |
|
| 664 |
+ var parts []string |
|
| 665 |
+ for tok.value != "]" {
|
|
| 666 |
+ parts = append(parts, tok.value) |
|
| 667 |
+ tok = p.next() |
|
| 668 |
+ if tok.err != nil {
|
|
| 669 |
+ return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
|
| 670 |
+ } |
|
| 671 |
+ } |
|
| 672 |
+ return strings.Join(parts, ""), nil |
|
| 673 |
+} |
|
| 674 |
+ |
|
| 646 | 675 |
// consumeOptionalSeparator consumes an optional semicolon or comma. |
| 647 | 676 |
// It is used in readStruct to provide backward compatibility. |
| 648 | 677 |
func (p *textParser) consumeOptionalSeparator() error {
|
| ... | ... |
@@ -707,12 +792,12 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
| 707 | 707 |
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) |
| 708 | 708 |
return p.readAny(fv.Index(fv.Len()-1), props) |
| 709 | 709 |
case reflect.Bool: |
| 710 |
- // Either "true", "false", 1 or 0. |
|
| 710 |
+ // true/1/t/True or false/f/0/False. |
|
| 711 | 711 |
switch tok.value {
|
| 712 |
- case "true", "1": |
|
| 712 |
+ case "true", "1", "t", "True": |
|
| 713 | 713 |
fv.SetBool(true) |
| 714 | 714 |
return nil |
| 715 |
- case "false", "0": |
|
| 715 |
+ case "false", "0", "f", "False": |
|
| 716 | 716 |
fv.SetBool(false) |
| 717 | 717 |
return nil |
| 718 | 718 |
} |
| 719 | 719 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,136 @@ |
| 0 |
+// Go support for Protocol Buffers - Google's data interchange format |
|
| 1 |
+// |
|
| 2 |
+// Copyright 2016 The Go Authors. All rights reserved. |
|
| 3 |
+// https://github.com/golang/protobuf |
|
| 4 |
+// |
|
| 5 |
+// Redistribution and use in source and binary forms, with or without |
|
| 6 |
+// modification, are permitted provided that the following conditions are |
|
| 7 |
+// met: |
|
| 8 |
+// |
|
| 9 |
+// * Redistributions of source code must retain the above copyright |
|
| 10 |
+// notice, this list of conditions and the following disclaimer. |
|
| 11 |
+// * Redistributions in binary form must reproduce the above |
|
| 12 |
+// copyright notice, this list of conditions and the following disclaimer |
|
| 13 |
+// in the documentation and/or other materials provided with the |
|
| 14 |
+// distribution. |
|
| 15 |
+// * Neither the name of Google Inc. nor the names of its |
|
| 16 |
+// contributors may be used to endorse or promote products derived from |
|
| 17 |
+// this software without specific prior written permission. |
|
| 18 |
+// |
|
| 19 |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 20 |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 21 |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 22 |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 23 |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 24 |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 25 |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 26 |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 27 |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 28 |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 29 |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 30 |
+ |
|
| 31 |
+package ptypes |
|
| 32 |
+ |
|
| 33 |
+// This file implements functions to marshal proto.Message to/from |
|
| 34 |
+// google.protobuf.Any message. |
|
| 35 |
+ |
|
| 36 |
+import ( |
|
| 37 |
+ "fmt" |
|
| 38 |
+ "reflect" |
|
| 39 |
+ "strings" |
|
| 40 |
+ |
|
| 41 |
+ "github.com/golang/protobuf/proto" |
|
| 42 |
+ "github.com/golang/protobuf/ptypes/any" |
|
| 43 |
+) |
|
| 44 |
+ |
|
| 45 |
+const googleApis = "type.googleapis.com/" |
|
| 46 |
+ |
|
| 47 |
+// AnyMessageName returns the name of the message contained in a google.protobuf.Any message. |
|
| 48 |
+// |
|
| 49 |
+// Note that regular type assertions should be done using the Is |
|
| 50 |
+// function. AnyMessageName is provided for less common use cases like filtering a |
|
| 51 |
+// sequence of Any messages based on a set of allowed message type names. |
|
| 52 |
+func AnyMessageName(any *any.Any) (string, error) {
|
|
| 53 |
+ slash := strings.LastIndex(any.TypeUrl, "/") |
|
| 54 |
+ if slash < 0 {
|
|
| 55 |
+ return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
|
|
| 56 |
+ } |
|
| 57 |
+ return any.TypeUrl[slash+1:], nil |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any. |
|
| 61 |
+func MarshalAny(pb proto.Message) (*any.Any, error) {
|
|
| 62 |
+ value, err := proto.Marshal(pb) |
|
| 63 |
+ if err != nil {
|
|
| 64 |
+ return nil, err |
|
| 65 |
+ } |
|
| 66 |
+ return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
|
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+// DynamicAny is a value that can be passed to UnmarshalAny to automatically |
|
| 70 |
+// allocate a proto.Message for the type specified in a google.protobuf.Any |
|
| 71 |
+// message. The allocated message is stored in the embedded proto.Message. |
|
| 72 |
+// |
|
| 73 |
+// Example: |
|
| 74 |
+// |
|
| 75 |
+// var x ptypes.DynamicAny |
|
| 76 |
+// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
|
|
| 77 |
+// fmt.Printf("unmarshaled message: %v", x.Message)
|
|
| 78 |
+type DynamicAny struct {
|
|
| 79 |
+ proto.Message |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+// Empty returns a new proto.Message of the type specified in a |
|
| 83 |
+// google.protobuf.Any message. It returns an error if corresponding message |
|
| 84 |
+// type isn't linked in. |
|
| 85 |
+func Empty(any *any.Any) (proto.Message, error) {
|
|
| 86 |
+ aname, err := AnyMessageName(any) |
|
| 87 |
+ if err != nil {
|
|
| 88 |
+ return nil, err |
|
| 89 |
+ } |
|
| 90 |
+ |
|
| 91 |
+ t := proto.MessageType(aname) |
|
| 92 |
+ if t == nil {
|
|
| 93 |
+ return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
|
|
| 94 |
+ } |
|
| 95 |
+ return reflect.New(t.Elem()).Interface().(proto.Message), nil |
|
| 96 |
+} |
|
| 97 |
+ |
|
| 98 |
+// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any |
|
| 99 |
+// message and places the decoded result in pb. It returns an error if type of |
|
| 100 |
+// contents of Any message does not match type of pb message. |
|
| 101 |
+// |
|
| 102 |
+// pb can be a proto.Message, or a *DynamicAny. |
|
| 103 |
+func UnmarshalAny(any *any.Any, pb proto.Message) error {
|
|
| 104 |
+ if d, ok := pb.(*DynamicAny); ok {
|
|
| 105 |
+ if d.Message == nil {
|
|
| 106 |
+ var err error |
|
| 107 |
+ d.Message, err = Empty(any) |
|
| 108 |
+ if err != nil {
|
|
| 109 |
+ return err |
|
| 110 |
+ } |
|
| 111 |
+ } |
|
| 112 |
+ return UnmarshalAny(any, d.Message) |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ aname, err := AnyMessageName(any) |
|
| 116 |
+ if err != nil {
|
|
| 117 |
+ return err |
|
| 118 |
+ } |
|
| 119 |
+ |
|
| 120 |
+ mname := proto.MessageName(pb) |
|
| 121 |
+ if aname != mname {
|
|
| 122 |
+ return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
|
|
| 123 |
+ } |
|
| 124 |
+ return proto.Unmarshal(any.Value, pb) |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+// Is returns true if any value contains a given message type. |
|
| 128 |
+func Is(any *any.Any, pb proto.Message) bool {
|
|
| 129 |
+ aname, err := AnyMessageName(any) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ return false |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ return aname == proto.MessageName(pb) |
|
| 135 |
+} |
| 0 | 136 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,155 @@ |
| 0 |
+// Code generated by protoc-gen-go. |
|
| 1 |
+// source: github.com/golang/protobuf/ptypes/any/any.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+Package any is a generated protocol buffer package. |
|
| 6 |
+ |
|
| 7 |
+It is generated from these files: |
|
| 8 |
+ github.com/golang/protobuf/ptypes/any/any.proto |
|
| 9 |
+ |
|
| 10 |
+It has these top-level messages: |
|
| 11 |
+ Any |
|
| 12 |
+*/ |
|
| 13 |
+package any |
|
| 14 |
+ |
|
| 15 |
+import proto "github.com/golang/protobuf/proto" |
|
| 16 |
+import fmt "fmt" |
|
| 17 |
+import math "math" |
|
| 18 |
+ |
|
| 19 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 20 |
+var _ = proto.Marshal |
|
| 21 |
+var _ = fmt.Errorf |
|
| 22 |
+var _ = math.Inf |
|
| 23 |
+ |
|
| 24 |
+// This is a compile-time assertion to ensure that this generated file |
|
| 25 |
+// is compatible with the proto package it is being compiled against. |
|
| 26 |
+// A compilation error at this line likely means your copy of the |
|
| 27 |
+// proto package needs to be updated. |
|
| 28 |
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package |
|
| 29 |
+ |
|
| 30 |
+// `Any` contains an arbitrary serialized protocol buffer message along with a |
|
| 31 |
+// URL that describes the type of the serialized message. |
|
| 32 |
+// |
|
| 33 |
+// Protobuf library provides support to pack/unpack Any values in the form |
|
| 34 |
+// of utility functions or additional generated methods of the Any type. |
|
| 35 |
+// |
|
| 36 |
+// Example 1: Pack and unpack a message in C++. |
|
| 37 |
+// |
|
| 38 |
+// Foo foo = ...; |
|
| 39 |
+// Any any; |
|
| 40 |
+// any.PackFrom(foo); |
|
| 41 |
+// ... |
|
| 42 |
+// if (any.UnpackTo(&foo)) {
|
|
| 43 |
+// ... |
|
| 44 |
+// } |
|
| 45 |
+// |
|
| 46 |
+// Example 2: Pack and unpack a message in Java. |
|
| 47 |
+// |
|
| 48 |
+// Foo foo = ...; |
|
| 49 |
+// Any any = Any.pack(foo); |
|
| 50 |
+// ... |
|
| 51 |
+// if (any.is(Foo.class)) {
|
|
| 52 |
+// foo = any.unpack(Foo.class); |
|
| 53 |
+// } |
|
| 54 |
+// |
|
| 55 |
+// Example 3: Pack and unpack a message in Python. |
|
| 56 |
+// |
|
| 57 |
+// foo = Foo(...) |
|
| 58 |
+// any = Any() |
|
| 59 |
+// any.Pack(foo) |
|
| 60 |
+// ... |
|
| 61 |
+// if any.Is(Foo.DESCRIPTOR): |
|
| 62 |
+// any.Unpack(foo) |
|
| 63 |
+// ... |
|
| 64 |
+// |
|
| 65 |
+// The pack methods provided by protobuf library will by default use |
|
| 66 |
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack |
|
| 67 |
+// methods only use the fully qualified type name after the last '/' |
|
| 68 |
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type |
|
| 69 |
+// name "y.z". |
|
| 70 |
+// |
|
| 71 |
+// |
|
| 72 |
+// JSON |
|
| 73 |
+// ==== |
|
| 74 |
+// The JSON representation of an `Any` value uses the regular |
|
| 75 |
+// representation of the deserialized, embedded message, with an |
|
| 76 |
+// additional field `@type` which contains the type URL. Example: |
|
| 77 |
+// |
|
| 78 |
+// package google.profile; |
|
| 79 |
+// message Person {
|
|
| 80 |
+// string first_name = 1; |
|
| 81 |
+// string last_name = 2; |
|
| 82 |
+// } |
|
| 83 |
+// |
|
| 84 |
+// {
|
|
| 85 |
+// "@type": "type.googleapis.com/google.profile.Person", |
|
| 86 |
+// "firstName": <string>, |
|
| 87 |
+// "lastName": <string> |
|
| 88 |
+// } |
|
| 89 |
+// |
|
| 90 |
+// If the embedded message type is well-known and has a custom JSON |
|
| 91 |
+// representation, that representation will be embedded adding a field |
|
| 92 |
+// `value` which holds the custom JSON in addition to the `@type` |
|
| 93 |
+// field. Example (for message [google.protobuf.Duration][]): |
|
| 94 |
+// |
|
| 95 |
+// {
|
|
| 96 |
+// "@type": "type.googleapis.com/google.protobuf.Duration", |
|
| 97 |
+// "value": "1.212s" |
|
| 98 |
+// } |
|
| 99 |
+// |
|
| 100 |
+type Any struct {
|
|
| 101 |
+ // A URL/resource name whose content describes the type of the |
|
| 102 |
+ // serialized protocol buffer message. |
|
| 103 |
+ // |
|
| 104 |
+ // For URLs which use the scheme `http`, `https`, or no scheme, the |
|
| 105 |
+ // following restrictions and interpretations apply: |
|
| 106 |
+ // |
|
| 107 |
+ // * If no scheme is provided, `https` is assumed. |
|
| 108 |
+ // * The last segment of the URL's path must represent the fully |
|
| 109 |
+ // qualified name of the type (as in `path/google.protobuf.Duration`). |
|
| 110 |
+ // The name should be in a canonical form (e.g., leading "." is |
|
| 111 |
+ // not accepted). |
|
| 112 |
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][] |
|
| 113 |
+ // value in binary format, or produce an error. |
|
| 114 |
+ // * Applications are allowed to cache lookup results based on the |
|
| 115 |
+ // URL, or have them precompiled into a binary to avoid any |
|
| 116 |
+ // lookup. Therefore, binary compatibility needs to be preserved |
|
| 117 |
+ // on changes to types. (Use versioned type names to manage |
|
| 118 |
+ // breaking changes.) |
|
| 119 |
+ // |
|
| 120 |
+ // Schemes other than `http`, `https` (or the empty scheme) might be |
|
| 121 |
+ // used with implementation specific semantics. |
|
| 122 |
+ // |
|
| 123 |
+ TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` |
|
| 124 |
+ // Must be a valid serialized protocol buffer of the above specified type. |
|
| 125 |
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` |
|
| 126 |
+} |
|
| 127 |
+ |
|
| 128 |
+func (m *Any) Reset() { *m = Any{} }
|
|
| 129 |
+func (m *Any) String() string { return proto.CompactTextString(m) }
|
|
| 130 |
+func (*Any) ProtoMessage() {}
|
|
| 131 |
+func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
|
| 132 |
+func (*Any) XXX_WellKnownType() string { return "Any" }
|
|
| 133 |
+ |
|
| 134 |
+func init() {
|
|
| 135 |
+ proto.RegisterType((*Any)(nil), "google.protobuf.Any") |
|
| 136 |
+} |
|
| 137 |
+ |
|
| 138 |
+func init() { proto.RegisterFile("github.com/golang/protobuf/ptypes/any/any.proto", fileDescriptor0) }
|
|
| 139 |
+ |
|
| 140 |
+var fileDescriptor0 = []byte{
|
|
| 141 |
+ // 187 bytes of a gzipped FileDescriptorProto |
|
| 142 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xcf, 0x2c, 0xc9, |
|
| 143 |
+ 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, |
|
| 144 |
+ 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcc, |
|
| 145 |
+ 0xab, 0x04, 0x61, 0x3d, 0xb0, 0xb8, 0x10, 0x7f, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x1e, 0x4c, |
|
| 146 |
+ 0x95, 0x92, 0x19, 0x17, 0xb3, 0x63, 0x5e, 0xa5, 0x90, 0x24, 0x17, 0x07, 0x48, 0x79, 0x7c, 0x69, |
|
| 147 |
+ 0x51, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24, |
|
| 148 |
+ 0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0xe1, |
|
| 149 |
+ 0x38, 0x15, 0x71, 0x09, 0x27, 0xe7, 0xe7, 0xea, 0xa1, 0x19, 0xe7, 0xc4, 0xe1, 0x98, 0x57, 0x19, |
|
| 150 |
+ 0x00, 0xe2, 0x04, 0x30, 0x46, 0xa9, 0x12, 0xe5, 0xb8, 0x05, 0x8c, 0x8c, 0x8b, 0x98, 0x98, 0xdd, |
|
| 151 |
+ 0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x4c, 0x0b, 0x80, 0xaa, 0xd2, 0x0b, 0x4f, 0xcd, 0xc9, |
|
| 152 |
+ 0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0xa9, 0x4e, 0x62, 0x03, 0x6b, 0x37, 0x06, 0x04, 0x00, |
|
| 153 |
+ 0x00, 0xff, 0xff, 0xc6, 0x4d, 0x03, 0x23, 0xf6, 0x00, 0x00, 0x00, |
|
| 154 |
+} |
| 0 | 155 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,140 @@ |
| 0 |
+// Protocol Buffers - Google's data interchange format |
|
| 1 |
+// Copyright 2008 Google Inc. All rights reserved. |
|
| 2 |
+// https://developers.google.com/protocol-buffers/ |
|
| 3 |
+// |
|
| 4 |
+// Redistribution and use in source and binary forms, with or without |
|
| 5 |
+// modification, are permitted provided that the following conditions are |
|
| 6 |
+// met: |
|
| 7 |
+// |
|
| 8 |
+// * Redistributions of source code must retain the above copyright |
|
| 9 |
+// notice, this list of conditions and the following disclaimer. |
|
| 10 |
+// * Redistributions in binary form must reproduce the above |
|
| 11 |
+// copyright notice, this list of conditions and the following disclaimer |
|
| 12 |
+// in the documentation and/or other materials provided with the |
|
| 13 |
+// distribution. |
|
| 14 |
+// * Neither the name of Google Inc. nor the names of its |
|
| 15 |
+// contributors may be used to endorse or promote products derived from |
|
| 16 |
+// this software without specific prior written permission. |
|
| 17 |
+// |
|
| 18 |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 19 |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 20 |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 21 |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 22 |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 23 |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 24 |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 25 |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 26 |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 27 |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 28 |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 29 |
+ |
|
| 30 |
+syntax = "proto3"; |
|
| 31 |
+ |
|
| 32 |
+package google.protobuf; |
|
| 33 |
+ |
|
| 34 |
+option csharp_namespace = "Google.Protobuf.WellKnownTypes"; |
|
| 35 |
+option go_package = "github.com/golang/protobuf/ptypes/any"; |
|
| 36 |
+option java_package = "com.google.protobuf"; |
|
| 37 |
+option java_outer_classname = "AnyProto"; |
|
| 38 |
+option java_multiple_files = true; |
|
| 39 |
+option java_generate_equals_and_hash = true; |
|
| 40 |
+option objc_class_prefix = "GPB"; |
|
| 41 |
+ |
|
| 42 |
+// `Any` contains an arbitrary serialized protocol buffer message along with a |
|
| 43 |
+// URL that describes the type of the serialized message. |
|
| 44 |
+// |
|
| 45 |
+// Protobuf library provides support to pack/unpack Any values in the form |
|
| 46 |
+// of utility functions or additional generated methods of the Any type. |
|
| 47 |
+// |
|
| 48 |
+// Example 1: Pack and unpack a message in C++. |
|
| 49 |
+// |
|
| 50 |
+// Foo foo = ...; |
|
| 51 |
+// Any any; |
|
| 52 |
+// any.PackFrom(foo); |
|
| 53 |
+// ... |
|
| 54 |
+// if (any.UnpackTo(&foo)) {
|
|
| 55 |
+// ... |
|
| 56 |
+// } |
|
| 57 |
+// |
|
| 58 |
+// Example 2: Pack and unpack a message in Java. |
|
| 59 |
+// |
|
| 60 |
+// Foo foo = ...; |
|
| 61 |
+// Any any = Any.pack(foo); |
|
| 62 |
+// ... |
|
| 63 |
+// if (any.is(Foo.class)) {
|
|
| 64 |
+// foo = any.unpack(Foo.class); |
|
| 65 |
+// } |
|
| 66 |
+// |
|
| 67 |
+// Example 3: Pack and unpack a message in Python. |
|
| 68 |
+// |
|
| 69 |
+// foo = Foo(...) |
|
| 70 |
+// any = Any() |
|
| 71 |
+// any.Pack(foo) |
|
| 72 |
+// ... |
|
| 73 |
+// if any.Is(Foo.DESCRIPTOR): |
|
| 74 |
+// any.Unpack(foo) |
|
| 75 |
+// ... |
|
| 76 |
+// |
|
| 77 |
+// The pack methods provided by protobuf library will by default use |
|
| 78 |
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack |
|
| 79 |
+// methods only use the fully qualified type name after the last '/' |
|
| 80 |
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type |
|
| 81 |
+// name "y.z". |
|
| 82 |
+// |
|
| 83 |
+// |
|
| 84 |
+// JSON |
|
| 85 |
+// ==== |
|
| 86 |
+// The JSON representation of an `Any` value uses the regular |
|
| 87 |
+// representation of the deserialized, embedded message, with an |
|
| 88 |
+// additional field `@type` which contains the type URL. Example: |
|
| 89 |
+// |
|
| 90 |
+// package google.profile; |
|
| 91 |
+// message Person {
|
|
| 92 |
+// string first_name = 1; |
|
| 93 |
+// string last_name = 2; |
|
| 94 |
+// } |
|
| 95 |
+// |
|
| 96 |
+// {
|
|
| 97 |
+// "@type": "type.googleapis.com/google.profile.Person", |
|
| 98 |
+// "firstName": <string>, |
|
| 99 |
+// "lastName": <string> |
|
| 100 |
+// } |
|
| 101 |
+// |
|
| 102 |
+// If the embedded message type is well-known and has a custom JSON |
|
| 103 |
+// representation, that representation will be embedded adding a field |
|
| 104 |
+// `value` which holds the custom JSON in addition to the `@type` |
|
| 105 |
+// field. Example (for message [google.protobuf.Duration][]): |
|
| 106 |
+// |
|
| 107 |
+// {
|
|
| 108 |
+// "@type": "type.googleapis.com/google.protobuf.Duration", |
|
| 109 |
+// "value": "1.212s" |
|
| 110 |
+// } |
|
| 111 |
+// |
|
| 112 |
+message Any {
|
|
| 113 |
+ // A URL/resource name whose content describes the type of the |
|
| 114 |
+ // serialized protocol buffer message. |
|
| 115 |
+ // |
|
| 116 |
+ // For URLs which use the scheme `http`, `https`, or no scheme, the |
|
| 117 |
+ // following restrictions and interpretations apply: |
|
| 118 |
+ // |
|
| 119 |
+ // * If no scheme is provided, `https` is assumed. |
|
| 120 |
+ // * The last segment of the URL's path must represent the fully |
|
| 121 |
+ // qualified name of the type (as in `path/google.protobuf.Duration`). |
|
| 122 |
+ // The name should be in a canonical form (e.g., leading "." is |
|
| 123 |
+ // not accepted). |
|
| 124 |
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][] |
|
| 125 |
+ // value in binary format, or produce an error. |
|
| 126 |
+ // * Applications are allowed to cache lookup results based on the |
|
| 127 |
+ // URL, or have them precompiled into a binary to avoid any |
|
| 128 |
+ // lookup. Therefore, binary compatibility needs to be preserved |
|
| 129 |
+ // on changes to types. (Use versioned type names to manage |
|
| 130 |
+ // breaking changes.) |
|
| 131 |
+ // |
|
| 132 |
+ // Schemes other than `http`, `https` (or the empty scheme) might be |
|
| 133 |
+ // used with implementation specific semantics. |
|
| 134 |
+ // |
|
| 135 |
+ string type_url = 1; |
|
| 136 |
+ |
|
| 137 |
+ // Must be a valid serialized protocol buffer of the above specified type. |
|
| 138 |
+ bytes value = 2; |
|
| 139 |
+} |
| ... | ... |
@@ -1,12 +1,12 @@ |
| 1 | 1 |
// Code generated by protoc-gen-go. |
| 2 |
-// source: github.com/golang/protobuf/types/duration/duration.proto |
|
| 2 |
+// source: github.com/golang/protobuf/ptypes/duration/duration.proto |
|
| 3 | 3 |
// DO NOT EDIT! |
| 4 | 4 |
|
| 5 | 5 |
/* |
| 6 | 6 |
Package duration is a generated protocol buffer package. |
| 7 | 7 |
|
| 8 | 8 |
It is generated from these files: |
| 9 |
- github.com/golang/protobuf/types/duration/duration.proto |
|
| 9 |
+ github.com/golang/protobuf/ptypes/duration/duration.proto |
|
| 10 | 10 |
|
| 11 | 11 |
It has these top-level messages: |
| 12 | 12 |
Duration |
| ... | ... |
@@ -24,7 +24,9 @@ var _ = math.Inf |
| 24 | 24 |
|
| 25 | 25 |
// This is a compile-time assertion to ensure that this generated file |
| 26 | 26 |
// is compatible with the proto package it is being compiled against. |
| 27 |
-const _ = proto.ProtoPackageIsVersion1 |
|
| 27 |
+// A compilation error at this line likely means your copy of the |
|
| 28 |
+// proto package needs to be updated. |
|
| 29 |
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package |
|
| 28 | 30 |
|
| 29 | 31 |
// A Duration represents a signed, fixed-length span of time represented |
| 30 | 32 |
// as a count of seconds and fractions of seconds at nanosecond |
| ... | ... |
@@ -67,6 +69,7 @@ const _ = proto.ProtoPackageIsVersion1 |
| 67 | 67 |
// end.nanos -= 1000000000; |
| 68 | 68 |
// } |
| 69 | 69 |
// |
| 70 |
+// |
|
| 70 | 71 |
type Duration struct {
|
| 71 | 72 |
// Signed seconds of the span of time. Must be from -315,576,000,000 |
| 72 | 73 |
// to +315,576,000,000 inclusive. |
| ... | ... |
@@ -84,23 +87,28 @@ func (m *Duration) Reset() { *m = Duration{} }
|
| 84 | 84 |
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
| 85 | 85 |
func (*Duration) ProtoMessage() {}
|
| 86 | 86 |
func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
| 87 |
+func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
|
| 87 | 88 |
|
| 88 | 89 |
func init() {
|
| 89 | 90 |
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") |
| 90 | 91 |
} |
| 91 | 92 |
|
| 93 |
+func init() {
|
|
| 94 |
+ proto.RegisterFile("github.com/golang/protobuf/ptypes/duration/duration.proto", fileDescriptor0)
|
|
| 95 |
+} |
|
| 96 |
+ |
|
| 92 | 97 |
var fileDescriptor0 = []byte{
|
| 93 |
- // 186 bytes of a gzipped FileDescriptorProto |
|
| 94 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x48, 0xcf, 0x2c, 0xc9, |
|
| 98 |
+ // 189 bytes of a gzipped FileDescriptorProto |
|
| 99 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, |
|
| 95 | 100 |
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, |
| 96 |
- 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, 0x2d, |
|
| 97 |
- 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x0a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, 0xd3, |
|
| 98 |
- 0x73, 0x52, 0xf5, 0x60, 0xca, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, 0xd8, |
|
| 99 |
- 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, |
|
| 100 |
- 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, 0x84, |
|
| 101 |
- 0xe3, 0x14, 0xc5, 0x25, 0x0c, 0x74, 0x81, 0x1e, 0x9a, 0x91, 0x4e, 0xbc, 0x30, 0x03, 0x03, 0x40, |
|
| 102 |
- 0x22, 0x01, 0x8c, 0x51, 0x1c, 0x30, 0x47, 0x2c, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0xec, 0x1e, 0xe0, |
|
| 103 |
- 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0xa2, 0x2b, 0x00, 0xaa, 0x4b, 0x2f, 0x3c, 0x35, 0x27, 0xc7, 0x3b, |
|
| 104 |
- 0x2f, 0xbf, 0x3c, 0x2f, 0x04, 0xe4, 0x81, 0x24, 0x36, 0xb0, 0x71, 0xc6, 0x80, 0x00, 0x00, 0x00, |
|
| 105 |
- 0xff, 0xff, 0x04, 0x47, 0x33, 0x15, 0xeb, 0x00, 0x00, 0x00, |
|
| 101 |
+ 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, |
|
| 102 |
+ 0x2d, 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x2a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, |
|
| 103 |
+ 0xd3, 0x73, 0x52, 0xf5, 0x60, 0xea, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, |
|
| 104 |
+ 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, |
|
| 105 |
+ 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xd6, |
|
| 106 |
+ 0x20, 0x08, 0xc7, 0xa9, 0x86, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x48, 0x27, 0x5e, 0x98, |
|
| 107 |
+ 0x81, 0x01, 0x20, 0x91, 0x00, 0xc6, 0x28, 0x2d, 0xe2, 0xdd, 0xbb, 0x80, 0x91, 0x71, 0x11, 0x13, |
|
| 108 |
+ 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xb9, 0x01, 0x50, 0xa5, 0x7a, 0xe1, 0xa9, |
|
| 109 |
+ 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x2d, 0x49, 0x6c, 0x60, 0x33, 0x8c, 0x01, |
|
| 110 |
+ 0x01, 0x00, 0x00, 0xff, 0xff, 0x62, 0xfb, 0xb1, 0x51, 0x0e, 0x01, 0x00, 0x00, |
|
| 106 | 111 |
} |
| ... | ... |
@@ -31,9 +31,9 @@ |
| 31 | 31 |
syntax = "proto3"; |
| 32 | 32 |
|
| 33 | 33 |
package google.protobuf; |
| 34 |
-option go_package = "duration"; |
|
| 35 | 34 |
|
| 36 | 35 |
option csharp_namespace = "Google.Protobuf.WellKnownTypes"; |
| 36 |
+option go_package = "github.com/golang/protobuf/ptypes/duration"; |
|
| 37 | 37 |
option java_package = "com.google.protobuf"; |
| 38 | 38 |
option java_outer_classname = "DurationProto"; |
| 39 | 39 |
option java_multiple_files = true; |
| ... | ... |
@@ -81,6 +81,7 @@ option objc_class_prefix = "GPB"; |
| 81 | 81 |
// end.nanos -= 1000000000; |
| 82 | 82 |
// } |
| 83 | 83 |
// |
| 84 |
+// |
|
| 84 | 85 |
message Duration {
|
| 85 | 86 |
|
| 86 | 87 |
// Signed seconds of the span of time. Must be from -315,576,000,000 |
| ... | ... |
@@ -5,7 +5,7 @@ |
| 5 | 5 |
# see https://github.com/golang/protobuf for instructions. |
| 6 | 6 |
# You also need Go and Git installed. |
| 7 | 7 |
|
| 8 |
-PKG=github.com/golang/protobuf/types |
|
| 8 |
+PKG=github.com/golang/protobuf/ptypes |
|
| 9 | 9 |
UPSTREAM=https://github.com/google/protobuf |
| 10 | 10 |
UPSTREAM_SUBDIR=src/google/protobuf |
| 11 | 11 |
PROTO_FILES=' |
| ... | ... |
@@ -51,17 +51,11 @@ for f in $(cd $PKG && find * -name '*.proto'); do |
| 51 | 51 |
fi |
| 52 | 52 |
filename_map[$up]=$f |
| 53 | 53 |
done |
| 54 |
-# Pass 2: copy files, making necessary adjustments. |
|
| 54 |
+# Pass 2: copy files |
|
| 55 | 55 |
for up in "${!filename_map[@]}"; do
|
| 56 | 56 |
f=${filename_map[$up]}
|
| 57 | 57 |
shortname=$(basename $f | sed 's,\.proto$,,') |
| 58 |
- cat $tmpdir/$UPSTREAM_SUBDIR/$up | |
|
| 59 |
- # Adjust proto package. |
|
| 60 |
- # TODO(dsymonds): Upstream the go_package option instead. |
|
| 61 |
- sed '/^package /a option go_package = "'${shortname}'";' |
|
|
| 62 |
- # Unfortunately "package struct" doesn't work. |
|
| 63 |
- sed '/option go_package/s,"struct","structpb",' | |
|
| 64 |
- cat > $PKG/$f |
|
| 58 |
+ cp $tmpdir/$UPSTREAM_SUBDIR/$up $PKG/$f |
|
| 65 | 59 |
done |
| 66 | 60 |
|
| 67 | 61 |
# Run protoc once per package. |
| ... | ... |
@@ -1,12 +1,12 @@ |
| 1 | 1 |
// Code generated by protoc-gen-go. |
| 2 |
-// source: github.com/golang/protobuf/types/timestamp/timestamp.proto |
|
| 2 |
+// source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto |
|
| 3 | 3 |
// DO NOT EDIT! |
| 4 | 4 |
|
| 5 | 5 |
/* |
| 6 | 6 |
Package timestamp is a generated protocol buffer package. |
| 7 | 7 |
|
| 8 | 8 |
It is generated from these files: |
| 9 |
- github.com/golang/protobuf/types/timestamp/timestamp.proto |
|
| 9 |
+ github.com/golang/protobuf/ptypes/timestamp/timestamp.proto |
|
| 10 | 10 |
|
| 11 | 11 |
It has these top-level messages: |
| 12 | 12 |
Timestamp |
| ... | ... |
@@ -24,7 +24,9 @@ var _ = math.Inf |
| 24 | 24 |
|
| 25 | 25 |
// This is a compile-time assertion to ensure that this generated file |
| 26 | 26 |
// is compatible with the proto package it is being compiled against. |
| 27 |
-const _ = proto.ProtoPackageIsVersion1 |
|
| 27 |
+// A compilation error at this line likely means your copy of the |
|
| 28 |
+// proto package needs to be updated. |
|
| 29 |
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package |
|
| 28 | 30 |
|
| 29 | 31 |
// A Timestamp represents a point in time independent of any time zone |
| 30 | 32 |
// or calendar, represented as seconds and fractions of seconds at |
| ... | ... |
@@ -97,23 +99,29 @@ func (m *Timestamp) Reset() { *m = Timestamp{} }
|
| 97 | 97 |
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
| 98 | 98 |
func (*Timestamp) ProtoMessage() {}
|
| 99 | 99 |
func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
| 100 |
+func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
|
| 100 | 101 |
|
| 101 | 102 |
func init() {
|
| 102 | 103 |
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") |
| 103 | 104 |
} |
| 104 | 105 |
|
| 106 |
+func init() {
|
|
| 107 |
+ proto.RegisterFile("github.com/golang/protobuf/ptypes/timestamp/timestamp.proto", fileDescriptor0)
|
|
| 108 |
+} |
|
| 109 |
+ |
|
| 105 | 110 |
var fileDescriptor0 = []byte{
|
| 106 |
- // 190 bytes of a gzipped FileDescriptorProto |
|
| 107 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4a, 0xcf, 0x2c, 0xc9, |
|
| 111 |
+ // 194 bytes of a gzipped FileDescriptorProto |
|
| 112 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, |
|
| 108 | 113 |
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, |
| 109 |
- 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, 0xcc, |
|
| 110 |
- 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x4a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, |
|
| 111 |
- 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x1a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, 0xb8, |
|
| 112 |
- 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, |
|
| 113 |
- 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, |
|
| 114 |
- 0x84, 0xe3, 0x14, 0xcf, 0x25, 0x0c, 0x74, 0x84, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, |
|
| 115 |
- 0x40, 0x42, 0x01, 0x8c, 0x51, 0x9c, 0x70, 0x77, 0x2c, 0x60, 0x64, 0xfc, 0xc1, 0xc8, 0xb8, 0x88, |
|
| 116 |
- 0x89, 0xd9, 0x3d, 0xc0, 0x69, 0x15, 0x93, 0x9c, 0x3b, 0x44, 0x6b, 0x00, 0x54, 0xab, 0x5e, 0x78, |
|
| 117 |
- 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0xc8, 0x23, 0x49, 0x6c, 0x60, 0x33, 0x8d, |
|
| 118 |
- 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xdd, 0x30, 0x93, 0xf3, 0x00, 0x00, 0x00, |
|
| 114 |
+ 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, |
|
| 115 |
+ 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x6a, 0x84, 0xf8, 0xd3, 0xf3, |
|
| 116 |
+ 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x3a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, |
|
| 117 |
+ 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, |
|
| 118 |
+ 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, |
|
| 119 |
+ 0xd6, 0x20, 0x08, 0xc7, 0xa9, 0x91, 0x91, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x50, 0x27, |
|
| 120 |
+ 0x3e, 0xb8, 0x91, 0x01, 0x20, 0xa1, 0x00, 0xc6, 0x28, 0x6d, 0x12, 0x1c, 0xbd, 0x80, 0x91, 0xf1, |
|
| 121 |
+ 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, 0xc3, 0x03, |
|
| 122 |
+ 0xa0, 0xca, 0xf5, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, 0xda, 0x92, |
|
| 123 |
+ 0xd8, 0xc0, 0xe6, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x17, 0x5f, 0xb7, 0xdc, 0x17, 0x01, |
|
| 124 |
+ 0x00, 0x00, |
|
| 119 | 125 |
} |
| ... | ... |
@@ -31,10 +31,10 @@ |
| 31 | 31 |
syntax = "proto3"; |
| 32 | 32 |
|
| 33 | 33 |
package google.protobuf; |
| 34 |
-option go_package = "timestamp"; |
|
| 35 | 34 |
|
| 36 | 35 |
option csharp_namespace = "Google.Protobuf.WellKnownTypes"; |
| 37 | 36 |
option cc_enable_arenas = true; |
| 37 |
+option go_package = "github.com/golang/protobuf/ptypes/timestamp"; |
|
| 38 | 38 |
option java_package = "com.google.protobuf"; |
| 39 | 39 |
option java_outer_classname = "TimestampProto"; |
| 40 | 40 |
option java_multiple_files = true; |
| ... | ... |
@@ -1,17 +1,21 @@ |
| 1 | 1 |
language: go |
| 2 | 2 |
|
| 3 | 3 |
go: |
| 4 |
- - 1.5.3 |
|
| 5 |
- - 1.6 |
|
| 4 |
+ - 1.5.4 |
|
| 5 |
+ - 1.6.3 |
|
| 6 |
+ |
|
| 7 |
+go_import_path: google.golang.org/grpc |
|
| 6 | 8 |
|
| 7 | 9 |
before_install: |
| 10 |
+ - go get golang.org/x/tools/cmd/goimports |
|
| 11 |
+ - go get github.com/golang/lint/golint |
|
| 8 | 12 |
- go get github.com/axw/gocov/gocov |
| 9 | 13 |
- go get github.com/mattn/goveralls |
| 10 | 14 |
- go get golang.org/x/tools/cmd/cover |
| 11 | 15 |
|
| 12 |
-install: |
|
| 13 |
- - mkdir -p "$GOPATH/src/google.golang.org" |
|
| 14 |
- - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/google.golang.org/grpc" |
|
| 15 |
- |
|
| 16 | 16 |
script: |
| 17 |
+ - '! gofmt -s -d -l . 2>&1 | read' |
|
| 18 |
+ - '! goimports -l . | read' |
|
| 19 |
+ - '! golint ./... | grep -vE "(_string|\.pb)\.go:"' |
|
| 20 |
+ - '! go tool vet -all . 2>&1 | grep -vE "constant [0-9]+ not a string in call to Errorf"' |
|
| 17 | 21 |
- make test testrace |
| ... | ... |
@@ -21,8 +21,9 @@ proto: |
| 21 | 21 |
exit 1; \ |
| 22 | 22 |
fi |
| 23 | 23 |
go get -u -v github.com/golang/protobuf/protoc-gen-go |
| 24 |
- for file in $$(git ls-files '*.proto'); do \ |
|
| 25 |
- protoc -I $$(dirname $$file) --go_out=plugins=grpc:$$(dirname $$file) $$file; \ |
|
| 24 |
+ # use $$dir as the root for all proto files in the same directory |
|
| 25 |
+ for dir in $$(git ls-files '*.proto' | xargs -n1 dirname | uniq); do \ |
|
| 26 |
+ protoc -I $$dir --go_out=plugins=grpc:$$dir $$dir/*.proto; \ |
|
| 26 | 27 |
done |
| 27 | 28 |
|
| 28 | 29 |
test: testdeps |
| ... | ... |
@@ -1,22 +1,22 @@ |
| 1 | 1 |
Additional IP Rights Grant (Patents) |
| 2 | 2 |
|
| 3 | 3 |
"This implementation" means the copyrightable works distributed by |
| 4 |
-Google as part of the GRPC project. |
|
| 4 |
+Google as part of the gRPC project. |
|
| 5 | 5 |
|
| 6 | 6 |
Google hereby grants to You a perpetual, worldwide, non-exclusive, |
| 7 | 7 |
no-charge, royalty-free, irrevocable (except as stated in this section) |
| 8 | 8 |
patent license to make, have made, use, offer to sell, sell, import, |
| 9 | 9 |
transfer and otherwise run, modify and propagate the contents of this |
| 10 |
-implementation of GRPC, where such license applies only to those patent |
|
| 10 |
+implementation of gRPC, where such license applies only to those patent |
|
| 11 | 11 |
claims, both currently owned or controlled by Google and acquired in |
| 12 | 12 |
the future, licensable by Google that are necessarily infringed by this |
| 13 |
-implementation of GRPC. This grant does not include claims that would be |
|
| 13 |
+implementation of gRPC. This grant does not include claims that would be |
|
| 14 | 14 |
infringed only as a consequence of further modification of this |
| 15 | 15 |
implementation. If you or your agent or exclusive licensee institute or |
| 16 | 16 |
order or agree to the institution of patent litigation against any |
| 17 | 17 |
entity (including a cross-claim or counterclaim in a lawsuit) alleging |
| 18 |
-that this implementation of GRPC or any code incorporated within this |
|
| 19 |
-implementation of GRPC constitutes direct or contributory patent |
|
| 18 |
+that this implementation of gRPC or any code incorporated within this |
|
| 19 |
+implementation of gRPC constitutes direct or contributory patent |
|
| 20 | 20 |
infringement, or inducement of patent infringement, then any patent |
| 21 |
-rights granted to you under this License for this implementation of GRPC |
|
| 21 |
+rights granted to you under this License for this implementation of gRPC |
|
| 22 | 22 |
shall terminate as of the date such litigation is filed. |
| ... | ... |
@@ -19,7 +19,7 @@ var ( |
| 19 | 19 |
// backoffStrategy defines the methodology for backing off after a grpc |
| 20 | 20 |
// connection failure. |
| 21 | 21 |
// |
| 22 |
-// This is unexported until the GRPC project decides whether or not to allow |
|
| 22 |
+// This is unexported until the gRPC project decides whether or not to allow |
|
| 23 | 23 |
// alternative backoff strategies. Once a decision is made, this type and its |
| 24 | 24 |
// method may be exported. |
| 25 | 25 |
type backoffStrategy interface {
|
| ... | ... |
@@ -28,14 +28,14 @@ type backoffStrategy interface {
|
| 28 | 28 |
backoff(retries int) time.Duration |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
-// BackoffConfig defines the parameters for the default GRPC backoff strategy. |
|
| 31 |
+// BackoffConfig defines the parameters for the default gRPC backoff strategy. |
|
| 32 | 32 |
type BackoffConfig struct {
|
| 33 | 33 |
// MaxDelay is the upper bound of backoff delay. |
| 34 | 34 |
MaxDelay time.Duration |
| 35 | 35 |
|
| 36 | 36 |
// TODO(stevvooe): The following fields are not exported, as allowing |
| 37 |
- // changes would violate the current GRPC specification for backoff. If |
|
| 38 |
- // GRPC decides to allow more interesting backoff strategies, these fields |
|
| 37 |
+ // changes would violate the current gRPC specification for backoff. If |
|
| 38 |
+ // gRPC decides to allow more interesting backoff strategies, these fields |
|
| 39 | 39 |
// may be opened up in the future. |
| 40 | 40 |
|
| 41 | 41 |
// baseDelay is the amount of time to wait before retrying after the first |
| 42 | 42 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,385 @@ |
| 0 |
+/* |
|
| 1 |
+ * |
|
| 2 |
+ * Copyright 2016, Google Inc. |
|
| 3 |
+ * All rights reserved. |
|
| 4 |
+ * |
|
| 5 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 6 |
+ * modification, are permitted provided that the following conditions are |
|
| 7 |
+ * met: |
|
| 8 |
+ * |
|
| 9 |
+ * * Redistributions of source code must retain the above copyright |
|
| 10 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 11 |
+ * * Redistributions in binary form must reproduce the above |
|
| 12 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 13 |
+ * in the documentation and/or other materials provided with the |
|
| 14 |
+ * distribution. |
|
| 15 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 16 |
+ * contributors may be used to endorse or promote products derived from |
|
| 17 |
+ * this software without specific prior written permission. |
|
| 18 |
+ * |
|
| 19 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 20 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 21 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 22 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 23 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 24 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 25 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 26 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 27 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 28 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 29 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 30 |
+ * |
|
| 31 |
+ */ |
|
| 32 |
+ |
|
| 33 |
+package grpc |
|
| 34 |
+ |
|
| 35 |
+import ( |
|
| 36 |
+ "fmt" |
|
| 37 |
+ "sync" |
|
| 38 |
+ |
|
| 39 |
+ "golang.org/x/net/context" |
|
| 40 |
+ "google.golang.org/grpc/grpclog" |
|
| 41 |
+ "google.golang.org/grpc/naming" |
|
| 42 |
+) |
|
| 43 |
+ |
|
| 44 |
+// Address represents a server the client connects to. |
|
| 45 |
+// This is the EXPERIMENTAL API and may be changed or extended in the future. |
|
| 46 |
+type Address struct {
|
|
| 47 |
+ // Addr is the server address on which a connection will be established. |
|
| 48 |
+ Addr string |
|
| 49 |
+ // Metadata is the information associated with Addr, which may be used |
|
| 50 |
+ // to make load balancing decision. |
|
| 51 |
+ Metadata interface{}
|
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// BalancerGetOptions configures a Get call. |
|
| 55 |
+// This is the EXPERIMENTAL API and may be changed or extended in the future. |
|
| 56 |
+type BalancerGetOptions struct {
|
|
| 57 |
+ // BlockingWait specifies whether Get should block when there is no |
|
| 58 |
+ // connected address. |
|
| 59 |
+ BlockingWait bool |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+// Balancer chooses network addresses for RPCs. |
|
| 63 |
+// This is the EXPERIMENTAL API and may be changed or extended in the future. |
|
| 64 |
+type Balancer interface {
|
|
| 65 |
+ // Start does the initialization work to bootstrap a Balancer. For example, |
|
| 66 |
+ // this function may start the name resolution and watch the updates. It will |
|
| 67 |
+ // be called when dialing. |
|
| 68 |
+ Start(target string) error |
|
| 69 |
+ // Up informs the Balancer that gRPC has a connection to the server at |
|
| 70 |
+ // addr. It returns down which is called once the connection to addr gets |
|
| 71 |
+ // lost or closed. |
|
| 72 |
+ // TODO: It is not clear how to construct and take advantage the meaningful error |
|
| 73 |
+ // parameter for down. Need realistic demands to guide. |
|
| 74 |
+ Up(addr Address) (down func(error)) |
|
| 75 |
+ // Get gets the address of a server for the RPC corresponding to ctx. |
|
| 76 |
+ // i) If it returns a connected address, gRPC internals issues the RPC on the |
|
| 77 |
+ // connection to this address; |
|
| 78 |
+ // ii) If it returns an address on which the connection is under construction |
|
| 79 |
+ // (initiated by Notify(...)) but not connected, gRPC internals |
|
| 80 |
+ // * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or |
|
| 81 |
+ // Shutdown state; |
|
| 82 |
+ // or |
|
| 83 |
+ // * issues RPC on the connection otherwise. |
|
| 84 |
+ // iii) If it returns an address on which the connection does not exist, gRPC |
|
| 85 |
+ // internals treats it as an error and will fail the corresponding RPC. |
|
| 86 |
+ // |
|
| 87 |
+ // Therefore, the following is the recommended rule when writing a custom Balancer. |
|
| 88 |
+ // If opts.BlockingWait is true, it should return a connected address or |
|
| 89 |
+ // block if there is no connected address. It should respect the timeout or |
|
| 90 |
+ // cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast |
|
| 91 |
+ // RPCs), it should return an address it has notified via Notify(...) immediately |
|
| 92 |
+ // instead of blocking. |
|
| 93 |
+ // |
|
| 94 |
+ // The function returns put which is called once the rpc has completed or failed. |
|
| 95 |
+ // put can collect and report RPC stats to a remote load balancer. |
|
| 96 |
+ // |
|
| 97 |
+ // This function should only return the errors Balancer cannot recover by itself. |
|
| 98 |
+ // gRPC internals will fail the RPC if an error is returned. |
|
| 99 |
+ Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) |
|
| 100 |
+ // Notify returns a channel that is used by gRPC internals to watch the addresses |
|
| 101 |
+ // gRPC needs to connect. The addresses might be from a name resolver or remote |
|
| 102 |
+ // load balancer. gRPC internals will compare it with the existing connected |
|
| 103 |
+ // addresses. If the address Balancer notified is not in the existing connected |
|
| 104 |
+ // addresses, gRPC starts to connect the address. If an address in the existing |
|
| 105 |
+ // connected addresses is not in the notification list, the corresponding connection |
|
| 106 |
+ // is shutdown gracefully. Otherwise, there are no operations to take. Note that |
|
| 107 |
+ // the Address slice must be the full list of the Addresses which should be connected. |
|
| 108 |
+ // It is NOT delta. |
|
| 109 |
+ Notify() <-chan []Address |
|
| 110 |
+ // Close shuts down the balancer. |
|
| 111 |
+ Close() error |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+// downErr implements net.Error. It is constructed by gRPC internals and passed to the down |
|
| 115 |
+// call of Balancer. |
|
| 116 |
+type downErr struct {
|
|
| 117 |
+ timeout bool |
|
| 118 |
+ temporary bool |
|
| 119 |
+ desc string |
|
| 120 |
+} |
|
| 121 |
+ |
|
| 122 |
+func (e downErr) Error() string { return e.desc }
|
|
| 123 |
+func (e downErr) Timeout() bool { return e.timeout }
|
|
| 124 |
+func (e downErr) Temporary() bool { return e.temporary }
|
|
| 125 |
+ |
|
| 126 |
+func downErrorf(timeout, temporary bool, format string, a ...interface{}) downErr {
|
|
| 127 |
+ return downErr{
|
|
| 128 |
+ timeout: timeout, |
|
| 129 |
+ temporary: temporary, |
|
| 130 |
+ desc: fmt.Sprintf(format, a...), |
|
| 131 |
+ } |
|
| 132 |
+} |
|
| 133 |
+ |
|
| 134 |
+// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch |
|
| 135 |
+// the name resolution updates and updates the addresses available correspondingly. |
|
| 136 |
+func RoundRobin(r naming.Resolver) Balancer {
|
|
| 137 |
+ return &roundRobin{r: r}
|
|
| 138 |
+} |
|
| 139 |
+ |
|
| 140 |
+type addrInfo struct {
|
|
| 141 |
+ addr Address |
|
| 142 |
+ connected bool |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+type roundRobin struct {
|
|
| 146 |
+ r naming.Resolver |
|
| 147 |
+ w naming.Watcher |
|
| 148 |
+ addrs []*addrInfo // all the addresses the client should potentially connect |
|
| 149 |
+ mu sync.Mutex |
|
| 150 |
+ addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to. |
|
| 151 |
+ next int // index of the next address to return for Get() |
|
| 152 |
+ waitCh chan struct{} // the channel to block when there is no connected address available
|
|
| 153 |
+ done bool // The Balancer is closed. |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+func (rr *roundRobin) watchAddrUpdates() error {
|
|
| 157 |
+ updates, err := rr.w.Next() |
|
| 158 |
+ if err != nil {
|
|
| 159 |
+ grpclog.Printf("grpc: the naming watcher stops working due to %v.\n", err)
|
|
| 160 |
+ return err |
|
| 161 |
+ } |
|
| 162 |
+ rr.mu.Lock() |
|
| 163 |
+ defer rr.mu.Unlock() |
|
| 164 |
+ for _, update := range updates {
|
|
| 165 |
+ addr := Address{
|
|
| 166 |
+ Addr: update.Addr, |
|
| 167 |
+ Metadata: update.Metadata, |
|
| 168 |
+ } |
|
| 169 |
+ switch update.Op {
|
|
| 170 |
+ case naming.Add: |
|
| 171 |
+ var exist bool |
|
| 172 |
+ for _, v := range rr.addrs {
|
|
| 173 |
+ if addr == v.addr {
|
|
| 174 |
+ exist = true |
|
| 175 |
+ grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr)
|
|
| 176 |
+ break |
|
| 177 |
+ } |
|
| 178 |
+ } |
|
| 179 |
+ if exist {
|
|
| 180 |
+ continue |
|
| 181 |
+ } |
|
| 182 |
+ rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
|
|
| 183 |
+ case naming.Delete: |
|
| 184 |
+ for i, v := range rr.addrs {
|
|
| 185 |
+ if addr == v.addr {
|
|
| 186 |
+ copy(rr.addrs[i:], rr.addrs[i+1:]) |
|
| 187 |
+ rr.addrs = rr.addrs[:len(rr.addrs)-1] |
|
| 188 |
+ break |
|
| 189 |
+ } |
|
| 190 |
+ } |
|
| 191 |
+ default: |
|
| 192 |
+ grpclog.Println("Unknown update.Op ", update.Op)
|
|
| 193 |
+ } |
|
| 194 |
+ } |
|
| 195 |
+ // Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified. |
|
| 196 |
+ open := make([]Address, len(rr.addrs)) |
|
| 197 |
+ for i, v := range rr.addrs {
|
|
| 198 |
+ open[i] = v.addr |
|
| 199 |
+ } |
|
| 200 |
+ if rr.done {
|
|
| 201 |
+ return ErrClientConnClosing |
|
| 202 |
+ } |
|
| 203 |
+ rr.addrCh <- open |
|
| 204 |
+ return nil |
|
| 205 |
+} |
|
| 206 |
+ |
|
| 207 |
+func (rr *roundRobin) Start(target string) error {
|
|
| 208 |
+ if rr.r == nil {
|
|
| 209 |
+ // If there is no name resolver installed, it is not needed to |
|
| 210 |
+ // do name resolution. In this case, target is added into rr.addrs |
|
| 211 |
+ // as the only address available and rr.addrCh stays nil. |
|
| 212 |
+ rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}})
|
|
| 213 |
+ return nil |
|
| 214 |
+ } |
|
| 215 |
+ w, err := rr.r.Resolve(target) |
|
| 216 |
+ if err != nil {
|
|
| 217 |
+ return err |
|
| 218 |
+ } |
|
| 219 |
+ rr.w = w |
|
| 220 |
+ rr.addrCh = make(chan []Address) |
|
| 221 |
+ go func() {
|
|
| 222 |
+ for {
|
|
| 223 |
+ if err := rr.watchAddrUpdates(); err != nil {
|
|
| 224 |
+ return |
|
| 225 |
+ } |
|
| 226 |
+ } |
|
| 227 |
+ }() |
|
| 228 |
+ return nil |
|
| 229 |
+} |
|
| 230 |
+ |
|
| 231 |
+// Up sets the connected state of addr and sends notification if there are pending |
|
| 232 |
+// Get() calls. |
|
| 233 |
+func (rr *roundRobin) Up(addr Address) func(error) {
|
|
| 234 |
+ rr.mu.Lock() |
|
| 235 |
+ defer rr.mu.Unlock() |
|
| 236 |
+ var cnt int |
|
| 237 |
+ for _, a := range rr.addrs {
|
|
| 238 |
+ if a.addr == addr {
|
|
| 239 |
+ if a.connected {
|
|
| 240 |
+ return nil |
|
| 241 |
+ } |
|
| 242 |
+ a.connected = true |
|
| 243 |
+ } |
|
| 244 |
+ if a.connected {
|
|
| 245 |
+ cnt++ |
|
| 246 |
+ } |
|
| 247 |
+ } |
|
| 248 |
+ // addr is only one which is connected. Notify the Get() callers who are blocking. |
|
| 249 |
+ if cnt == 1 && rr.waitCh != nil {
|
|
| 250 |
+ close(rr.waitCh) |
|
| 251 |
+ rr.waitCh = nil |
|
| 252 |
+ } |
|
| 253 |
+ return func(err error) {
|
|
| 254 |
+ rr.down(addr, err) |
|
| 255 |
+ } |
|
| 256 |
+} |
|
| 257 |
+ |
|
| 258 |
+// down unsets the connected state of addr. |
|
| 259 |
+func (rr *roundRobin) down(addr Address, err error) {
|
|
| 260 |
+ rr.mu.Lock() |
|
| 261 |
+ defer rr.mu.Unlock() |
|
| 262 |
+ for _, a := range rr.addrs {
|
|
| 263 |
+ if addr == a.addr {
|
|
| 264 |
+ a.connected = false |
|
| 265 |
+ break |
|
| 266 |
+ } |
|
| 267 |
+ } |
|
| 268 |
+} |
|
| 269 |
+ |
|
| 270 |
+// Get returns the next addr in the rotation. |
|
| 271 |
+func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
|
|
| 272 |
+ var ch chan struct{}
|
|
| 273 |
+ rr.mu.Lock() |
|
| 274 |
+ if rr.done {
|
|
| 275 |
+ rr.mu.Unlock() |
|
| 276 |
+ err = ErrClientConnClosing |
|
| 277 |
+ return |
|
| 278 |
+ } |
|
| 279 |
+ |
|
| 280 |
+ if len(rr.addrs) > 0 {
|
|
| 281 |
+ if rr.next >= len(rr.addrs) {
|
|
| 282 |
+ rr.next = 0 |
|
| 283 |
+ } |
|
| 284 |
+ next := rr.next |
|
| 285 |
+ for {
|
|
| 286 |
+ a := rr.addrs[next] |
|
| 287 |
+ next = (next + 1) % len(rr.addrs) |
|
| 288 |
+ if a.connected {
|
|
| 289 |
+ addr = a.addr |
|
| 290 |
+ rr.next = next |
|
| 291 |
+ rr.mu.Unlock() |
|
| 292 |
+ return |
|
| 293 |
+ } |
|
| 294 |
+ if next == rr.next {
|
|
| 295 |
+ // Has iterated all the possible address but none is connected. |
|
| 296 |
+ break |
|
| 297 |
+ } |
|
| 298 |
+ } |
|
| 299 |
+ } |
|
| 300 |
+ if !opts.BlockingWait {
|
|
| 301 |
+ if len(rr.addrs) == 0 {
|
|
| 302 |
+ rr.mu.Unlock() |
|
| 303 |
+ err = fmt.Errorf("there is no address available")
|
|
| 304 |
+ return |
|
| 305 |
+ } |
|
| 306 |
+ // Returns the next addr on rr.addrs for failfast RPCs. |
|
| 307 |
+ addr = rr.addrs[rr.next].addr |
|
| 308 |
+ rr.next++ |
|
| 309 |
+ rr.mu.Unlock() |
|
| 310 |
+ return |
|
| 311 |
+ } |
|
| 312 |
+ // Wait on rr.waitCh for non-failfast RPCs. |
|
| 313 |
+ if rr.waitCh == nil {
|
|
| 314 |
+ ch = make(chan struct{})
|
|
| 315 |
+ rr.waitCh = ch |
|
| 316 |
+ } else {
|
|
| 317 |
+ ch = rr.waitCh |
|
| 318 |
+ } |
|
| 319 |
+ rr.mu.Unlock() |
|
| 320 |
+ for {
|
|
| 321 |
+ select {
|
|
| 322 |
+ case <-ctx.Done(): |
|
| 323 |
+ err = ctx.Err() |
|
| 324 |
+ return |
|
| 325 |
+ case <-ch: |
|
| 326 |
+ rr.mu.Lock() |
|
| 327 |
+ if rr.done {
|
|
| 328 |
+ rr.mu.Unlock() |
|
| 329 |
+ err = ErrClientConnClosing |
|
| 330 |
+ return |
|
| 331 |
+ } |
|
| 332 |
+ |
|
| 333 |
+ if len(rr.addrs) > 0 {
|
|
| 334 |
+ if rr.next >= len(rr.addrs) {
|
|
| 335 |
+ rr.next = 0 |
|
| 336 |
+ } |
|
| 337 |
+ next := rr.next |
|
| 338 |
+ for {
|
|
| 339 |
+ a := rr.addrs[next] |
|
| 340 |
+ next = (next + 1) % len(rr.addrs) |
|
| 341 |
+ if a.connected {
|
|
| 342 |
+ addr = a.addr |
|
| 343 |
+ rr.next = next |
|
| 344 |
+ rr.mu.Unlock() |
|
| 345 |
+ return |
|
| 346 |
+ } |
|
| 347 |
+ if next == rr.next {
|
|
| 348 |
+ // Has iterated all the possible address but none is connected. |
|
| 349 |
+ break |
|
| 350 |
+ } |
|
| 351 |
+ } |
|
| 352 |
+ } |
|
| 353 |
+ // The newly added addr got removed by Down() again. |
|
| 354 |
+ if rr.waitCh == nil {
|
|
| 355 |
+ ch = make(chan struct{})
|
|
| 356 |
+ rr.waitCh = ch |
|
| 357 |
+ } else {
|
|
| 358 |
+ ch = rr.waitCh |
|
| 359 |
+ } |
|
| 360 |
+ rr.mu.Unlock() |
|
| 361 |
+ } |
|
| 362 |
+ } |
|
| 363 |
+} |
|
| 364 |
+ |
|
| 365 |
+func (rr *roundRobin) Notify() <-chan []Address {
|
|
| 366 |
+ return rr.addrCh |
|
| 367 |
+} |
|
| 368 |
+ |
|
| 369 |
+func (rr *roundRobin) Close() error {
|
|
| 370 |
+ rr.mu.Lock() |
|
| 371 |
+ defer rr.mu.Unlock() |
|
| 372 |
+ rr.done = true |
|
| 373 |
+ if rr.w != nil {
|
|
| 374 |
+ rr.w.Close() |
|
| 375 |
+ } |
|
| 376 |
+ if rr.waitCh != nil {
|
|
| 377 |
+ close(rr.waitCh) |
|
| 378 |
+ rr.waitCh = nil |
|
| 379 |
+ } |
|
| 380 |
+ if rr.addrCh != nil {
|
|
| 381 |
+ close(rr.addrCh) |
|
| 382 |
+ } |
|
| 383 |
+ return nil |
|
| 384 |
+} |
| ... | ... |
@@ -36,6 +36,7 @@ package grpc |
| 36 | 36 |
import ( |
| 37 | 37 |
"bytes" |
| 38 | 38 |
"io" |
| 39 |
+ "math" |
|
| 39 | 40 |
"time" |
| 40 | 41 |
|
| 41 | 42 |
"golang.org/x/net/context" |
| ... | ... |
@@ -51,13 +52,20 @@ import ( |
| 51 | 51 |
func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error {
|
| 52 | 52 |
// Try to acquire header metadata from the server if there is any. |
| 53 | 53 |
var err error |
| 54 |
+ defer func() {
|
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ if _, ok := err.(transport.ConnectionError); !ok {
|
|
| 57 |
+ t.CloseStream(stream, err) |
|
| 58 |
+ } |
|
| 59 |
+ } |
|
| 60 |
+ }() |
|
| 54 | 61 |
c.headerMD, err = stream.Header() |
| 55 | 62 |
if err != nil {
|
| 56 | 63 |
return err |
| 57 | 64 |
} |
| 58 | 65 |
p := &parser{r: stream}
|
| 59 | 66 |
for {
|
| 60 |
- if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil {
|
|
| 67 |
+ if err = recv(p, dopts.codec, stream, dopts.dc, reply, math.MaxInt32); err != nil {
|
|
| 61 | 68 |
if err == io.EOF {
|
| 62 | 69 |
break |
| 63 | 70 |
} |
| ... | ... |
@@ -76,6 +84,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd |
| 76 | 76 |
} |
| 77 | 77 |
defer func() {
|
| 78 | 78 |
if err != nil {
|
| 79 |
+ // If err is connection error, t will be closed, no need to close stream here. |
|
| 79 | 80 |
if _, ok := err.(transport.ConnectionError); !ok {
|
| 80 | 81 |
t.CloseStream(stream, err) |
| 81 | 82 |
} |
| ... | ... |
@@ -90,7 +99,10 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd |
| 90 | 90 |
return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err) |
| 91 | 91 |
} |
| 92 | 92 |
err = t.Write(stream, outBuf, opts) |
| 93 |
- if err != nil {
|
|
| 93 |
+ // t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method |
|
| 94 |
+ // does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following |
|
| 95 |
+ // recvResponse to get the final status. |
|
| 96 |
+ if err != nil && err != io.EOF {
|
|
| 94 | 97 |
return nil, err |
| 95 | 98 |
} |
| 96 | 99 |
// Sent successfully. |
| ... | ... |
@@ -101,7 +113,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd |
| 101 | 101 |
// Invoke is called by generated code. Also users can call Invoke directly when it |
| 102 | 102 |
// is really needed in their use cases. |
| 103 | 103 |
func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) {
|
| 104 |
- var c callInfo |
|
| 104 |
+ c := defaultCallInfo |
|
| 105 | 105 |
for _, o := range opts {
|
| 106 | 106 |
if err := o.before(&c); err != nil {
|
| 107 | 107 |
return toRPCErr(err) |
| ... | ... |
@@ -132,19 +144,16 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
|
| 132 | 132 |
Last: true, |
| 133 | 133 |
Delay: false, |
| 134 | 134 |
} |
| 135 |
- var ( |
|
| 136 |
- lastErr error // record the error that happened |
|
| 137 |
- ) |
|
| 138 | 135 |
for {
|
| 139 | 136 |
var ( |
| 140 | 137 |
err error |
| 141 | 138 |
t transport.ClientTransport |
| 142 | 139 |
stream *transport.Stream |
| 140 |
+ // Record the put handler from Balancer.Get(...). It is called once the |
|
| 141 |
+ // RPC has completed or failed. |
|
| 142 |
+ put func() |
|
| 143 | 143 |
) |
| 144 |
- // TODO(zhaoq): Need a formal spec of retry strategy for non-failfast rpcs. |
|
| 145 |
- if lastErr != nil && c.failFast {
|
|
| 146 |
- return toRPCErr(lastErr) |
|
| 147 |
- } |
|
| 144 |
+ // TODO(zhaoq): Need a formal spec of fail-fast. |
|
| 148 | 145 |
callHdr := &transport.CallHdr{
|
| 149 | 146 |
Host: cc.authority, |
| 150 | 147 |
Method: method, |
| ... | ... |
@@ -152,39 +161,65 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
|
| 152 | 152 |
if cc.dopts.cp != nil {
|
| 153 | 153 |
callHdr.SendCompress = cc.dopts.cp.Type() |
| 154 | 154 |
} |
| 155 |
- t, err = cc.dopts.picker.Pick(ctx) |
|
| 155 |
+ gopts := BalancerGetOptions{
|
|
| 156 |
+ BlockingWait: !c.failFast, |
|
| 157 |
+ } |
|
| 158 |
+ t, put, err = cc.getTransport(ctx, gopts) |
|
| 156 | 159 |
if err != nil {
|
| 157 |
- if lastErr != nil {
|
|
| 158 |
- // This was a retry; return the error from the last attempt. |
|
| 159 |
- return toRPCErr(lastErr) |
|
| 160 |
+ // TODO(zhaoq): Probably revisit the error handling. |
|
| 161 |
+ if _, ok := err.(*rpcError); ok {
|
|
| 162 |
+ return err |
|
| 160 | 163 |
} |
| 161 |
- return toRPCErr(err) |
|
| 164 |
+ if err == errConnClosing || err == errConnUnavailable {
|
|
| 165 |
+ if c.failFast {
|
|
| 166 |
+ return Errorf(codes.Unavailable, "%v", err) |
|
| 167 |
+ } |
|
| 168 |
+ continue |
|
| 169 |
+ } |
|
| 170 |
+ // All the other errors are treated as Internal errors. |
|
| 171 |
+ return Errorf(codes.Internal, "%v", err) |
|
| 162 | 172 |
} |
| 163 | 173 |
if c.traceInfo.tr != nil {
|
| 164 | 174 |
c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)
|
| 165 | 175 |
} |
| 166 | 176 |
stream, err = sendRequest(ctx, cc.dopts.codec, cc.dopts.cp, callHdr, t, args, topts) |
| 167 | 177 |
if err != nil {
|
| 168 |
- if _, ok := err.(transport.ConnectionError); ok {
|
|
| 169 |
- lastErr = err |
|
| 170 |
- continue |
|
| 178 |
+ if put != nil {
|
|
| 179 |
+ put() |
|
| 180 |
+ put = nil |
|
| 171 | 181 |
} |
| 172 |
- if lastErr != nil {
|
|
| 173 |
- return toRPCErr(lastErr) |
|
| 182 |
+ // Retry a non-failfast RPC when |
|
| 183 |
+ // i) there is a connection error; or |
|
| 184 |
+ // ii) the server started to drain before this RPC was initiated. |
|
| 185 |
+ if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain {
|
|
| 186 |
+ if c.failFast {
|
|
| 187 |
+ return toRPCErr(err) |
|
| 188 |
+ } |
|
| 189 |
+ continue |
|
| 174 | 190 |
} |
| 175 | 191 |
return toRPCErr(err) |
| 176 | 192 |
} |
| 177 |
- // Receive the response |
|
| 178 |
- lastErr = recvResponse(cc.dopts, t, &c, stream, reply) |
|
| 179 |
- if _, ok := lastErr.(transport.ConnectionError); ok {
|
|
| 180 |
- continue |
|
| 193 |
+ err = recvResponse(cc.dopts, t, &c, stream, reply) |
|
| 194 |
+ if err != nil {
|
|
| 195 |
+ if put != nil {
|
|
| 196 |
+ put() |
|
| 197 |
+ put = nil |
|
| 198 |
+ } |
|
| 199 |
+ if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain {
|
|
| 200 |
+ if c.failFast {
|
|
| 201 |
+ return toRPCErr(err) |
|
| 202 |
+ } |
|
| 203 |
+ continue |
|
| 204 |
+ } |
|
| 205 |
+ return toRPCErr(err) |
|
| 181 | 206 |
} |
| 182 | 207 |
if c.traceInfo.tr != nil {
|
| 183 | 208 |
c.traceInfo.tr.LazyLog(&payload{sent: false, msg: reply}, true)
|
| 184 | 209 |
} |
| 185 |
- t.CloseStream(stream, lastErr) |
|
| 186 |
- if lastErr != nil {
|
|
| 187 |
- return toRPCErr(lastErr) |
|
| 210 |
+ t.CloseStream(stream, nil) |
|
| 211 |
+ if put != nil {
|
|
| 212 |
+ put() |
|
| 213 |
+ put = nil |
|
| 188 | 214 |
} |
| 189 | 215 |
return Errorf(stream.StatusCode(), "%s", stream.StatusDesc()) |
| 190 | 216 |
} |
| ... | ... |
@@ -49,22 +49,33 @@ import ( |
| 49 | 49 |
) |
| 50 | 50 |
|
| 51 | 51 |
var ( |
| 52 |
- // ErrUnspecTarget indicates that the target address is unspecified. |
|
| 53 |
- ErrUnspecTarget = errors.New("grpc: target is unspecified")
|
|
| 54 |
- // ErrNoTransportSecurity indicates that there is no transport security |
|
| 52 |
+ // ErrClientConnClosing indicates that the operation is illegal because |
|
| 53 |
+ // the ClientConn is closing. |
|
| 54 |
+ ErrClientConnClosing = errors.New("grpc: the client connection is closing")
|
|
| 55 |
+ // ErrClientConnTimeout indicates that the ClientConn cannot establish the |
|
| 56 |
+ // underlying connections within the specified timeout. |
|
| 57 |
+ ErrClientConnTimeout = errors.New("grpc: timed out when dialing")
|
|
| 58 |
+ |
|
| 59 |
+ // errNoTransportSecurity indicates that there is no transport security |
|
| 55 | 60 |
// being set for ClientConn. Users should either set one or explicitly |
| 56 | 61 |
// call WithInsecure DialOption to disable security. |
| 57 |
- ErrNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
|
|
| 58 |
- // ErrCredentialsMisuse indicates that users want to transmit security information |
|
| 59 |
- // (e.g., oauth2 token) which requires secure connection on an insecure |
|
| 62 |
+ errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
|
|
| 63 |
+ // errTransportCredentialsMissing indicates that users want to transmit security |
|
| 64 |
+ // information (e.g., oauth2 token) which requires secure connection on an insecure |
|
| 60 | 65 |
// connection. |
| 61 |
- ErrCredentialsMisuse = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportAuthenticator() to set)")
|
|
| 62 |
- // ErrClientConnClosing indicates that the operation is illegal because |
|
| 63 |
- // the session is closing. |
|
| 64 |
- ErrClientConnClosing = errors.New("grpc: the client connection is closing")
|
|
| 65 |
- // ErrClientConnTimeout indicates that the connection could not be |
|
| 66 |
- // established or re-established within the specified timeout. |
|
| 67 |
- ErrClientConnTimeout = errors.New("grpc: timed out trying to connect")
|
|
| 66 |
+ errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
|
|
| 67 |
+ // errCredentialsConflict indicates that grpc.WithTransportCredentials() |
|
| 68 |
+ // and grpc.WithInsecure() are both called for a connection. |
|
| 69 |
+ errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)")
|
|
| 70 |
+ // errNetworkIO indicates that the connection is down due to some network I/O error. |
|
| 71 |
+ errNetworkIO = errors.New("grpc: failed with network I/O error")
|
|
| 72 |
+ // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs. |
|
| 73 |
+ errConnDrain = errors.New("grpc: the connection is drained")
|
|
| 74 |
+ // errConnClosing indicates that the connection is closing. |
|
| 75 |
+ errConnClosing = errors.New("grpc: the connection is closing")
|
|
| 76 |
+ // errConnUnavailable indicates that the connection is unavailable. |
|
| 77 |
+ errConnUnavailable = errors.New("grpc: the connection is unavailable")
|
|
| 78 |
+ errNoAddr = errors.New("grpc: there is no address available to dial")
|
|
| 68 | 79 |
// minimum time to give a connection to complete |
| 69 | 80 |
minConnectTimeout = 20 * time.Second |
| 70 | 81 |
) |
| ... | ... |
@@ -76,9 +87,10 @@ type dialOptions struct {
|
| 76 | 76 |
cp Compressor |
| 77 | 77 |
dc Decompressor |
| 78 | 78 |
bs backoffStrategy |
| 79 |
- picker Picker |
|
| 79 |
+ balancer Balancer |
|
| 80 | 80 |
block bool |
| 81 | 81 |
insecure bool |
| 82 |
+ timeout time.Duration |
|
| 82 | 83 |
copts transport.ConnectOptions |
| 83 | 84 |
} |
| 84 | 85 |
|
| ... | ... |
@@ -108,10 +120,10 @@ func WithDecompressor(dc Decompressor) DialOption {
|
| 108 | 108 |
} |
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 |
-// WithPicker returns a DialOption which sets a picker for connection selection. |
|
| 112 |
-func WithPicker(p Picker) DialOption {
|
|
| 111 |
+// WithBalancer returns a DialOption which sets a load balancer. |
|
| 112 |
+func WithBalancer(b Balancer) DialOption {
|
|
| 113 | 113 |
return func(o *dialOptions) {
|
| 114 |
- o.picker = p |
|
| 114 |
+ o.balancer = b |
|
| 115 | 115 |
} |
| 116 | 116 |
} |
| 117 | 117 |
|
| ... | ... |
@@ -136,7 +148,7 @@ func WithBackoffConfig(b BackoffConfig) DialOption {
|
| 136 | 136 |
// withBackoff sets the backoff strategy used for retries after a |
| 137 | 137 |
// failed connection attempt. |
| 138 | 138 |
// |
| 139 |
-// This can be exported if arbitrary backoff strategies are allowed by GRPC. |
|
| 139 |
+// This can be exported if arbitrary backoff strategies are allowed by gRPC. |
|
| 140 | 140 |
func withBackoff(bs backoffStrategy) DialOption {
|
| 141 | 141 |
return func(o *dialOptions) {
|
| 142 | 142 |
o.bs = bs |
| ... | ... |
@@ -162,31 +174,37 @@ func WithInsecure() DialOption {
|
| 162 | 162 |
|
| 163 | 163 |
// WithTransportCredentials returns a DialOption which configures a |
| 164 | 164 |
// connection level security credentials (e.g., TLS/SSL). |
| 165 |
-func WithTransportCredentials(creds credentials.TransportAuthenticator) DialOption {
|
|
| 165 |
+func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
|
|
| 166 | 166 |
return func(o *dialOptions) {
|
| 167 |
- o.copts.AuthOptions = append(o.copts.AuthOptions, creds) |
|
| 167 |
+ o.copts.TransportCredentials = creds |
|
| 168 | 168 |
} |
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 | 171 |
// WithPerRPCCredentials returns a DialOption which sets |
| 172 | 172 |
// credentials which will place auth state on each outbound RPC. |
| 173 |
-func WithPerRPCCredentials(creds credentials.Credentials) DialOption {
|
|
| 173 |
+func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
|
|
| 174 | 174 |
return func(o *dialOptions) {
|
| 175 |
- o.copts.AuthOptions = append(o.copts.AuthOptions, creds) |
|
| 175 |
+ o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) |
|
| 176 | 176 |
} |
| 177 | 177 |
} |
| 178 | 178 |
|
| 179 |
-// WithTimeout returns a DialOption that configures a timeout for dialing a client connection. |
|
| 179 |
+// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn |
|
| 180 |
+// initially. This is valid if and only if WithBlock() is present. |
|
| 180 | 181 |
func WithTimeout(d time.Duration) DialOption {
|
| 181 | 182 |
return func(o *dialOptions) {
|
| 182 |
- o.copts.Timeout = d |
|
| 183 |
+ o.timeout = d |
|
| 183 | 184 |
} |
| 184 | 185 |
} |
| 185 | 186 |
|
| 186 | 187 |
// WithDialer returns a DialOption that specifies a function to use for dialing network addresses. |
| 187 |
-func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption {
|
|
| 188 |
+func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
|
|
| 188 | 189 |
return func(o *dialOptions) {
|
| 189 |
- o.copts.Dialer = f |
|
| 190 |
+ o.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) {
|
|
| 191 |
+ if deadline, ok := ctx.Deadline(); ok {
|
|
| 192 |
+ return f(addr, deadline.Sub(time.Now())) |
|
| 193 |
+ } |
|
| 194 |
+ return f(addr, 0) |
|
| 195 |
+ } |
|
| 190 | 196 |
} |
| 191 | 197 |
} |
| 192 | 198 |
|
| ... | ... |
@@ -197,30 +215,84 @@ func WithUserAgent(s string) DialOption {
|
| 197 | 197 |
} |
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 |
-// Dial creates a client connection the given target. |
|
| 200 |
+// Dial creates a client connection to the given target. |
|
| 201 | 201 |
func Dial(target string, opts ...DialOption) (*ClientConn, error) {
|
| 202 |
+ return DialContext(context.Background(), target, opts...) |
|
| 203 |
+} |
|
| 204 |
+ |
|
| 205 |
+// DialContext creates a client connection to the given target |
|
| 206 |
+// using the supplied context. |
|
| 207 |
+func DialContext(ctx context.Context, target string, opts ...DialOption) (*ClientConn, error) {
|
|
| 202 | 208 |
cc := &ClientConn{
|
| 203 | 209 |
target: target, |
| 210 |
+ conns: make(map[Address]*addrConn), |
|
| 204 | 211 |
} |
| 212 |
+ cc.ctx, cc.cancel = context.WithCancel(ctx) |
|
| 205 | 213 |
for _, opt := range opts {
|
| 206 | 214 |
opt(&cc.dopts) |
| 207 | 215 |
} |
| 216 |
+ |
|
| 217 |
+ // Set defaults. |
|
| 208 | 218 |
if cc.dopts.codec == nil {
|
| 209 |
- // Set the default codec. |
|
| 210 | 219 |
cc.dopts.codec = protoCodec{}
|
| 211 | 220 |
} |
| 212 |
- |
|
| 213 | 221 |
if cc.dopts.bs == nil {
|
| 214 | 222 |
cc.dopts.bs = DefaultBackoffConfig |
| 215 | 223 |
} |
| 216 | 224 |
|
| 217 |
- if cc.dopts.picker == nil {
|
|
| 218 |
- cc.dopts.picker = &unicastPicker{
|
|
| 219 |
- target: target, |
|
| 225 |
+ var ( |
|
| 226 |
+ ok bool |
|
| 227 |
+ addrs []Address |
|
| 228 |
+ ) |
|
| 229 |
+ if cc.dopts.balancer == nil {
|
|
| 230 |
+ // Connect to target directly if balancer is nil. |
|
| 231 |
+ addrs = append(addrs, Address{Addr: target})
|
|
| 232 |
+ } else {
|
|
| 233 |
+ if err := cc.dopts.balancer.Start(target); err != nil {
|
|
| 234 |
+ return nil, err |
|
| 235 |
+ } |
|
| 236 |
+ ch := cc.dopts.balancer.Notify() |
|
| 237 |
+ if ch == nil {
|
|
| 238 |
+ // There is no name resolver installed. |
|
| 239 |
+ addrs = append(addrs, Address{Addr: target})
|
|
| 240 |
+ } else {
|
|
| 241 |
+ addrs, ok = <-ch |
|
| 242 |
+ if !ok || len(addrs) == 0 {
|
|
| 243 |
+ return nil, errNoAddr |
|
| 244 |
+ } |
|
| 245 |
+ } |
|
| 246 |
+ } |
|
| 247 |
+ waitC := make(chan error, 1) |
|
| 248 |
+ go func() {
|
|
| 249 |
+ for _, a := range addrs {
|
|
| 250 |
+ if err := cc.resetAddrConn(a, false, nil); err != nil {
|
|
| 251 |
+ waitC <- err |
|
| 252 |
+ return |
|
| 253 |
+ } |
|
| 220 | 254 |
} |
| 255 |
+ close(waitC) |
|
| 256 |
+ }() |
|
| 257 |
+ var timeoutCh <-chan time.Time |
|
| 258 |
+ if cc.dopts.timeout > 0 {
|
|
| 259 |
+ timeoutCh = time.After(cc.dopts.timeout) |
|
| 221 | 260 |
} |
| 222 |
- if err := cc.dopts.picker.Init(cc); err != nil {
|
|
| 223 |
- return nil, err |
|
| 261 |
+ select {
|
|
| 262 |
+ case err := <-waitC: |
|
| 263 |
+ if err != nil {
|
|
| 264 |
+ cc.Close() |
|
| 265 |
+ return nil, err |
|
| 266 |
+ } |
|
| 267 |
+ case <-cc.ctx.Done(): |
|
| 268 |
+ cc.Close() |
|
| 269 |
+ return nil, cc.ctx.Err() |
|
| 270 |
+ case <-timeoutCh: |
|
| 271 |
+ cc.Close() |
|
| 272 |
+ return nil, ErrClientConnTimeout |
|
| 273 |
+ } |
|
| 274 |
+ // If balancer is nil or balancer.Notify() is nil, ok will be false here. |
|
| 275 |
+ // The lbWatcher goroutine will not be created. |
|
| 276 |
+ if ok {
|
|
| 277 |
+ go cc.lbWatcher() |
|
| 224 | 278 |
} |
| 225 | 279 |
colonPos := strings.LastIndex(target, ":") |
| 226 | 280 |
if colonPos == -1 {
|
| ... | ... |
@@ -263,361 +335,511 @@ func (s ConnectivityState) String() string {
|
| 263 | 263 |
} |
| 264 | 264 |
} |
| 265 | 265 |
|
| 266 |
-// ClientConn represents a client connection to an RPC service. |
|
| 266 |
+// ClientConn represents a client connection to an RPC server. |
|
| 267 | 267 |
type ClientConn struct {
|
| 268 |
+ ctx context.Context |
|
| 269 |
+ cancel context.CancelFunc |
|
| 270 |
+ |
|
| 268 | 271 |
target string |
| 269 | 272 |
authority string |
| 270 | 273 |
dopts dialOptions |
| 271 |
-} |
|
| 272 |
- |
|
| 273 |
-// State returns the connectivity state of cc. |
|
| 274 |
-// This is EXPERIMENTAL API. |
|
| 275 |
-func (cc *ClientConn) State() (ConnectivityState, error) {
|
|
| 276 |
- return cc.dopts.picker.State() |
|
| 277 |
-} |
|
| 278 | 274 |
|
| 279 |
-// WaitForStateChange blocks until the state changes to something other than the sourceState. |
|
| 280 |
-// It returns the new state or error. |
|
| 281 |
-// This is EXPERIMENTAL API. |
|
| 282 |
-func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
|
|
| 283 |
- return cc.dopts.picker.WaitForStateChange(ctx, sourceState) |
|
| 275 |
+ mu sync.RWMutex |
|
| 276 |
+ conns map[Address]*addrConn |
|
| 284 | 277 |
} |
| 285 | 278 |
|
| 286 |
-// Close starts to tear down the ClientConn. |
|
| 287 |
-func (cc *ClientConn) Close() error {
|
|
| 288 |
- return cc.dopts.picker.Close() |
|
| 289 |
-} |
|
| 290 |
- |
|
| 291 |
-// Conn is a client connection to a single destination. |
|
| 292 |
-type Conn struct {
|
|
| 293 |
- target string |
|
| 294 |
- dopts dialOptions |
|
| 295 |
- resetChan chan int |
|
| 296 |
- shutdownChan chan struct{}
|
|
| 297 |
- events trace.EventLog |
|
| 298 |
- |
|
| 299 |
- mu sync.Mutex |
|
| 300 |
- state ConnectivityState |
|
| 301 |
- stateCV *sync.Cond |
|
| 302 |
- // ready is closed and becomes nil when a new transport is up or failed |
|
| 303 |
- // due to timeout. |
|
| 304 |
- ready chan struct{}
|
|
| 305 |
- transport transport.ClientTransport |
|
| 279 |
+func (cc *ClientConn) lbWatcher() {
|
|
| 280 |
+ for addrs := range cc.dopts.balancer.Notify() {
|
|
| 281 |
+ var ( |
|
| 282 |
+ add []Address // Addresses need to setup connections. |
|
| 283 |
+ del []*addrConn // Connections need to tear down. |
|
| 284 |
+ ) |
|
| 285 |
+ cc.mu.Lock() |
|
| 286 |
+ for _, a := range addrs {
|
|
| 287 |
+ if _, ok := cc.conns[a]; !ok {
|
|
| 288 |
+ add = append(add, a) |
|
| 289 |
+ } |
|
| 290 |
+ } |
|
| 291 |
+ for k, c := range cc.conns {
|
|
| 292 |
+ var keep bool |
|
| 293 |
+ for _, a := range addrs {
|
|
| 294 |
+ if k == a {
|
|
| 295 |
+ keep = true |
|
| 296 |
+ break |
|
| 297 |
+ } |
|
| 298 |
+ } |
|
| 299 |
+ if !keep {
|
|
| 300 |
+ del = append(del, c) |
|
| 301 |
+ delete(cc.conns, c.addr) |
|
| 302 |
+ } |
|
| 303 |
+ } |
|
| 304 |
+ cc.mu.Unlock() |
|
| 305 |
+ for _, a := range add {
|
|
| 306 |
+ cc.resetAddrConn(a, true, nil) |
|
| 307 |
+ } |
|
| 308 |
+ for _, c := range del {
|
|
| 309 |
+ c.tearDown(errConnDrain) |
|
| 310 |
+ } |
|
| 311 |
+ } |
|
| 306 | 312 |
} |
| 307 | 313 |
|
| 308 |
-// NewConn creates a Conn. |
|
| 309 |
-func NewConn(cc *ClientConn) (*Conn, error) {
|
|
| 310 |
- if cc.target == "" {
|
|
| 311 |
- return nil, ErrUnspecTarget |
|
| 312 |
- } |
|
| 313 |
- c := &Conn{
|
|
| 314 |
- target: cc.target, |
|
| 315 |
- dopts: cc.dopts, |
|
| 316 |
- resetChan: make(chan int, 1), |
|
| 317 |
- shutdownChan: make(chan struct{}),
|
|
| 314 |
+// resetAddrConn creates an addrConn for addr and adds it to cc.conns. |
|
| 315 |
+// If there is an old addrConn for addr, it will be torn down, using tearDownErr as the reason. |
|
| 316 |
+// If tearDownErr is nil, errConnDrain will be used instead. |
|
| 317 |
+func (cc *ClientConn) resetAddrConn(addr Address, skipWait bool, tearDownErr error) error {
|
|
| 318 |
+ ac := &addrConn{
|
|
| 319 |
+ cc: cc, |
|
| 320 |
+ addr: addr, |
|
| 321 |
+ dopts: cc.dopts, |
|
| 318 | 322 |
} |
| 323 |
+ ac.ctx, ac.cancel = context.WithCancel(cc.ctx) |
|
| 324 |
+ ac.stateCV = sync.NewCond(&ac.mu) |
|
| 319 | 325 |
if EnableTracing {
|
| 320 |
- c.events = trace.NewEventLog("grpc.ClientConn", c.target)
|
|
| 326 |
+ ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr)
|
|
| 321 | 327 |
} |
| 322 |
- if !c.dopts.insecure {
|
|
| 323 |
- var ok bool |
|
| 324 |
- for _, cd := range c.dopts.copts.AuthOptions {
|
|
| 325 |
- if _, ok = cd.(credentials.TransportAuthenticator); ok {
|
|
| 326 |
- break |
|
| 327 |
- } |
|
| 328 |
- } |
|
| 329 |
- if !ok {
|
|
| 330 |
- return nil, ErrNoTransportSecurity |
|
| 328 |
+ if !ac.dopts.insecure {
|
|
| 329 |
+ if ac.dopts.copts.TransportCredentials == nil {
|
|
| 330 |
+ return errNoTransportSecurity |
|
| 331 | 331 |
} |
| 332 | 332 |
} else {
|
| 333 |
- for _, cd := range c.dopts.copts.AuthOptions {
|
|
| 333 |
+ if ac.dopts.copts.TransportCredentials != nil {
|
|
| 334 |
+ return errCredentialsConflict |
|
| 335 |
+ } |
|
| 336 |
+ for _, cd := range ac.dopts.copts.PerRPCCredentials {
|
|
| 334 | 337 |
if cd.RequireTransportSecurity() {
|
| 335 |
- return nil, ErrCredentialsMisuse |
|
| 338 |
+ return errTransportCredentialsMissing |
|
| 336 | 339 |
} |
| 337 | 340 |
} |
| 338 | 341 |
} |
| 339 |
- c.stateCV = sync.NewCond(&c.mu) |
|
| 340 |
- if c.dopts.block {
|
|
| 341 |
- if err := c.resetTransport(false); err != nil {
|
|
| 342 |
- c.Close() |
|
| 343 |
- return nil, err |
|
| 342 |
+ // Track ac in cc. This needs to be done before any getTransport(...) is called. |
|
| 343 |
+ cc.mu.Lock() |
|
| 344 |
+ if cc.conns == nil {
|
|
| 345 |
+ cc.mu.Unlock() |
|
| 346 |
+ return ErrClientConnClosing |
|
| 347 |
+ } |
|
| 348 |
+ stale := cc.conns[ac.addr] |
|
| 349 |
+ cc.conns[ac.addr] = ac |
|
| 350 |
+ cc.mu.Unlock() |
|
| 351 |
+ if stale != nil {
|
|
| 352 |
+ // There is an addrConn alive on ac.addr already. This could be due to |
|
| 353 |
+ // 1) a buggy Balancer notifies duplicated Addresses; |
|
| 354 |
+ // 2) goaway was received, a new ac will replace the old ac. |
|
| 355 |
+ // The old ac should be deleted from cc.conns, but the |
|
| 356 |
+ // underlying transport should drain rather than close. |
|
| 357 |
+ if tearDownErr == nil {
|
|
| 358 |
+ // tearDownErr is nil if resetAddrConn is called by |
|
| 359 |
+ // 1) Dial |
|
| 360 |
+ // 2) lbWatcher |
|
| 361 |
+ // In both cases, the stale ac should drain, not close. |
|
| 362 |
+ stale.tearDown(errConnDrain) |
|
| 363 |
+ } else {
|
|
| 364 |
+ stale.tearDown(tearDownErr) |
|
| 365 |
+ } |
|
| 366 |
+ } |
|
| 367 |
+ // skipWait may overwrite the decision in ac.dopts.block. |
|
| 368 |
+ if ac.dopts.block && !skipWait {
|
|
| 369 |
+ if err := ac.resetTransport(false); err != nil {
|
|
| 370 |
+ if err != errConnClosing {
|
|
| 371 |
+ // Tear down ac and delete it from cc.conns. |
|
| 372 |
+ cc.mu.Lock() |
|
| 373 |
+ delete(cc.conns, ac.addr) |
|
| 374 |
+ cc.mu.Unlock() |
|
| 375 |
+ ac.tearDown(err) |
|
| 376 |
+ } |
|
| 377 |
+ if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() {
|
|
| 378 |
+ return e.Origin() |
|
| 379 |
+ } |
|
| 380 |
+ return err |
|
| 344 | 381 |
} |
| 345 | 382 |
// Start to monitor the error status of transport. |
| 346 |
- go c.transportMonitor() |
|
| 383 |
+ go ac.transportMonitor() |
|
| 347 | 384 |
} else {
|
| 348 | 385 |
// Start a goroutine connecting to the server asynchronously. |
| 349 | 386 |
go func() {
|
| 350 |
- if err := c.resetTransport(false); err != nil {
|
|
| 351 |
- grpclog.Printf("Failed to dial %s: %v; please retry.", c.target, err)
|
|
| 352 |
- c.Close() |
|
| 387 |
+ if err := ac.resetTransport(false); err != nil {
|
|
| 388 |
+ grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err)
|
|
| 389 |
+ if err != errConnClosing {
|
|
| 390 |
+ // Keep this ac in cc.conns, to get the reason it's torn down. |
|
| 391 |
+ ac.tearDown(err) |
|
| 392 |
+ } |
|
| 353 | 393 |
return |
| 354 | 394 |
} |
| 355 |
- c.transportMonitor() |
|
| 395 |
+ ac.transportMonitor() |
|
| 356 | 396 |
}() |
| 357 | 397 |
} |
| 358 |
- return c, nil |
|
| 398 |
+ return nil |
|
| 359 | 399 |
} |
| 360 | 400 |
|
| 361 |
-// printf records an event in cc's event log, unless cc has been closed. |
|
| 362 |
-// REQUIRES cc.mu is held. |
|
| 363 |
-func (cc *Conn) printf(format string, a ...interface{}) {
|
|
| 364 |
- if cc.events != nil {
|
|
| 365 |
- cc.events.Printf(format, a...) |
|
| 401 |
+func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) {
|
|
| 402 |
+ var ( |
|
| 403 |
+ ac *addrConn |
|
| 404 |
+ ok bool |
|
| 405 |
+ put func() |
|
| 406 |
+ ) |
|
| 407 |
+ if cc.dopts.balancer == nil {
|
|
| 408 |
+ // If balancer is nil, there should be only one addrConn available. |
|
| 409 |
+ cc.mu.RLock() |
|
| 410 |
+ if cc.conns == nil {
|
|
| 411 |
+ cc.mu.RUnlock() |
|
| 412 |
+ return nil, nil, toRPCErr(ErrClientConnClosing) |
|
| 413 |
+ } |
|
| 414 |
+ for _, ac = range cc.conns {
|
|
| 415 |
+ // Break after the first iteration to get the first addrConn. |
|
| 416 |
+ ok = true |
|
| 417 |
+ break |
|
| 418 |
+ } |
|
| 419 |
+ cc.mu.RUnlock() |
|
| 420 |
+ } else {
|
|
| 421 |
+ var ( |
|
| 422 |
+ addr Address |
|
| 423 |
+ err error |
|
| 424 |
+ ) |
|
| 425 |
+ addr, put, err = cc.dopts.balancer.Get(ctx, opts) |
|
| 426 |
+ if err != nil {
|
|
| 427 |
+ return nil, nil, toRPCErr(err) |
|
| 428 |
+ } |
|
| 429 |
+ cc.mu.RLock() |
|
| 430 |
+ if cc.conns == nil {
|
|
| 431 |
+ cc.mu.RUnlock() |
|
| 432 |
+ return nil, nil, toRPCErr(ErrClientConnClosing) |
|
| 433 |
+ } |
|
| 434 |
+ ac, ok = cc.conns[addr] |
|
| 435 |
+ cc.mu.RUnlock() |
|
| 366 | 436 |
} |
| 437 |
+ if !ok {
|
|
| 438 |
+ if put != nil {
|
|
| 439 |
+ put() |
|
| 440 |
+ } |
|
| 441 |
+ return nil, nil, errConnClosing |
|
| 442 |
+ } |
|
| 443 |
+ t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait) |
|
| 444 |
+ if err != nil {
|
|
| 445 |
+ if put != nil {
|
|
| 446 |
+ put() |
|
| 447 |
+ } |
|
| 448 |
+ return nil, nil, err |
|
| 449 |
+ } |
|
| 450 |
+ return t, put, nil |
|
| 367 | 451 |
} |
| 368 | 452 |
|
| 369 |
-// errorf records an error in cc's event log, unless cc has been closed. |
|
| 370 |
-// REQUIRES cc.mu is held. |
|
| 371 |
-func (cc *Conn) errorf(format string, a ...interface{}) {
|
|
| 372 |
- if cc.events != nil {
|
|
| 373 |
- cc.events.Errorf(format, a...) |
|
| 453 |
+// Close tears down the ClientConn and all underlying connections. |
|
| 454 |
+func (cc *ClientConn) Close() error {
|
|
| 455 |
+ cc.cancel() |
|
| 456 |
+ |
|
| 457 |
+ cc.mu.Lock() |
|
| 458 |
+ if cc.conns == nil {
|
|
| 459 |
+ cc.mu.Unlock() |
|
| 460 |
+ return ErrClientConnClosing |
|
| 374 | 461 |
} |
| 462 |
+ conns := cc.conns |
|
| 463 |
+ cc.conns = nil |
|
| 464 |
+ cc.mu.Unlock() |
|
| 465 |
+ if cc.dopts.balancer != nil {
|
|
| 466 |
+ cc.dopts.balancer.Close() |
|
| 467 |
+ } |
|
| 468 |
+ for _, ac := range conns {
|
|
| 469 |
+ ac.tearDown(ErrClientConnClosing) |
|
| 470 |
+ } |
|
| 471 |
+ return nil |
|
| 375 | 472 |
} |
| 376 | 473 |
|
| 377 |
-// State returns the connectivity state of the Conn |
|
| 378 |
-func (cc *Conn) State() ConnectivityState {
|
|
| 379 |
- cc.mu.Lock() |
|
| 380 |
- defer cc.mu.Unlock() |
|
| 381 |
- return cc.state |
|
| 474 |
+// addrConn is a network connection to a given address. |
|
| 475 |
+type addrConn struct {
|
|
| 476 |
+ ctx context.Context |
|
| 477 |
+ cancel context.CancelFunc |
|
| 478 |
+ |
|
| 479 |
+ cc *ClientConn |
|
| 480 |
+ addr Address |
|
| 481 |
+ dopts dialOptions |
|
| 482 |
+ events trace.EventLog |
|
| 483 |
+ |
|
| 484 |
+ mu sync.Mutex |
|
| 485 |
+ state ConnectivityState |
|
| 486 |
+ stateCV *sync.Cond |
|
| 487 |
+ down func(error) // the handler called when a connection is down. |
|
| 488 |
+ // ready is closed and becomes nil when a new transport is up or failed |
|
| 489 |
+ // due to timeout. |
|
| 490 |
+ ready chan struct{}
|
|
| 491 |
+ transport transport.ClientTransport |
|
| 492 |
+ |
|
| 493 |
+ // The reason this addrConn is torn down. |
|
| 494 |
+ tearDownErr error |
|
| 382 | 495 |
} |
| 383 | 496 |
|
| 384 |
-// WaitForStateChange blocks until the state changes to something other than the sourceState. |
|
| 385 |
-func (cc *Conn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
|
|
| 386 |
- cc.mu.Lock() |
|
| 387 |
- defer cc.mu.Unlock() |
|
| 388 |
- if sourceState != cc.state {
|
|
| 389 |
- return cc.state, nil |
|
| 497 |
+// printf records an event in ac's event log, unless ac has been closed. |
|
| 498 |
+// REQUIRES ac.mu is held. |
|
| 499 |
+func (ac *addrConn) printf(format string, a ...interface{}) {
|
|
| 500 |
+ if ac.events != nil {
|
|
| 501 |
+ ac.events.Printf(format, a...) |
|
| 502 |
+ } |
|
| 503 |
+} |
|
| 504 |
+ |
|
| 505 |
+// errorf records an error in ac's event log, unless ac has been closed. |
|
| 506 |
+// REQUIRES ac.mu is held. |
|
| 507 |
+func (ac *addrConn) errorf(format string, a ...interface{}) {
|
|
| 508 |
+ if ac.events != nil {
|
|
| 509 |
+ ac.events.Errorf(format, a...) |
|
| 510 |
+ } |
|
| 511 |
+} |
|
| 512 |
+ |
|
| 513 |
+// getState returns the connectivity state of the Conn |
|
| 514 |
+func (ac *addrConn) getState() ConnectivityState {
|
|
| 515 |
+ ac.mu.Lock() |
|
| 516 |
+ defer ac.mu.Unlock() |
|
| 517 |
+ return ac.state |
|
| 518 |
+} |
|
| 519 |
+ |
|
| 520 |
+// waitForStateChange blocks until the state changes to something other than the sourceState. |
|
| 521 |
+func (ac *addrConn) waitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
|
|
| 522 |
+ ac.mu.Lock() |
|
| 523 |
+ defer ac.mu.Unlock() |
|
| 524 |
+ if sourceState != ac.state {
|
|
| 525 |
+ return ac.state, nil |
|
| 390 | 526 |
} |
| 391 | 527 |
done := make(chan struct{})
|
| 392 | 528 |
var err error |
| 393 | 529 |
go func() {
|
| 394 | 530 |
select {
|
| 395 | 531 |
case <-ctx.Done(): |
| 396 |
- cc.mu.Lock() |
|
| 532 |
+ ac.mu.Lock() |
|
| 397 | 533 |
err = ctx.Err() |
| 398 |
- cc.stateCV.Broadcast() |
|
| 399 |
- cc.mu.Unlock() |
|
| 534 |
+ ac.stateCV.Broadcast() |
|
| 535 |
+ ac.mu.Unlock() |
|
| 400 | 536 |
case <-done: |
| 401 | 537 |
} |
| 402 | 538 |
}() |
| 403 | 539 |
defer close(done) |
| 404 |
- for sourceState == cc.state {
|
|
| 405 |
- cc.stateCV.Wait() |
|
| 540 |
+ for sourceState == ac.state {
|
|
| 541 |
+ ac.stateCV.Wait() |
|
| 406 | 542 |
if err != nil {
|
| 407 |
- return cc.state, err |
|
| 543 |
+ return ac.state, err |
|
| 408 | 544 |
} |
| 409 | 545 |
} |
| 410 |
- return cc.state, nil |
|
| 546 |
+ return ac.state, nil |
|
| 411 | 547 |
} |
| 412 | 548 |
|
| 413 |
-// NotifyReset tries to signal the underlying transport needs to be reset due to |
|
| 414 |
-// for example a name resolution change in flight. |
|
| 415 |
-func (cc *Conn) NotifyReset() {
|
|
| 416 |
- select {
|
|
| 417 |
- case cc.resetChan <- 0: |
|
| 418 |
- default: |
|
| 419 |
- } |
|
| 420 |
-} |
|
| 421 |
- |
|
| 422 |
-func (cc *Conn) resetTransport(closeTransport bool) error {
|
|
| 423 |
- var retries int |
|
| 424 |
- start := time.Now() |
|
| 425 |
- for {
|
|
| 426 |
- cc.mu.Lock() |
|
| 427 |
- cc.printf("connecting")
|
|
| 428 |
- if cc.state == Shutdown {
|
|
| 429 |
- // cc.Close() has been invoked. |
|
| 430 |
- cc.mu.Unlock() |
|
| 431 |
- return ErrClientConnClosing |
|
| 432 |
- } |
|
| 433 |
- cc.state = Connecting |
|
| 434 |
- cc.stateCV.Broadcast() |
|
| 435 |
- cc.mu.Unlock() |
|
| 436 |
- if closeTransport {
|
|
| 437 |
- cc.transport.Close() |
|
| 549 |
+func (ac *addrConn) resetTransport(closeTransport bool) error {
|
|
| 550 |
+ for retries := 0; ; retries++ {
|
|
| 551 |
+ ac.mu.Lock() |
|
| 552 |
+ ac.printf("connecting")
|
|
| 553 |
+ if ac.state == Shutdown {
|
|
| 554 |
+ // ac.tearDown(...) has been invoked. |
|
| 555 |
+ ac.mu.Unlock() |
|
| 556 |
+ return errConnClosing |
|
| 438 | 557 |
} |
| 439 |
- // Adjust timeout for the current try. |
|
| 440 |
- copts := cc.dopts.copts |
|
| 441 |
- if copts.Timeout < 0 {
|
|
| 442 |
- cc.Close() |
|
| 443 |
- return ErrClientConnTimeout |
|
| 558 |
+ if ac.down != nil {
|
|
| 559 |
+ ac.down(downErrorf(false, true, "%v", errNetworkIO)) |
|
| 560 |
+ ac.down = nil |
|
| 444 | 561 |
} |
| 445 |
- if copts.Timeout > 0 {
|
|
| 446 |
- copts.Timeout -= time.Since(start) |
|
| 447 |
- if copts.Timeout <= 0 {
|
|
| 448 |
- cc.Close() |
|
| 449 |
- return ErrClientConnTimeout |
|
| 450 |
- } |
|
| 451 |
- } |
|
| 452 |
- sleepTime := cc.dopts.bs.backoff(retries) |
|
| 453 |
- timeout := sleepTime |
|
| 454 |
- if timeout < minConnectTimeout {
|
|
| 455 |
- timeout = minConnectTimeout |
|
| 562 |
+ ac.state = Connecting |
|
| 563 |
+ ac.stateCV.Broadcast() |
|
| 564 |
+ t := ac.transport |
|
| 565 |
+ ac.mu.Unlock() |
|
| 566 |
+ if closeTransport && t != nil {
|
|
| 567 |
+ t.Close() |
|
| 456 | 568 |
} |
| 457 |
- if copts.Timeout == 0 || copts.Timeout > timeout {
|
|
| 458 |
- copts.Timeout = timeout |
|
| 569 |
+ sleepTime := ac.dopts.bs.backoff(retries) |
|
| 570 |
+ timeout := minConnectTimeout |
|
| 571 |
+ if timeout < sleepTime {
|
|
| 572 |
+ timeout = sleepTime |
|
| 459 | 573 |
} |
| 574 |
+ ctx, cancel := context.WithTimeout(ac.ctx, timeout) |
|
| 460 | 575 |
connectTime := time.Now() |
| 461 |
- addr, err := cc.dopts.picker.PickAddr() |
|
| 462 |
- var newTransport transport.ClientTransport |
|
| 463 |
- if err == nil {
|
|
| 464 |
- newTransport, err = transport.NewClientTransport(addr, &copts) |
|
| 465 |
- } |
|
| 576 |
+ newTransport, err := transport.NewClientTransport(ctx, ac.addr.Addr, ac.dopts.copts) |
|
| 466 | 577 |
if err != nil {
|
| 467 |
- cc.mu.Lock() |
|
| 468 |
- if cc.state == Shutdown {
|
|
| 469 |
- // cc.Close() has been invoked. |
|
| 470 |
- cc.mu.Unlock() |
|
| 471 |
- return ErrClientConnClosing |
|
| 472 |
- } |
|
| 473 |
- cc.errorf("transient failure: %v", err)
|
|
| 474 |
- cc.state = TransientFailure |
|
| 475 |
- cc.stateCV.Broadcast() |
|
| 476 |
- if cc.ready != nil {
|
|
| 477 |
- close(cc.ready) |
|
| 478 |
- cc.ready = nil |
|
| 578 |
+ cancel() |
|
| 579 |
+ |
|
| 580 |
+ if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() {
|
|
| 581 |
+ return err |
|
| 479 | 582 |
} |
| 480 |
- cc.mu.Unlock() |
|
| 481 |
- sleepTime -= time.Since(connectTime) |
|
| 482 |
- if sleepTime < 0 {
|
|
| 483 |
- sleepTime = 0 |
|
| 583 |
+ grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr)
|
|
| 584 |
+ ac.mu.Lock() |
|
| 585 |
+ if ac.state == Shutdown {
|
|
| 586 |
+ // ac.tearDown(...) has been invoked. |
|
| 587 |
+ ac.mu.Unlock() |
|
| 588 |
+ return errConnClosing |
|
| 484 | 589 |
} |
| 485 |
- // Fail early before falling into sleep. |
|
| 486 |
- if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) {
|
|
| 487 |
- cc.mu.Lock() |
|
| 488 |
- cc.errorf("connection timeout")
|
|
| 489 |
- cc.mu.Unlock() |
|
| 490 |
- cc.Close() |
|
| 491 |
- return ErrClientConnTimeout |
|
| 590 |
+ ac.errorf("transient failure: %v", err)
|
|
| 591 |
+ ac.state = TransientFailure |
|
| 592 |
+ ac.stateCV.Broadcast() |
|
| 593 |
+ if ac.ready != nil {
|
|
| 594 |
+ close(ac.ready) |
|
| 595 |
+ ac.ready = nil |
|
| 492 | 596 |
} |
| 597 |
+ ac.mu.Unlock() |
|
| 493 | 598 |
closeTransport = false |
| 494 |
- time.Sleep(sleepTime) |
|
| 495 |
- retries++ |
|
| 496 |
- grpclog.Printf("grpc: Conn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
|
|
| 599 |
+ select {
|
|
| 600 |
+ case <-time.After(sleepTime - time.Since(connectTime)): |
|
| 601 |
+ case <-ac.ctx.Done(): |
|
| 602 |
+ return ac.ctx.Err() |
|
| 603 |
+ } |
|
| 497 | 604 |
continue |
| 498 | 605 |
} |
| 499 |
- cc.mu.Lock() |
|
| 500 |
- cc.printf("ready")
|
|
| 501 |
- if cc.state == Shutdown {
|
|
| 502 |
- // cc.Close() has been invoked. |
|
| 503 |
- cc.mu.Unlock() |
|
| 606 |
+ ac.mu.Lock() |
|
| 607 |
+ ac.printf("ready")
|
|
| 608 |
+ if ac.state == Shutdown {
|
|
| 609 |
+ // ac.tearDown(...) has been invoked. |
|
| 610 |
+ ac.mu.Unlock() |
|
| 504 | 611 |
newTransport.Close() |
| 505 |
- return ErrClientConnClosing |
|
| 612 |
+ return errConnClosing |
|
| 506 | 613 |
} |
| 507 |
- cc.state = Ready |
|
| 508 |
- cc.stateCV.Broadcast() |
|
| 509 |
- cc.transport = newTransport |
|
| 510 |
- if cc.ready != nil {
|
|
| 511 |
- close(cc.ready) |
|
| 512 |
- cc.ready = nil |
|
| 614 |
+ ac.state = Ready |
|
| 615 |
+ ac.stateCV.Broadcast() |
|
| 616 |
+ ac.transport = newTransport |
|
| 617 |
+ if ac.ready != nil {
|
|
| 618 |
+ close(ac.ready) |
|
| 619 |
+ ac.ready = nil |
|
| 513 | 620 |
} |
| 514 |
- cc.mu.Unlock() |
|
| 621 |
+ if ac.cc.dopts.balancer != nil {
|
|
| 622 |
+ ac.down = ac.cc.dopts.balancer.Up(ac.addr) |
|
| 623 |
+ } |
|
| 624 |
+ ac.mu.Unlock() |
|
| 515 | 625 |
return nil |
| 516 | 626 |
} |
| 517 | 627 |
} |
| 518 | 628 |
|
| 519 |
-func (cc *Conn) reconnect() bool {
|
|
| 520 |
- cc.mu.Lock() |
|
| 521 |
- if cc.state == Shutdown {
|
|
| 522 |
- // cc.Close() has been invoked. |
|
| 523 |
- cc.mu.Unlock() |
|
| 524 |
- return false |
|
| 525 |
- } |
|
| 526 |
- cc.state = TransientFailure |
|
| 527 |
- cc.stateCV.Broadcast() |
|
| 528 |
- cc.mu.Unlock() |
|
| 529 |
- if err := cc.resetTransport(true); err != nil {
|
|
| 530 |
- // The ClientConn is closing. |
|
| 531 |
- cc.mu.Lock() |
|
| 532 |
- cc.printf("transport exiting: %v", err)
|
|
| 533 |
- cc.mu.Unlock() |
|
| 534 |
- grpclog.Printf("grpc: Conn.transportMonitor exits due to: %v", err)
|
|
| 535 |
- return false |
|
| 536 |
- } |
|
| 537 |
- return true |
|
| 538 |
-} |
|
| 539 |
- |
|
| 540 | 629 |
// Run in a goroutine to track the error in transport and create the |
| 541 | 630 |
// new transport if an error happens. It returns when the channel is closing. |
| 542 |
-func (cc *Conn) transportMonitor() {
|
|
| 631 |
+func (ac *addrConn) transportMonitor() {
|
|
| 543 | 632 |
for {
|
| 633 |
+ ac.mu.Lock() |
|
| 634 |
+ t := ac.transport |
|
| 635 |
+ ac.mu.Unlock() |
|
| 544 | 636 |
select {
|
| 545 |
- // shutdownChan is needed to detect the teardown when |
|
| 546 |
- // the ClientConn is idle (i.e., no RPC in flight). |
|
| 547 |
- case <-cc.shutdownChan: |
|
| 637 |
+ // This is needed to detect the teardown when |
|
| 638 |
+ // the addrConn is idle (i.e., no RPC in flight). |
|
| 639 |
+ case <-ac.ctx.Done(): |
|
| 640 |
+ select {
|
|
| 641 |
+ case <-t.Error(): |
|
| 642 |
+ t.Close() |
|
| 643 |
+ default: |
|
| 644 |
+ } |
|
| 645 |
+ return |
|
| 646 |
+ case <-t.GoAway(): |
|
| 647 |
+ // If GoAway happens without any network I/O error, ac is closed without shutting down the |
|
| 648 |
+ // underlying transport (the transport will be closed when all the pending RPCs finished or |
|
| 649 |
+ // failed.). |
|
| 650 |
+ // If GoAway and some network I/O error happen concurrently, ac and its underlying transport |
|
| 651 |
+ // are closed. |
|
| 652 |
+ // In both cases, a new ac is created. |
|
| 653 |
+ select {
|
|
| 654 |
+ case <-t.Error(): |
|
| 655 |
+ ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) |
|
| 656 |
+ default: |
|
| 657 |
+ ac.cc.resetAddrConn(ac.addr, true, errConnDrain) |
|
| 658 |
+ } |
|
| 548 | 659 |
return |
| 549 |
- case <-cc.resetChan: |
|
| 550 |
- if !cc.reconnect() {
|
|
| 660 |
+ case <-t.Error(): |
|
| 661 |
+ select {
|
|
| 662 |
+ case <-ac.ctx.Done(): |
|
| 663 |
+ t.Close() |
|
| 664 |
+ return |
|
| 665 |
+ case <-t.GoAway(): |
|
| 666 |
+ ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) |
|
| 551 | 667 |
return |
| 668 |
+ default: |
|
| 552 | 669 |
} |
| 553 |
- case <-cc.transport.Error(): |
|
| 554 |
- if !cc.reconnect() {
|
|
| 670 |
+ ac.mu.Lock() |
|
| 671 |
+ if ac.state == Shutdown {
|
|
| 672 |
+ // ac has been shutdown. |
|
| 673 |
+ ac.mu.Unlock() |
|
| 555 | 674 |
return |
| 556 | 675 |
} |
| 557 |
- // Tries to drain reset signal if there is any since it is out-dated. |
|
| 558 |
- select {
|
|
| 559 |
- case <-cc.resetChan: |
|
| 560 |
- default: |
|
| 676 |
+ ac.state = TransientFailure |
|
| 677 |
+ ac.stateCV.Broadcast() |
|
| 678 |
+ ac.mu.Unlock() |
|
| 679 |
+ if err := ac.resetTransport(true); err != nil {
|
|
| 680 |
+ ac.mu.Lock() |
|
| 681 |
+ ac.printf("transport exiting: %v", err)
|
|
| 682 |
+ ac.mu.Unlock() |
|
| 683 |
+ grpclog.Printf("grpc: addrConn.transportMonitor exits due to: %v", err)
|
|
| 684 |
+ if err != errConnClosing {
|
|
| 685 |
+ // Keep this ac in cc.conns, to get the reason it's torn down. |
|
| 686 |
+ ac.tearDown(err) |
|
| 687 |
+ } |
|
| 688 |
+ return |
|
| 561 | 689 |
} |
| 562 | 690 |
} |
| 563 | 691 |
} |
| 564 | 692 |
} |
| 565 | 693 |
|
| 566 |
-// Wait blocks until i) the new transport is up or ii) ctx is done or iii) cc is closed. |
|
| 567 |
-func (cc *Conn) Wait(ctx context.Context) (transport.ClientTransport, error) {
|
|
| 694 |
+// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or |
|
| 695 |
+// iv) transport is in TransientFailure and there's no balancer/failfast is true. |
|
| 696 |
+func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) {
|
|
| 568 | 697 |
for {
|
| 569 |
- cc.mu.Lock() |
|
| 698 |
+ ac.mu.Lock() |
|
| 570 | 699 |
switch {
|
| 571 |
- case cc.state == Shutdown: |
|
| 572 |
- cc.mu.Unlock() |
|
| 573 |
- return nil, ErrClientConnClosing |
|
| 574 |
- case cc.state == Ready: |
|
| 575 |
- ct := cc.transport |
|
| 576 |
- cc.mu.Unlock() |
|
| 577 |
- return ct, nil |
|
| 578 |
- default: |
|
| 579 |
- ready := cc.ready |
|
| 580 |
- if ready == nil {
|
|
| 581 |
- ready = make(chan struct{})
|
|
| 582 |
- cc.ready = ready |
|
| 700 |
+ case ac.state == Shutdown: |
|
| 701 |
+ if failfast || !hasBalancer {
|
|
| 702 |
+ // RPC is failfast or balancer is nil. This RPC should fail with ac.tearDownErr. |
|
| 703 |
+ err := ac.tearDownErr |
|
| 704 |
+ ac.mu.Unlock() |
|
| 705 |
+ return nil, err |
|
| 583 | 706 |
} |
| 584 |
- cc.mu.Unlock() |
|
| 585 |
- select {
|
|
| 586 |
- case <-ctx.Done(): |
|
| 587 |
- return nil, transport.ContextErr(ctx.Err()) |
|
| 588 |
- // Wait until the new transport is ready or failed. |
|
| 589 |
- case <-ready: |
|
| 707 |
+ ac.mu.Unlock() |
|
| 708 |
+ return nil, errConnClosing |
|
| 709 |
+ case ac.state == Ready: |
|
| 710 |
+ ct := ac.transport |
|
| 711 |
+ ac.mu.Unlock() |
|
| 712 |
+ return ct, nil |
|
| 713 |
+ case ac.state == TransientFailure: |
|
| 714 |
+ if failfast || hasBalancer {
|
|
| 715 |
+ ac.mu.Unlock() |
|
| 716 |
+ return nil, errConnUnavailable |
|
| 590 | 717 |
} |
| 591 | 718 |
} |
| 719 |
+ ready := ac.ready |
|
| 720 |
+ if ready == nil {
|
|
| 721 |
+ ready = make(chan struct{})
|
|
| 722 |
+ ac.ready = ready |
|
| 723 |
+ } |
|
| 724 |
+ ac.mu.Unlock() |
|
| 725 |
+ select {
|
|
| 726 |
+ case <-ctx.Done(): |
|
| 727 |
+ return nil, toRPCErr(ctx.Err()) |
|
| 728 |
+ // Wait until the new transport is ready or failed. |
|
| 729 |
+ case <-ready: |
|
| 730 |
+ } |
|
| 592 | 731 |
} |
| 593 | 732 |
} |
| 594 | 733 |
|
| 595 |
-// Close starts to tear down the Conn. Returns ErrClientConnClosing if |
|
| 596 |
-// it has been closed (mostly due to dial time-out). |
|
| 734 |
+// tearDown starts to tear down the addrConn. |
|
| 597 | 735 |
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in |
| 598 |
-// some edge cases (e.g., the caller opens and closes many ClientConn's in a |
|
| 736 |
+// some edge cases (e.g., the caller opens and closes many addrConn's in a |
|
| 599 | 737 |
// tight loop. |
| 600 |
-func (cc *Conn) Close() error {
|
|
| 601 |
- cc.mu.Lock() |
|
| 602 |
- defer cc.mu.Unlock() |
|
| 603 |
- if cc.state == Shutdown {
|
|
| 604 |
- return ErrClientConnClosing |
|
| 605 |
- } |
|
| 606 |
- cc.state = Shutdown |
|
| 607 |
- cc.stateCV.Broadcast() |
|
| 608 |
- if cc.events != nil {
|
|
| 609 |
- cc.events.Finish() |
|
| 610 |
- cc.events = nil |
|
| 611 |
- } |
|
| 612 |
- if cc.ready != nil {
|
|
| 613 |
- close(cc.ready) |
|
| 614 |
- cc.ready = nil |
|
| 615 |
- } |
|
| 616 |
- if cc.transport != nil {
|
|
| 617 |
- cc.transport.Close() |
|
| 618 |
- } |
|
| 619 |
- if cc.shutdownChan != nil {
|
|
| 620 |
- close(cc.shutdownChan) |
|
| 621 |
- } |
|
| 622 |
- return nil |
|
| 738 |
+// tearDown doesn't remove ac from ac.cc.conns. |
|
| 739 |
+func (ac *addrConn) tearDown(err error) {
|
|
| 740 |
+ ac.cancel() |
|
| 741 |
+ |
|
| 742 |
+ ac.mu.Lock() |
|
| 743 |
+ defer ac.mu.Unlock() |
|
| 744 |
+ if ac.down != nil {
|
|
| 745 |
+ ac.down(downErrorf(false, false, "%v", err)) |
|
| 746 |
+ ac.down = nil |
|
| 747 |
+ } |
|
| 748 |
+ if err == errConnDrain && ac.transport != nil {
|
|
| 749 |
+ // GracefulClose(...) may be executed multiple times when |
|
| 750 |
+ // i) receiving multiple GoAway frames from the server; or |
|
| 751 |
+ // ii) there are concurrent name resolver/Balancer triggered |
|
| 752 |
+ // address removal and GoAway. |
|
| 753 |
+ ac.transport.GracefulClose() |
|
| 754 |
+ } |
|
| 755 |
+ if ac.state == Shutdown {
|
|
| 756 |
+ return |
|
| 757 |
+ } |
|
| 758 |
+ ac.state = Shutdown |
|
| 759 |
+ ac.tearDownErr = err |
|
| 760 |
+ ac.stateCV.Broadcast() |
|
| 761 |
+ if ac.events != nil {
|
|
| 762 |
+ ac.events.Finish() |
|
| 763 |
+ ac.events = nil |
|
| 764 |
+ } |
|
| 765 |
+ if ac.ready != nil {
|
|
| 766 |
+ close(ac.ready) |
|
| 767 |
+ ac.ready = nil |
|
| 768 |
+ } |
|
| 769 |
+ if ac.transport != nil && err != errConnDrain {
|
|
| 770 |
+ ac.transport.Close() |
|
| 771 |
+ } |
|
| 772 |
+ return |
|
| 623 | 773 |
} |
| ... | ... |
@@ -44,7 +44,6 @@ import ( |
| 44 | 44 |
"io/ioutil" |
| 45 | 45 |
"net" |
| 46 | 46 |
"strings" |
| 47 |
- "time" |
|
| 48 | 47 |
|
| 49 | 48 |
"golang.org/x/net/context" |
| 50 | 49 |
) |
| ... | ... |
@@ -54,9 +53,9 @@ var ( |
| 54 | 54 |
alpnProtoStr = []string{"h2"}
|
| 55 | 55 |
) |
| 56 | 56 |
|
| 57 |
-// Credentials defines the common interface all supported credentials must |
|
| 58 |
-// implement. |
|
| 59 |
-type Credentials interface {
|
|
| 57 |
+// PerRPCCredentials defines the common interface for the credentials which need to |
|
| 58 |
+// attach security information to every RPC (e.g., oauth2). |
|
| 59 |
+type PerRPCCredentials interface {
|
|
| 60 | 60 |
// GetRequestMetadata gets the current request metadata, refreshing |
| 61 | 61 |
// tokens if required. This should be called by the transport layer on |
| 62 | 62 |
// each request, and the data should be populated in headers or other |
| ... | ... |
@@ -66,7 +65,7 @@ type Credentials interface {
|
| 66 | 66 |
// TODO(zhaoq): Define the set of the qualified keys instead of leaving |
| 67 | 67 |
// it as an arbitrary string. |
| 68 | 68 |
GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) |
| 69 |
- // RequireTransportSecurity indicates whether the credentails requires |
|
| 69 |
+ // RequireTransportSecurity indicates whether the credentials requires |
|
| 70 | 70 |
// transport security. |
| 71 | 71 |
RequireTransportSecurity() bool |
| 72 | 72 |
} |
| ... | ... |
@@ -87,20 +86,20 @@ type AuthInfo interface {
|
| 87 | 87 |
AuthType() string |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 |
-// TransportAuthenticator defines the common interface for all the live gRPC wire |
|
| 90 |
+// TransportCredentials defines the common interface for all the live gRPC wire |
|
| 91 | 91 |
// protocols and supported transport security protocols (e.g., TLS, SSL). |
| 92 |
-type TransportAuthenticator interface {
|
|
| 92 |
+type TransportCredentials interface {
|
|
| 93 | 93 |
// ClientHandshake does the authentication handshake specified by the corresponding |
| 94 | 94 |
// authentication protocol on rawConn for clients. It returns the authenticated |
| 95 | 95 |
// connection and the corresponding auth information about the connection. |
| 96 |
- ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error) |
|
| 96 |
+ // Implementations must use the provided context to implement timely cancellation. |
|
| 97 |
+ ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) |
|
| 97 | 98 |
// ServerHandshake does the authentication handshake for servers. It returns |
| 98 | 99 |
// the authenticated connection and the corresponding auth information about |
| 99 | 100 |
// the connection. |
| 100 |
- ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) |
|
| 101 |
- // Info provides the ProtocolInfo of this TransportAuthenticator. |
|
| 101 |
+ ServerHandshake(net.Conn) (net.Conn, AuthInfo, error) |
|
| 102 |
+ // Info provides the ProtocolInfo of this TransportCredentials. |
|
| 102 | 103 |
Info() ProtocolInfo |
| 103 |
- Credentials |
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 | 106 |
// TLSInfo contains the auth information for a TLS authenticated connection. |
| ... | ... |
@@ -109,6 +108,7 @@ type TLSInfo struct {
|
| 109 | 109 |
State tls.ConnectionState |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 |
+// AuthType returns the type of TLSInfo as a string. |
|
| 112 | 113 |
func (t TLSInfo) AuthType() string {
|
| 113 | 114 |
return "tls" |
| 114 | 115 |
} |
| ... | ... |
@@ -116,7 +116,7 @@ func (t TLSInfo) AuthType() string {
|
| 116 | 116 |
// tlsCreds is the credentials required for authenticating a connection using TLS. |
| 117 | 117 |
type tlsCreds struct {
|
| 118 | 118 |
// TLS configuration |
| 119 |
- config tls.Config |
|
| 119 |
+ config *tls.Config |
|
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
func (c tlsCreds) Info() ProtocolInfo {
|
| ... | ... |
@@ -136,40 +136,28 @@ func (c *tlsCreds) RequireTransportSecurity() bool {
|
| 136 | 136 |
return true |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 |
-type timeoutError struct{}
|
|
| 140 |
- |
|
| 141 |
-func (timeoutError) Error() string { return "credentials: Dial timed out" }
|
|
| 142 |
-func (timeoutError) Timeout() bool { return true }
|
|
| 143 |
-func (timeoutError) Temporary() bool { return true }
|
|
| 144 |
- |
|
| 145 |
-func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) {
|
|
| 146 |
- // borrow some code from tls.DialWithDialer |
|
| 147 |
- var errChannel chan error |
|
| 148 |
- if timeout != 0 {
|
|
| 149 |
- errChannel = make(chan error, 2) |
|
| 150 |
- time.AfterFunc(timeout, func() {
|
|
| 151 |
- errChannel <- timeoutError{}
|
|
| 152 |
- }) |
|
| 153 |
- } |
|
| 154 |
- if c.config.ServerName == "" {
|
|
| 139 |
+func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
|
|
| 140 |
+ // use local cfg to avoid clobbering ServerName if using multiple endpoints |
|
| 141 |
+ cfg := cloneTLSConfig(c.config) |
|
| 142 |
+ if cfg.ServerName == "" {
|
|
| 155 | 143 |
colonPos := strings.LastIndex(addr, ":") |
| 156 | 144 |
if colonPos == -1 {
|
| 157 | 145 |
colonPos = len(addr) |
| 158 | 146 |
} |
| 159 |
- c.config.ServerName = addr[:colonPos] |
|
| 160 |
- } |
|
| 161 |
- conn := tls.Client(rawConn, &c.config) |
|
| 162 |
- if timeout == 0 {
|
|
| 163 |
- err = conn.Handshake() |
|
| 164 |
- } else {
|
|
| 165 |
- go func() {
|
|
| 166 |
- errChannel <- conn.Handshake() |
|
| 167 |
- }() |
|
| 168 |
- err = <-errChannel |
|
| 147 |
+ cfg.ServerName = addr[:colonPos] |
|
| 169 | 148 |
} |
| 170 |
- if err != nil {
|
|
| 171 |
- rawConn.Close() |
|
| 172 |
- return nil, nil, err |
|
| 149 |
+ conn := tls.Client(rawConn, cfg) |
|
| 150 |
+ errChannel := make(chan error, 1) |
|
| 151 |
+ go func() {
|
|
| 152 |
+ errChannel <- conn.Handshake() |
|
| 153 |
+ }() |
|
| 154 |
+ select {
|
|
| 155 |
+ case err := <-errChannel: |
|
| 156 |
+ if err != nil {
|
|
| 157 |
+ return nil, nil, err |
|
| 158 |
+ } |
|
| 159 |
+ case <-ctx.Done(): |
|
| 160 |
+ return nil, nil, ctx.Err() |
|
| 173 | 161 |
} |
| 174 | 162 |
// TODO(zhaoq): Omit the auth info for client now. It is more for |
| 175 | 163 |
// information than anything else. |
| ... | ... |
@@ -177,28 +165,27 @@ func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.D |
| 177 | 177 |
} |
| 178 | 178 |
|
| 179 | 179 |
func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
|
| 180 |
- conn := tls.Server(rawConn, &c.config) |
|
| 180 |
+ conn := tls.Server(rawConn, c.config) |
|
| 181 | 181 |
if err := conn.Handshake(); err != nil {
|
| 182 |
- rawConn.Close() |
|
| 183 | 182 |
return nil, nil, err |
| 184 | 183 |
} |
| 185 | 184 |
return conn, TLSInfo{conn.ConnectionState()}, nil
|
| 186 | 185 |
} |
| 187 | 186 |
|
| 188 |
-// NewTLS uses c to construct a TransportAuthenticator based on TLS. |
|
| 189 |
-func NewTLS(c *tls.Config) TransportAuthenticator {
|
|
| 190 |
- tc := &tlsCreds{*c}
|
|
| 187 |
+// NewTLS uses c to construct a TransportCredentials based on TLS. |
|
| 188 |
+func NewTLS(c *tls.Config) TransportCredentials {
|
|
| 189 |
+ tc := &tlsCreds{cloneTLSConfig(c)}
|
|
| 191 | 190 |
tc.config.NextProtos = alpnProtoStr |
| 192 | 191 |
return tc |
| 193 | 192 |
} |
| 194 | 193 |
|
| 195 | 194 |
// NewClientTLSFromCert constructs a TLS from the input certificate for client. |
| 196 |
-func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportAuthenticator {
|
|
| 195 |
+func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportCredentials {
|
|
| 197 | 196 |
return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp})
|
| 198 | 197 |
} |
| 199 | 198 |
|
| 200 | 199 |
// NewClientTLSFromFile constructs a TLS from the input certificate file for client. |
| 201 |
-func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, error) {
|
|
| 200 |
+func NewClientTLSFromFile(certFile, serverName string) (TransportCredentials, error) {
|
|
| 202 | 201 |
b, err := ioutil.ReadFile(certFile) |
| 203 | 202 |
if err != nil {
|
| 204 | 203 |
return nil, err |
| ... | ... |
@@ -211,13 +198,13 @@ func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, |
| 211 | 211 |
} |
| 212 | 212 |
|
| 213 | 213 |
// NewServerTLSFromCert constructs a TLS from the input certificate for server. |
| 214 |
-func NewServerTLSFromCert(cert *tls.Certificate) TransportAuthenticator {
|
|
| 214 |
+func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
|
|
| 215 | 215 |
return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
|
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 | 218 |
// NewServerTLSFromFile constructs a TLS from the input certificate file and key |
| 219 | 219 |
// file for server. |
| 220 |
-func NewServerTLSFromFile(certFile, keyFile string) (TransportAuthenticator, error) {
|
|
| 220 |
+func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
|
|
| 221 | 221 |
cert, err := tls.LoadX509KeyPair(certFile, keyFile) |
| 222 | 222 |
if err != nil {
|
| 223 | 223 |
return nil, err |
| 224 | 224 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,76 @@ |
| 0 |
+// +build go1.7 |
|
| 1 |
+ |
|
| 2 |
+/* |
|
| 3 |
+ * |
|
| 4 |
+ * Copyright 2016, Google Inc. |
|
| 5 |
+ * All rights reserved. |
|
| 6 |
+ * |
|
| 7 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 8 |
+ * modification, are permitted provided that the following conditions are |
|
| 9 |
+ * met: |
|
| 10 |
+ * |
|
| 11 |
+ * * Redistributions of source code must retain the above copyright |
|
| 12 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 13 |
+ * * Redistributions in binary form must reproduce the above |
|
| 14 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 15 |
+ * in the documentation and/or other materials provided with the |
|
| 16 |
+ * distribution. |
|
| 17 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 18 |
+ * contributors may be used to endorse or promote products derived from |
|
| 19 |
+ * this software without specific prior written permission. |
|
| 20 |
+ * |
|
| 21 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 22 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 23 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 24 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 25 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 26 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 27 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 28 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 29 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 30 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 31 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 32 |
+ * |
|
| 33 |
+ */ |
|
| 34 |
+ |
|
| 35 |
+package credentials |
|
| 36 |
+ |
|
| 37 |
+import ( |
|
| 38 |
+ "crypto/tls" |
|
| 39 |
+) |
|
| 40 |
+ |
|
| 41 |
+// cloneTLSConfig returns a shallow clone of the exported |
|
| 42 |
+// fields of cfg, ignoring the unexported sync.Once, which |
|
| 43 |
+// contains a mutex and must not be copied. |
|
| 44 |
+// |
|
| 45 |
+// If cfg is nil, a new zero tls.Config is returned. |
|
| 46 |
+// |
|
| 47 |
+// TODO replace this function with official clone function. |
|
| 48 |
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
|
| 49 |
+ if cfg == nil {
|
|
| 50 |
+ return &tls.Config{}
|
|
| 51 |
+ } |
|
| 52 |
+ return &tls.Config{
|
|
| 53 |
+ Rand: cfg.Rand, |
|
| 54 |
+ Time: cfg.Time, |
|
| 55 |
+ Certificates: cfg.Certificates, |
|
| 56 |
+ NameToCertificate: cfg.NameToCertificate, |
|
| 57 |
+ GetCertificate: cfg.GetCertificate, |
|
| 58 |
+ RootCAs: cfg.RootCAs, |
|
| 59 |
+ NextProtos: cfg.NextProtos, |
|
| 60 |
+ ServerName: cfg.ServerName, |
|
| 61 |
+ ClientAuth: cfg.ClientAuth, |
|
| 62 |
+ ClientCAs: cfg.ClientCAs, |
|
| 63 |
+ InsecureSkipVerify: cfg.InsecureSkipVerify, |
|
| 64 |
+ CipherSuites: cfg.CipherSuites, |
|
| 65 |
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites, |
|
| 66 |
+ SessionTicketsDisabled: cfg.SessionTicketsDisabled, |
|
| 67 |
+ SessionTicketKey: cfg.SessionTicketKey, |
|
| 68 |
+ ClientSessionCache: cfg.ClientSessionCache, |
|
| 69 |
+ MinVersion: cfg.MinVersion, |
|
| 70 |
+ MaxVersion: cfg.MaxVersion, |
|
| 71 |
+ CurvePreferences: cfg.CurvePreferences, |
|
| 72 |
+ DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, |
|
| 73 |
+ Renegotiation: cfg.Renegotiation, |
|
| 74 |
+ } |
|
| 75 |
+} |
| 0 | 76 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,74 @@ |
| 0 |
+// +build !go1.7 |
|
| 1 |
+ |
|
| 2 |
+/* |
|
| 3 |
+ * |
|
| 4 |
+ * Copyright 2016, Google Inc. |
|
| 5 |
+ * All rights reserved. |
|
| 6 |
+ * |
|
| 7 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 8 |
+ * modification, are permitted provided that the following conditions are |
|
| 9 |
+ * met: |
|
| 10 |
+ * |
|
| 11 |
+ * * Redistributions of source code must retain the above copyright |
|
| 12 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 13 |
+ * * Redistributions in binary form must reproduce the above |
|
| 14 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 15 |
+ * in the documentation and/or other materials provided with the |
|
| 16 |
+ * distribution. |
|
| 17 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 18 |
+ * contributors may be used to endorse or promote products derived from |
|
| 19 |
+ * this software without specific prior written permission. |
|
| 20 |
+ * |
|
| 21 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 22 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 23 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 24 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 25 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 26 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 27 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 28 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 29 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 30 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 31 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 32 |
+ * |
|
| 33 |
+ */ |
|
| 34 |
+ |
|
| 35 |
+package credentials |
|
| 36 |
+ |
|
| 37 |
+import ( |
|
| 38 |
+ "crypto/tls" |
|
| 39 |
+) |
|
| 40 |
+ |
|
| 41 |
+// cloneTLSConfig returns a shallow clone of the exported |
|
| 42 |
+// fields of cfg, ignoring the unexported sync.Once, which |
|
| 43 |
+// contains a mutex and must not be copied. |
|
| 44 |
+// |
|
| 45 |
+// If cfg is nil, a new zero tls.Config is returned. |
|
| 46 |
+// |
|
| 47 |
+// TODO replace this function with official clone function. |
|
| 48 |
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
|
| 49 |
+ if cfg == nil {
|
|
| 50 |
+ return &tls.Config{}
|
|
| 51 |
+ } |
|
| 52 |
+ return &tls.Config{
|
|
| 53 |
+ Rand: cfg.Rand, |
|
| 54 |
+ Time: cfg.Time, |
|
| 55 |
+ Certificates: cfg.Certificates, |
|
| 56 |
+ NameToCertificate: cfg.NameToCertificate, |
|
| 57 |
+ GetCertificate: cfg.GetCertificate, |
|
| 58 |
+ RootCAs: cfg.RootCAs, |
|
| 59 |
+ NextProtos: cfg.NextProtos, |
|
| 60 |
+ ServerName: cfg.ServerName, |
|
| 61 |
+ ClientAuth: cfg.ClientAuth, |
|
| 62 |
+ ClientCAs: cfg.ClientCAs, |
|
| 63 |
+ InsecureSkipVerify: cfg.InsecureSkipVerify, |
|
| 64 |
+ CipherSuites: cfg.CipherSuites, |
|
| 65 |
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites, |
|
| 66 |
+ SessionTicketsDisabled: cfg.SessionTicketsDisabled, |
|
| 67 |
+ SessionTicketKey: cfg.SessionTicketKey, |
|
| 68 |
+ ClientSessionCache: cfg.ClientSessionCache, |
|
| 69 |
+ MinVersion: cfg.MinVersion, |
|
| 70 |
+ MaxVersion: cfg.MaxVersion, |
|
| 71 |
+ CurvePreferences: cfg.CurvePreferences, |
|
| 72 |
+ } |
|
| 73 |
+} |
| ... | ... |
@@ -45,7 +45,7 @@ import ( |
| 45 | 45 |
"google.golang.org/grpc/credentials" |
| 46 | 46 |
) |
| 47 | 47 |
|
| 48 |
-// TokenSource supplies credentials from an oauth2.TokenSource. |
|
| 48 |
+// TokenSource supplies PerRPCCredentials from an oauth2.TokenSource. |
|
| 49 | 49 |
type TokenSource struct {
|
| 50 | 50 |
oauth2.TokenSource |
| 51 | 51 |
} |
| ... | ... |
@@ -57,10 +57,11 @@ func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (ma |
| 57 | 57 |
return nil, err |
| 58 | 58 |
} |
| 59 | 59 |
return map[string]string{
|
| 60 |
- "authorization": token.TokenType + " " + token.AccessToken, |
|
| 60 |
+ "authorization": token.Type() + " " + token.AccessToken, |
|
| 61 | 61 |
}, nil |
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 |
+// RequireTransportSecurity indicates whether the credentails requires transport security. |
|
| 64 | 65 |
func (ts TokenSource) RequireTransportSecurity() bool {
|
| 65 | 66 |
return true |
| 66 | 67 |
} |
| ... | ... |
@@ -69,7 +70,8 @@ type jwtAccess struct {
|
| 69 | 69 |
jsonKey []byte |
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 |
-func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, error) {
|
|
| 72 |
+// NewJWTAccessFromFile creates PerRPCCredentials from the given keyFile. |
|
| 73 |
+func NewJWTAccessFromFile(keyFile string) (credentials.PerRPCCredentials, error) {
|
|
| 73 | 74 |
jsonKey, err := ioutil.ReadFile(keyFile) |
| 74 | 75 |
if err != nil {
|
| 75 | 76 |
return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
|
| ... | ... |
@@ -77,7 +79,8 @@ func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, error) {
|
| 77 | 77 |
return NewJWTAccessFromKey(jsonKey) |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 |
-func NewJWTAccessFromKey(jsonKey []byte) (credentials.Credentials, error) {
|
|
| 80 |
+// NewJWTAccessFromKey creates PerRPCCredentials from the given jsonKey. |
|
| 81 |
+func NewJWTAccessFromKey(jsonKey []byte) (credentials.PerRPCCredentials, error) {
|
|
| 81 | 82 |
return jwtAccess{jsonKey}, nil
|
| 82 | 83 |
} |
| 83 | 84 |
|
| ... | ... |
@@ -99,13 +102,13 @@ func (j jwtAccess) RequireTransportSecurity() bool {
|
| 99 | 99 |
return true |
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 |
-// oauthAccess supplies credentials from a given token. |
|
| 102 |
+// oauthAccess supplies PerRPCCredentials from a given token. |
|
| 103 | 103 |
type oauthAccess struct {
|
| 104 | 104 |
token oauth2.Token |
| 105 | 105 |
} |
| 106 | 106 |
|
| 107 |
-// NewOauthAccess constructs the credentials using a given token. |
|
| 108 |
-func NewOauthAccess(token *oauth2.Token) credentials.Credentials {
|
|
| 107 |
+// NewOauthAccess constructs the PerRPCCredentials using a given token. |
|
| 108 |
+func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials {
|
|
| 109 | 109 |
return oauthAccess{token: *token}
|
| 110 | 110 |
} |
| 111 | 111 |
|
| ... | ... |
@@ -119,15 +122,15 @@ func (oa oauthAccess) RequireTransportSecurity() bool {
|
| 119 | 119 |
return true |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 |
-// NewComputeEngine constructs the credentials that fetches access tokens from |
|
| 122 |
+// NewComputeEngine constructs the PerRPCCredentials that fetches access tokens from |
|
| 123 | 123 |
// Google Compute Engine (GCE)'s metadata server. It is only valid to use this |
| 124 | 124 |
// if your program is running on a GCE instance. |
| 125 | 125 |
// TODO(dsymonds): Deprecate and remove this. |
| 126 |
-func NewComputeEngine() credentials.Credentials {
|
|
| 126 |
+func NewComputeEngine() credentials.PerRPCCredentials {
|
|
| 127 | 127 |
return TokenSource{google.ComputeTokenSource("")}
|
| 128 | 128 |
} |
| 129 | 129 |
|
| 130 |
-// serviceAccount represents credentials via JWT signing key. |
|
| 130 |
+// serviceAccount represents PerRPCCredentials via JWT signing key. |
|
| 131 | 131 |
type serviceAccount struct {
|
| 132 | 132 |
config *jwt.Config |
| 133 | 133 |
} |
| ... | ... |
@@ -146,9 +149,9 @@ func (s serviceAccount) RequireTransportSecurity() bool {
|
| 146 | 146 |
return true |
| 147 | 147 |
} |
| 148 | 148 |
|
| 149 |
-// NewServiceAccountFromKey constructs the credentials using the JSON key slice |
|
| 149 |
+// NewServiceAccountFromKey constructs the PerRPCCredentials using the JSON key slice |
|
| 150 | 150 |
// from a Google Developers service account. |
| 151 |
-func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Credentials, error) {
|
|
| 151 |
+func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) {
|
|
| 152 | 152 |
config, err := google.JWTConfigFromJSON(jsonKey, scope...) |
| 153 | 153 |
if err != nil {
|
| 154 | 154 |
return nil, err |
| ... | ... |
@@ -156,9 +159,9 @@ func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Cred |
| 156 | 156 |
return serviceAccount{config: config}, nil
|
| 157 | 157 |
} |
| 158 | 158 |
|
| 159 |
-// NewServiceAccountFromFile constructs the credentials using the JSON key file |
|
| 159 |
+// NewServiceAccountFromFile constructs the PerRPCCredentials using the JSON key file |
|
| 160 | 160 |
// of a Google Developers service account. |
| 161 |
-func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Credentials, error) {
|
|
| 161 |
+func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) {
|
|
| 162 | 162 |
jsonKey, err := ioutil.ReadFile(keyFile) |
| 163 | 163 |
if err != nil {
|
| 164 | 164 |
return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
|
| ... | ... |
@@ -168,7 +171,7 @@ func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Cre |
| 168 | 168 |
|
| 169 | 169 |
// NewApplicationDefault returns "Application Default Credentials". For more |
| 170 | 170 |
// detail, see https://developers.google.com/accounts/docs/application-default-credentials. |
| 171 |
-func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.Credentials, error) {
|
|
| 171 |
+func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.PerRPCCredentials, error) {
|
|
| 172 | 172 |
t, err := google.DefaultTokenSource(ctx, scope...) |
| 173 | 173 |
if err != nil {
|
| 174 | 174 |
return nil, err |
| ... | ... |
@@ -1,12 +1,12 @@ |
| 1 | 1 |
// Code generated by protoc-gen-go. |
| 2 |
-// source: health/grpc_health_v1/health.proto |
|
| 2 |
+// source: health.proto |
|
| 3 | 3 |
// DO NOT EDIT! |
| 4 | 4 |
|
| 5 | 5 |
/* |
| 6 | 6 |
Package grpc_health_v1 is a generated protocol buffer package. |
| 7 | 7 |
|
| 8 | 8 |
It is generated from these files: |
| 9 |
- health/grpc_health_v1/health.proto |
|
| 9 |
+ health.proto |
|
| 10 | 10 |
|
| 11 | 11 |
It has these top-level messages: |
| 12 | 12 |
HealthCheckRequest |
| ... | ... |
@@ -30,7 +30,9 @@ var _ = math.Inf |
| 30 | 30 |
|
| 31 | 31 |
// This is a compile-time assertion to ensure that this generated file |
| 32 | 32 |
// is compatible with the proto package it is being compiled against. |
| 33 |
-const _ = proto.ProtoPackageIsVersion1 |
|
| 33 |
+// A compilation error at this line likely means your copy of the |
|
| 34 |
+// proto package needs to be updated. |
|
| 35 |
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package |
|
| 34 | 36 |
|
| 35 | 37 |
type HealthCheckResponse_ServingStatus int32 |
| 36 | 38 |
|
| ... | ... |
@@ -88,7 +90,7 @@ var _ grpc.ClientConn |
| 88 | 88 |
|
| 89 | 89 |
// This is a compile-time assertion to ensure that this generated file |
| 90 | 90 |
// is compatible with the grpc package it is being compiled against. |
| 91 |
-const _ = grpc.SupportPackageIsVersion2 |
|
| 91 |
+const _ = grpc.SupportPackageIsVersion3 |
|
| 92 | 92 |
|
| 93 | 93 |
// Client API for Health service |
| 94 | 94 |
|
| ... | ... |
@@ -150,23 +152,25 @@ var _Health_serviceDesc = grpc.ServiceDesc{
|
| 150 | 150 |
Handler: _Health_Check_Handler, |
| 151 | 151 |
}, |
| 152 | 152 |
}, |
| 153 |
- Streams: []grpc.StreamDesc{},
|
|
| 153 |
+ Streams: []grpc.StreamDesc{},
|
|
| 154 |
+ Metadata: fileDescriptor0, |
|
| 154 | 155 |
} |
| 155 | 156 |
|
| 157 |
+func init() { proto.RegisterFile("health.proto", fileDescriptor0) }
|
|
| 158 |
+ |
|
| 156 | 159 |
var fileDescriptor0 = []byte{
|
| 157 |
- // 209 bytes of a gzipped FileDescriptorProto |
|
| 158 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0xca, 0x48, 0x4d, 0xcc, |
|
| 159 |
- 0x29, 0xc9, 0xd0, 0x4f, 0x2f, 0x2a, 0x48, 0x8e, 0x87, 0xb0, 0xe3, 0xcb, 0x0c, 0xf5, 0x21, 0x2c, |
|
| 160 |
- 0xbd, 0x82, 0xa2, 0xfc, 0x92, 0x7c, 0x21, 0x3e, 0x90, 0xa4, 0x1e, 0x54, 0xa8, 0xcc, 0x50, 0x49, |
|
| 161 |
- 0x95, 0x4b, 0xc8, 0x03, 0xcc, 0x71, 0xce, 0x48, 0x4d, 0xce, 0x0e, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, |
|
| 162 |
- 0x2e, 0x11, 0xe2, 0xe7, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x95, 0x60, 0x54, 0x60, |
|
| 163 |
- 0xd4, 0xe0, 0x54, 0x9a, 0xc2, 0xc8, 0x25, 0x8c, 0xa2, 0xae, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, |
|
| 164 |
- 0xc8, 0x91, 0x8b, 0xad, 0xb8, 0x24, 0xb1, 0xa4, 0xb4, 0x18, 0xac, 0x8e, 0xcf, 0xc8, 0x50, 0x0f, |
|
| 165 |
- 0xd5, 0x7c, 0x3d, 0x2c, 0x9a, 0xf4, 0x82, 0x41, 0x46, 0xe7, 0xa5, 0x07, 0x83, 0x35, 0x2a, 0x59, |
|
| 166 |
- 0x71, 0xf1, 0xa2, 0x08, 0x08, 0x71, 0x73, 0xb1, 0x87, 0xfa, 0x79, 0xfb, 0xf9, 0x87, 0xfb, 0x09, |
|
| 167 |
- 0x30, 0x80, 0x38, 0xc1, 0xae, 0x41, 0x61, 0x9e, 0x7e, 0xee, 0x02, 0x8c, 0x40, 0x67, 0x71, 0xfb, |
|
| 168 |
- 0xf9, 0x87, 0xc4, 0xc3, 0x04, 0x98, 0x8c, 0xa2, 0xb8, 0xd8, 0x20, 0x16, 0x08, 0x05, 0x70, 0xb1, |
|
| 169 |
- 0x82, 0x2d, 0x11, 0x52, 0xc2, 0xeb, 0x02, 0xb0, 0xf7, 0xa4, 0x94, 0x89, 0x70, 0x65, 0x12, 0x1b, |
|
| 170 |
- 0x38, 0xc0, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xf7, 0x2e, 0x1f, 0x56, 0x01, 0x00, |
|
| 171 |
- 0x00, |
|
| 160 |
+ // 204 bytes of a gzipped FileDescriptorProto |
|
| 161 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x48, 0x4d, 0xcc, |
|
| 162 |
+ 0x29, 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x83, |
|
| 163 |
+ 0x0a, 0x95, 0x19, 0x2a, 0xe9, 0x71, 0x09, 0x79, 0x80, 0x39, 0xce, 0x19, 0xa9, 0xc9, 0xd9, 0x41, |
|
| 164 |
+ 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0x45, 0x65, 0x99, 0xc9, |
|
| 165 |
+ 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0xd2, 0x1c, 0x46, 0x2e, 0x61, 0x14, |
|
| 166 |
+ 0x0d, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x9e, 0x5c, 0x6c, 0xc5, 0x25, 0x89, 0x25, 0xa5, |
|
| 167 |
+ 0xc5, 0x60, 0x0d, 0x7c, 0x46, 0x86, 0x7a, 0xa8, 0x16, 0xe9, 0x61, 0xd1, 0xa4, 0x17, 0x0c, 0x32, |
|
| 168 |
+ 0x34, 0x2f, 0x3d, 0x18, 0xac, 0x31, 0x08, 0x6a, 0x80, 0x92, 0x15, 0x17, 0x2f, 0x8a, 0x84, 0x10, |
|
| 169 |
+ 0x37, 0x17, 0x7b, 0xa8, 0x9f, 0xb7, 0x9f, 0x7f, 0xb8, 0x9f, 0x00, 0x03, 0x88, 0x13, 0xec, 0x1a, |
|
| 170 |
+ 0x14, 0xe6, 0xe9, 0xe7, 0x2e, 0xc0, 0x28, 0xc4, 0xcf, 0xc5, 0xed, 0xe7, 0x1f, 0x12, 0x0f, 0x13, |
|
| 171 |
+ 0x60, 0x32, 0x8a, 0xe2, 0x62, 0x83, 0x58, 0x24, 0x14, 0xc0, 0xc5, 0x0a, 0xb6, 0x4c, 0x48, 0x09, |
|
| 172 |
+ 0xaf, 0x4b, 0xc0, 0xfe, 0x95, 0x52, 0x26, 0xc2, 0xb5, 0x49, 0x6c, 0xe0, 0x10, 0x34, 0x06, 0x04, |
|
| 173 |
+ 0x00, 0x00, 0xff, 0xff, 0xac, 0x56, 0x2a, 0xcb, 0x51, 0x01, 0x00, 0x00, |
|
| 172 | 174 |
} |
| ... | ... |
@@ -60,15 +60,21 @@ func encodeKeyValue(k, v string) (string, string) {
|
| 60 | 60 |
|
| 61 | 61 |
// DecodeKeyValue returns the original key and value corresponding to the |
| 62 | 62 |
// encoded data in k, v. |
| 63 |
+// If k is a binary header and v contains comma, v is split on comma before decoded, |
|
| 64 |
+// and the decoded v will be joined with comma before returned. |
|
| 63 | 65 |
func DecodeKeyValue(k, v string) (string, string, error) {
|
| 64 | 66 |
if !strings.HasSuffix(k, binHdrSuffix) {
|
| 65 | 67 |
return k, v, nil |
| 66 | 68 |
} |
| 67 |
- val, err := base64.StdEncoding.DecodeString(v) |
|
| 68 |
- if err != nil {
|
|
| 69 |
- return "", "", err |
|
| 69 |
+ vvs := strings.Split(v, ",") |
|
| 70 |
+ for i, vv := range vvs {
|
|
| 71 |
+ val, err := base64.StdEncoding.DecodeString(vv) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return "", "", err |
|
| 74 |
+ } |
|
| 75 |
+ vvs[i] = string(val) |
|
| 70 | 76 |
} |
| 71 |
- return k, string(val), nil |
|
| 77 |
+ return k, strings.Join(vvs, ","), nil |
|
| 72 | 78 |
} |
| 73 | 79 |
|
| 74 | 80 |
// MD is a mapping from metadata keys to values. Users should use the following |
| ... | ... |
@@ -66,7 +66,8 @@ type Resolver interface {
|
| 66 | 66 |
// Watcher watches for the updates on the specified target. |
| 67 | 67 |
type Watcher interface {
|
| 68 | 68 |
// Next blocks until an update or error happens. It may return one or more |
| 69 |
- // updates. The first call should get the full set of the results. |
|
| 69 |
+ // updates. The first call should get the full set of the results. It should |
|
| 70 |
+ // return an error if and only if Watcher cannot recover. |
|
| 70 | 71 |
Next() ([]*Update, error) |
| 71 | 72 |
// Close closes the Watcher. |
| 72 | 73 |
Close() |
| 73 | 74 |
deleted file mode 100644 |
| ... | ... |
@@ -1,243 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
- * |
|
| 3 |
- * Copyright 2014, Google Inc. |
|
| 4 |
- * All rights reserved. |
|
| 5 |
- * |
|
| 6 |
- * Redistribution and use in source and binary forms, with or without |
|
| 7 |
- * modification, are permitted provided that the following conditions are |
|
| 8 |
- * met: |
|
| 9 |
- * |
|
| 10 |
- * * Redistributions of source code must retain the above copyright |
|
| 11 |
- * notice, this list of conditions and the following disclaimer. |
|
| 12 |
- * * Redistributions in binary form must reproduce the above |
|
| 13 |
- * copyright notice, this list of conditions and the following disclaimer |
|
| 14 |
- * in the documentation and/or other materials provided with the |
|
| 15 |
- * distribution. |
|
| 16 |
- * * Neither the name of Google Inc. nor the names of its |
|
| 17 |
- * contributors may be used to endorse or promote products derived from |
|
| 18 |
- * this software without specific prior written permission. |
|
| 19 |
- * |
|
| 20 |
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 21 |
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 22 |
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 23 |
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 24 |
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 25 |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 26 |
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 27 |
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 28 |
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 29 |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 30 |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 31 |
- * |
|
| 32 |
- */ |
|
| 33 |
- |
|
| 34 |
-package grpc |
|
| 35 |
- |
|
| 36 |
-import ( |
|
| 37 |
- "container/list" |
|
| 38 |
- "fmt" |
|
| 39 |
- "sync" |
|
| 40 |
- |
|
| 41 |
- "golang.org/x/net/context" |
|
| 42 |
- "google.golang.org/grpc/grpclog" |
|
| 43 |
- "google.golang.org/grpc/naming" |
|
| 44 |
- "google.golang.org/grpc/transport" |
|
| 45 |
-) |
|
| 46 |
- |
|
| 47 |
-// Picker picks a Conn for RPC requests. |
|
| 48 |
-// This is EXPERIMENTAL and please do not implement your own Picker for now. |
|
| 49 |
-type Picker interface {
|
|
| 50 |
- // Init does initial processing for the Picker, e.g., initiate some connections. |
|
| 51 |
- Init(cc *ClientConn) error |
|
| 52 |
- // Pick blocks until either a transport.ClientTransport is ready for the upcoming RPC |
|
| 53 |
- // or some error happens. |
|
| 54 |
- Pick(ctx context.Context) (transport.ClientTransport, error) |
|
| 55 |
- // PickAddr picks a peer address for connecting. This will be called repeated for |
|
| 56 |
- // connecting/reconnecting. |
|
| 57 |
- PickAddr() (string, error) |
|
| 58 |
- // State returns the connectivity state of the underlying connections. |
|
| 59 |
- State() (ConnectivityState, error) |
|
| 60 |
- // WaitForStateChange blocks until the state changes to something other than |
|
| 61 |
- // the sourceState. It returns the new state or error. |
|
| 62 |
- WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) |
|
| 63 |
- // Close closes all the Conn's owned by this Picker. |
|
| 64 |
- Close() error |
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
-// unicastPicker is the default Picker which is used when there is no custom Picker |
|
| 68 |
-// specified by users. It always picks the same Conn. |
|
| 69 |
-type unicastPicker struct {
|
|
| 70 |
- target string |
|
| 71 |
- conn *Conn |
|
| 72 |
-} |
|
| 73 |
- |
|
| 74 |
-func (p *unicastPicker) Init(cc *ClientConn) error {
|
|
| 75 |
- c, err := NewConn(cc) |
|
| 76 |
- if err != nil {
|
|
| 77 |
- return err |
|
| 78 |
- } |
|
| 79 |
- p.conn = c |
|
| 80 |
- return nil |
|
| 81 |
-} |
|
| 82 |
- |
|
| 83 |
-func (p *unicastPicker) Pick(ctx context.Context) (transport.ClientTransport, error) {
|
|
| 84 |
- return p.conn.Wait(ctx) |
|
| 85 |
-} |
|
| 86 |
- |
|
| 87 |
-func (p *unicastPicker) PickAddr() (string, error) {
|
|
| 88 |
- return p.target, nil |
|
| 89 |
-} |
|
| 90 |
- |
|
| 91 |
-func (p *unicastPicker) State() (ConnectivityState, error) {
|
|
| 92 |
- return p.conn.State(), nil |
|
| 93 |
-} |
|
| 94 |
- |
|
| 95 |
-func (p *unicastPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
|
|
| 96 |
- return p.conn.WaitForStateChange(ctx, sourceState) |
|
| 97 |
-} |
|
| 98 |
- |
|
| 99 |
-func (p *unicastPicker) Close() error {
|
|
| 100 |
- if p.conn != nil {
|
|
| 101 |
- return p.conn.Close() |
|
| 102 |
- } |
|
| 103 |
- return nil |
|
| 104 |
-} |
|
| 105 |
- |
|
| 106 |
-// unicastNamingPicker picks an address from a name resolver to set up the connection. |
|
| 107 |
-type unicastNamingPicker struct {
|
|
| 108 |
- cc *ClientConn |
|
| 109 |
- resolver naming.Resolver |
|
| 110 |
- watcher naming.Watcher |
|
| 111 |
- mu sync.Mutex |
|
| 112 |
- // The list of the addresses are obtained from watcher. |
|
| 113 |
- addrs *list.List |
|
| 114 |
- // It tracks the current picked addr by PickAddr(). The next PickAddr may |
|
| 115 |
- // push it forward on addrs. |
|
| 116 |
- pickedAddr *list.Element |
|
| 117 |
- conn *Conn |
|
| 118 |
-} |
|
| 119 |
- |
|
| 120 |
-// NewUnicastNamingPicker creates a Picker to pick addresses from a name resolver |
|
| 121 |
-// to connect. |
|
| 122 |
-func NewUnicastNamingPicker(r naming.Resolver) Picker {
|
|
| 123 |
- return &unicastNamingPicker{
|
|
| 124 |
- resolver: r, |
|
| 125 |
- addrs: list.New(), |
|
| 126 |
- } |
|
| 127 |
-} |
|
| 128 |
- |
|
| 129 |
-type addrInfo struct {
|
|
| 130 |
- addr string |
|
| 131 |
- // Set to true if this addrInfo needs to be deleted in the next PickAddrr() call. |
|
| 132 |
- deleting bool |
|
| 133 |
-} |
|
| 134 |
- |
|
| 135 |
-// processUpdates calls Watcher.Next() once and processes the obtained updates. |
|
| 136 |
-func (p *unicastNamingPicker) processUpdates() error {
|
|
| 137 |
- updates, err := p.watcher.Next() |
|
| 138 |
- if err != nil {
|
|
| 139 |
- return err |
|
| 140 |
- } |
|
| 141 |
- for _, update := range updates {
|
|
| 142 |
- switch update.Op {
|
|
| 143 |
- case naming.Add: |
|
| 144 |
- p.mu.Lock() |
|
| 145 |
- p.addrs.PushBack(&addrInfo{
|
|
| 146 |
- addr: update.Addr, |
|
| 147 |
- }) |
|
| 148 |
- p.mu.Unlock() |
|
| 149 |
- // Initial connection setup |
|
| 150 |
- if p.conn == nil {
|
|
| 151 |
- conn, err := NewConn(p.cc) |
|
| 152 |
- if err != nil {
|
|
| 153 |
- return err |
|
| 154 |
- } |
|
| 155 |
- p.conn = conn |
|
| 156 |
- } |
|
| 157 |
- case naming.Delete: |
|
| 158 |
- p.mu.Lock() |
|
| 159 |
- for e := p.addrs.Front(); e != nil; e = e.Next() {
|
|
| 160 |
- if update.Addr == e.Value.(*addrInfo).addr {
|
|
| 161 |
- if e == p.pickedAddr {
|
|
| 162 |
- // Do not remove the element now if it is the current picked |
|
| 163 |
- // one. We leave the deletion to the next PickAddr() call. |
|
| 164 |
- e.Value.(*addrInfo).deleting = true |
|
| 165 |
- // Notify Conn to close it. All the live RPCs on this connection |
|
| 166 |
- // will be aborted. |
|
| 167 |
- p.conn.NotifyReset() |
|
| 168 |
- } else {
|
|
| 169 |
- p.addrs.Remove(e) |
|
| 170 |
- } |
|
| 171 |
- } |
|
| 172 |
- } |
|
| 173 |
- p.mu.Unlock() |
|
| 174 |
- default: |
|
| 175 |
- grpclog.Println("Unknown update.Op ", update.Op)
|
|
| 176 |
- } |
|
| 177 |
- } |
|
| 178 |
- return nil |
|
| 179 |
-} |
|
| 180 |
- |
|
| 181 |
-// monitor runs in a standalone goroutine to keep watching name resolution updates until the watcher |
|
| 182 |
-// is closed. |
|
| 183 |
-func (p *unicastNamingPicker) monitor() {
|
|
| 184 |
- for {
|
|
| 185 |
- if err := p.processUpdates(); err != nil {
|
|
| 186 |
- return |
|
| 187 |
- } |
|
| 188 |
- } |
|
| 189 |
-} |
|
| 190 |
- |
|
| 191 |
-func (p *unicastNamingPicker) Init(cc *ClientConn) error {
|
|
| 192 |
- w, err := p.resolver.Resolve(cc.target) |
|
| 193 |
- if err != nil {
|
|
| 194 |
- return err |
|
| 195 |
- } |
|
| 196 |
- p.watcher = w |
|
| 197 |
- p.cc = cc |
|
| 198 |
- // Get the initial name resolution. |
|
| 199 |
- if err := p.processUpdates(); err != nil {
|
|
| 200 |
- return err |
|
| 201 |
- } |
|
| 202 |
- go p.monitor() |
|
| 203 |
- return nil |
|
| 204 |
-} |
|
| 205 |
- |
|
| 206 |
-func (p *unicastNamingPicker) Pick(ctx context.Context) (transport.ClientTransport, error) {
|
|
| 207 |
- return p.conn.Wait(ctx) |
|
| 208 |
-} |
|
| 209 |
- |
|
| 210 |
-func (p *unicastNamingPicker) PickAddr() (string, error) {
|
|
| 211 |
- p.mu.Lock() |
|
| 212 |
- defer p.mu.Unlock() |
|
| 213 |
- if p.pickedAddr == nil {
|
|
| 214 |
- p.pickedAddr = p.addrs.Front() |
|
| 215 |
- } else {
|
|
| 216 |
- pa := p.pickedAddr |
|
| 217 |
- p.pickedAddr = pa.Next() |
|
| 218 |
- if pa.Value.(*addrInfo).deleting {
|
|
| 219 |
- p.addrs.Remove(pa) |
|
| 220 |
- } |
|
| 221 |
- if p.pickedAddr == nil {
|
|
| 222 |
- p.pickedAddr = p.addrs.Front() |
|
| 223 |
- } |
|
| 224 |
- } |
|
| 225 |
- if p.pickedAddr == nil {
|
|
| 226 |
- return "", fmt.Errorf("there is no address available to pick")
|
|
| 227 |
- } |
|
| 228 |
- return p.pickedAddr.Value.(*addrInfo).addr, nil |
|
| 229 |
-} |
|
| 230 |
- |
|
| 231 |
-func (p *unicastNamingPicker) State() (ConnectivityState, error) {
|
|
| 232 |
- return 0, fmt.Errorf("State() is not supported for unicastNamingPicker")
|
|
| 233 |
-} |
|
| 234 |
- |
|
| 235 |
-func (p *unicastNamingPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) {
|
|
| 236 |
- return 0, fmt.Errorf("WaitForStateChange is not supported for unicastNamingPciker")
|
|
| 237 |
-} |
|
| 238 |
- |
|
| 239 |
-func (p *unicastNamingPicker) Close() error {
|
|
| 240 |
- p.watcher.Close() |
|
| 241 |
- p.conn.Close() |
|
| 242 |
- return nil |
|
| 243 |
-} |
| ... | ... |
@@ -61,7 +61,7 @@ type Codec interface {
|
| 61 | 61 |
String() string |
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 |
-// protoCodec is a Codec implemetation with protobuf. It is the default codec for gRPC. |
|
| 64 |
+// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC. |
|
| 65 | 65 |
type protoCodec struct{}
|
| 66 | 66 |
|
| 67 | 67 |
func (protoCodec) Marshal(v interface{}) ([]byte, error) {
|
| ... | ... |
@@ -141,6 +141,8 @@ type callInfo struct {
|
| 141 | 141 |
traceInfo traceInfo // in trace.go |
| 142 | 142 |
} |
| 143 | 143 |
|
| 144 |
+var defaultCallInfo = callInfo{failFast: true}
|
|
| 145 |
+ |
|
| 144 | 146 |
// CallOption configures a Call before it starts or extracts information from |
| 145 | 147 |
// a Call after it completes. |
| 146 | 148 |
type CallOption interface {
|
| ... | ... |
@@ -179,6 +181,19 @@ func Trailer(md *metadata.MD) CallOption {
|
| 179 | 179 |
}) |
| 180 | 180 |
} |
| 181 | 181 |
|
| 182 |
+// FailFast configures the action to take when an RPC is attempted on broken |
|
| 183 |
+// connections or unreachable servers. If failfast is true, the RPC will fail |
|
| 184 |
+// immediately. Otherwise, the RPC client will block the call until a |
|
| 185 |
+// connection is available (or the call is canceled or times out) and will retry |
|
| 186 |
+// the call if it fails due to a transient error. Please refer to |
|
| 187 |
+// https://github.com/grpc/grpc/blob/master/doc/fail_fast.md |
|
| 188 |
+func FailFast(failFast bool) CallOption {
|
|
| 189 |
+ return beforeCall(func(c *callInfo) error {
|
|
| 190 |
+ c.failFast = failFast |
|
| 191 |
+ return nil |
|
| 192 |
+ }) |
|
| 193 |
+} |
|
| 194 |
+ |
|
| 182 | 195 |
// The format of the payload: compressed or not? |
| 183 | 196 |
type payloadFormat uint8 |
| 184 | 197 |
|
| ... | ... |
@@ -187,7 +202,7 @@ const ( |
| 187 | 187 |
compressionMade |
| 188 | 188 |
) |
| 189 | 189 |
|
| 190 |
-// parser reads complelete gRPC messages from the underlying reader. |
|
| 190 |
+// parser reads complete gRPC messages from the underlying reader. |
|
| 191 | 191 |
type parser struct {
|
| 192 | 192 |
// r is the underlying reader. |
| 193 | 193 |
// See the comment on recvMsg for the permissible |
| ... | ... |
@@ -212,7 +227,7 @@ type parser struct {
|
| 212 | 212 |
// No other error values or types must be returned, which also means |
| 213 | 213 |
// that the underlying io.Reader must not return an incompatible |
| 214 | 214 |
// error. |
| 215 |
-func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) {
|
|
| 215 |
+func (p *parser) recvMsg(maxMsgSize int) (pf payloadFormat, msg []byte, err error) {
|
|
| 216 | 216 |
if _, err := io.ReadFull(p.r, p.header[:]); err != nil {
|
| 217 | 217 |
return 0, nil, err |
| 218 | 218 |
} |
| ... | ... |
@@ -223,6 +238,9 @@ func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) {
|
| 223 | 223 |
if length == 0 {
|
| 224 | 224 |
return pf, nil, nil |
| 225 | 225 |
} |
| 226 |
+ if length > uint32(maxMsgSize) {
|
|
| 227 |
+ return 0, nil, Errorf(codes.Internal, "grpc: received message length %d exceeding the max size %d", length, maxMsgSize) |
|
| 228 |
+ } |
|
| 226 | 229 |
// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead |
| 227 | 230 |
// of making it for each message: |
| 228 | 231 |
msg = make([]byte, int(length)) |
| ... | ... |
@@ -284,20 +302,17 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) er |
| 284 | 284 |
switch pf {
|
| 285 | 285 |
case compressionNone: |
| 286 | 286 |
case compressionMade: |
| 287 |
- if recvCompress == "" {
|
|
| 288 |
- return transport.StreamErrorf(codes.InvalidArgument, "grpc: invalid grpc-encoding %q with compression enabled", recvCompress) |
|
| 289 |
- } |
|
| 290 | 287 |
if dc == nil || recvCompress != dc.Type() {
|
| 291 |
- return transport.StreamErrorf(codes.InvalidArgument, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) |
|
| 288 |
+ return transport.StreamErrorf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) |
|
| 292 | 289 |
} |
| 293 | 290 |
default: |
| 294 |
- return transport.StreamErrorf(codes.InvalidArgument, "grpc: received unexpected payload format %d", pf) |
|
| 291 |
+ return transport.StreamErrorf(codes.Internal, "grpc: received unexpected payload format %d", pf) |
|
| 295 | 292 |
} |
| 296 | 293 |
return nil |
| 297 | 294 |
} |
| 298 | 295 |
|
| 299 |
-func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}) error {
|
|
| 300 |
- pf, d, err := p.recvMsg() |
|
| 296 |
+func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}, maxMsgSize int) error {
|
|
| 297 |
+ pf, d, err := p.recvMsg(maxMsgSize) |
|
| 301 | 298 |
if err != nil {
|
| 302 | 299 |
return err |
| 303 | 300 |
} |
| ... | ... |
@@ -307,11 +322,16 @@ func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{
|
| 307 | 307 |
if pf == compressionMade {
|
| 308 | 308 |
d, err = dc.Do(bytes.NewReader(d)) |
| 309 | 309 |
if err != nil {
|
| 310 |
- return transport.StreamErrorf(codes.Internal, "grpc: failed to decompress the received message %v", err) |
|
| 310 |
+ return Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) |
|
| 311 | 311 |
} |
| 312 | 312 |
} |
| 313 |
+ if len(d) > maxMsgSize {
|
|
| 314 |
+ // TODO: Revisit the error code. Currently keep it consistent with java |
|
| 315 |
+ // implementation. |
|
| 316 |
+ return Errorf(codes.Internal, "grpc: received a message of %d bytes exceeding %d limit", len(d), maxMsgSize) |
|
| 317 |
+ } |
|
| 313 | 318 |
if err := c.Unmarshal(d, m); err != nil {
|
| 314 |
- return transport.StreamErrorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) |
|
| 319 |
+ return Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) |
|
| 315 | 320 |
} |
| 316 | 321 |
return nil |
| 317 | 322 |
} |
| ... | ... |
@@ -322,7 +342,7 @@ type rpcError struct {
|
| 322 | 322 |
desc string |
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 |
-func (e rpcError) Error() string {
|
|
| 325 |
+func (e *rpcError) Error() string {
|
|
| 326 | 326 |
return fmt.Sprintf("rpc error: code = %d desc = %s", e.code, e.desc)
|
| 327 | 327 |
} |
| 328 | 328 |
|
| ... | ... |
@@ -332,7 +352,7 @@ func Code(err error) codes.Code {
|
| 332 | 332 |
if err == nil {
|
| 333 | 333 |
return codes.OK |
| 334 | 334 |
} |
| 335 |
- if e, ok := err.(rpcError); ok {
|
|
| 335 |
+ if e, ok := err.(*rpcError); ok {
|
|
| 336 | 336 |
return e.code |
| 337 | 337 |
} |
| 338 | 338 |
return codes.Unknown |
| ... | ... |
@@ -344,7 +364,7 @@ func ErrorDesc(err error) string {
|
| 344 | 344 |
if err == nil {
|
| 345 | 345 |
return "" |
| 346 | 346 |
} |
| 347 |
- if e, ok := err.(rpcError); ok {
|
|
| 347 |
+ if e, ok := err.(*rpcError); ok {
|
|
| 348 | 348 |
return e.desc |
| 349 | 349 |
} |
| 350 | 350 |
return err.Error() |
| ... | ... |
@@ -356,7 +376,7 @@ func Errorf(c codes.Code, format string, a ...interface{}) error {
|
| 356 | 356 |
if c == codes.OK {
|
| 357 | 357 |
return nil |
| 358 | 358 |
} |
| 359 |
- return rpcError{
|
|
| 359 |
+ return &rpcError{
|
|
| 360 | 360 |
code: c, |
| 361 | 361 |
desc: fmt.Sprintf(format, a...), |
| 362 | 362 |
} |
| ... | ... |
@@ -365,18 +385,37 @@ func Errorf(c codes.Code, format string, a ...interface{}) error {
|
| 365 | 365 |
// toRPCErr converts an error into a rpcError. |
| 366 | 366 |
func toRPCErr(err error) error {
|
| 367 | 367 |
switch e := err.(type) {
|
| 368 |
- case rpcError: |
|
| 368 |
+ case *rpcError: |
|
| 369 | 369 |
return err |
| 370 | 370 |
case transport.StreamError: |
| 371 |
- return rpcError{
|
|
| 371 |
+ return &rpcError{
|
|
| 372 | 372 |
code: e.Code, |
| 373 | 373 |
desc: e.Desc, |
| 374 | 374 |
} |
| 375 | 375 |
case transport.ConnectionError: |
| 376 |
- return rpcError{
|
|
| 376 |
+ return &rpcError{
|
|
| 377 | 377 |
code: codes.Internal, |
| 378 | 378 |
desc: e.Desc, |
| 379 | 379 |
} |
| 380 |
+ default: |
|
| 381 |
+ switch err {
|
|
| 382 |
+ case context.DeadlineExceeded: |
|
| 383 |
+ return &rpcError{
|
|
| 384 |
+ code: codes.DeadlineExceeded, |
|
| 385 |
+ desc: err.Error(), |
|
| 386 |
+ } |
|
| 387 |
+ case context.Canceled: |
|
| 388 |
+ return &rpcError{
|
|
| 389 |
+ code: codes.Canceled, |
|
| 390 |
+ desc: err.Error(), |
|
| 391 |
+ } |
|
| 392 |
+ case ErrClientConnClosing: |
|
| 393 |
+ return &rpcError{
|
|
| 394 |
+ code: codes.FailedPrecondition, |
|
| 395 |
+ desc: err.Error(), |
|
| 396 |
+ } |
|
| 397 |
+ } |
|
| 398 |
+ |
|
| 380 | 399 |
} |
| 381 | 400 |
return Errorf(codes.Unknown, "%v", err) |
| 382 | 401 |
} |
| ... | ... |
@@ -409,10 +448,10 @@ func convertCode(err error) codes.Code {
|
| 409 | 409 |
return codes.Unknown |
| 410 | 410 |
} |
| 411 | 411 |
|
| 412 |
-// SupportPackageIsVersion2 is referenced from generated protocol buffer files |
|
| 412 |
+// SupportPackageIsVersion3 is referenced from generated protocol buffer files |
|
| 413 | 413 |
// to assert that that code is compatible with this version of the grpc package. |
| 414 | 414 |
// |
| 415 | 415 |
// This constant may be renamed in the future if a change in the generated code |
| 416 | 416 |
// requires a synchronised update of grpc-go and protoc-gen-go. This constant |
| 417 | 417 |
// should not be referenced from any other code. |
| 418 |
-const SupportPackageIsVersion2 = true |
|
| 418 |
+const SupportPackageIsVersion3 = true |
| ... | ... |
@@ -73,6 +73,7 @@ type ServiceDesc struct {
|
| 73 | 73 |
HandlerType interface{}
|
| 74 | 74 |
Methods []MethodDesc |
| 75 | 75 |
Streams []StreamDesc |
| 76 |
+ Metadata interface{}
|
|
| 76 | 77 |
} |
| 77 | 78 |
|
| 78 | 79 |
// service consists of the information of the server serving this service and |
| ... | ... |
@@ -81,30 +82,38 @@ type service struct {
|
| 81 | 81 |
server interface{} // the server for service methods
|
| 82 | 82 |
md map[string]*MethodDesc |
| 83 | 83 |
sd map[string]*StreamDesc |
| 84 |
+ mdata interface{}
|
|
| 84 | 85 |
} |
| 85 | 86 |
|
| 86 | 87 |
// Server is a gRPC server to serve RPC requests. |
| 87 | 88 |
type Server struct {
|
| 88 | 89 |
opts options |
| 89 | 90 |
|
| 90 |
- mu sync.Mutex // guards following |
|
| 91 |
- lis map[net.Listener]bool |
|
| 92 |
- conns map[io.Closer]bool |
|
| 91 |
+ mu sync.Mutex // guards following |
|
| 92 |
+ lis map[net.Listener]bool |
|
| 93 |
+ conns map[io.Closer]bool |
|
| 94 |
+ drain bool |
|
| 95 |
+ // A CondVar to let GracefulStop() blocks until all the pending RPCs are finished |
|
| 96 |
+ // and all the transport goes away. |
|
| 97 |
+ cv *sync.Cond |
|
| 93 | 98 |
m map[string]*service // service name -> service info |
| 94 | 99 |
events trace.EventLog |
| 95 | 100 |
} |
| 96 | 101 |
|
| 97 | 102 |
type options struct {
|
| 98 |
- creds credentials.Credentials |
|
| 103 |
+ creds credentials.TransportCredentials |
|
| 99 | 104 |
codec Codec |
| 100 | 105 |
cp Compressor |
| 101 | 106 |
dc Decompressor |
| 107 |
+ maxMsgSize int |
|
| 102 | 108 |
unaryInt UnaryServerInterceptor |
| 103 | 109 |
streamInt StreamServerInterceptor |
| 104 | 110 |
maxConcurrentStreams uint32 |
| 105 | 111 |
useHandlerImpl bool // use http.Handler-based server |
| 106 | 112 |
} |
| 107 | 113 |
|
| 114 |
+var defaultMaxMsgSize = 1024 * 1024 * 4 // use 4MB as the default message size limit |
|
| 115 |
+ |
|
| 108 | 116 |
// A ServerOption sets options. |
| 109 | 117 |
type ServerOption func(*options) |
| 110 | 118 |
|
| ... | ... |
@@ -115,18 +124,28 @@ func CustomCodec(codec Codec) ServerOption {
|
| 115 | 115 |
} |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 |
+// RPCCompressor returns a ServerOption that sets a compressor for outbound messages. |
|
| 118 | 119 |
func RPCCompressor(cp Compressor) ServerOption {
|
| 119 | 120 |
return func(o *options) {
|
| 120 | 121 |
o.cp = cp |
| 121 | 122 |
} |
| 122 | 123 |
} |
| 123 | 124 |
|
| 125 |
+// RPCDecompressor returns a ServerOption that sets a decompressor for inbound messages. |
|
| 124 | 126 |
func RPCDecompressor(dc Decompressor) ServerOption {
|
| 125 | 127 |
return func(o *options) {
|
| 126 | 128 |
o.dc = dc |
| 127 | 129 |
} |
| 128 | 130 |
} |
| 129 | 131 |
|
| 132 |
+// MaxMsgSize returns a ServerOption to set the max message size in bytes for inbound mesages. |
|
| 133 |
+// If this is not set, gRPC uses the default 4MB. |
|
| 134 |
+func MaxMsgSize(m int) ServerOption {
|
|
| 135 |
+ return func(o *options) {
|
|
| 136 |
+ o.maxMsgSize = m |
|
| 137 |
+ } |
|
| 138 |
+} |
|
| 139 |
+ |
|
| 130 | 140 |
// MaxConcurrentStreams returns a ServerOption that will apply a limit on the number |
| 131 | 141 |
// of concurrent streams to each ServerTransport. |
| 132 | 142 |
func MaxConcurrentStreams(n uint32) ServerOption {
|
| ... | ... |
@@ -136,7 +155,7 @@ func MaxConcurrentStreams(n uint32) ServerOption {
|
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 | 138 |
// Creds returns a ServerOption that sets credentials for server connections. |
| 139 |
-func Creds(c credentials.Credentials) ServerOption {
|
|
| 139 |
+func Creds(c credentials.TransportCredentials) ServerOption {
|
|
| 140 | 140 |
return func(o *options) {
|
| 141 | 141 |
o.creds = c |
| 142 | 142 |
} |
| ... | ... |
@@ -169,6 +188,7 @@ func StreamInterceptor(i StreamServerInterceptor) ServerOption {
|
| 169 | 169 |
// started to accept requests yet. |
| 170 | 170 |
func NewServer(opt ...ServerOption) *Server {
|
| 171 | 171 |
var opts options |
| 172 |
+ opts.maxMsgSize = defaultMaxMsgSize |
|
| 172 | 173 |
for _, o := range opt {
|
| 173 | 174 |
o(&opts) |
| 174 | 175 |
} |
| ... | ... |
@@ -182,6 +202,7 @@ func NewServer(opt ...ServerOption) *Server {
|
| 182 | 182 |
conns: make(map[io.Closer]bool), |
| 183 | 183 |
m: make(map[string]*service), |
| 184 | 184 |
} |
| 185 |
+ s.cv = sync.NewCond(&s.mu) |
|
| 185 | 186 |
if EnableTracing {
|
| 186 | 187 |
_, file, line, _ := runtime.Caller(1) |
| 187 | 188 |
s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line))
|
| ... | ... |
@@ -228,6 +249,7 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) {
|
| 228 | 228 |
server: ss, |
| 229 | 229 |
md: make(map[string]*MethodDesc), |
| 230 | 230 |
sd: make(map[string]*StreamDesc), |
| 231 |
+ mdata: sd.Metadata, |
|
| 231 | 232 |
} |
| 232 | 233 |
for i := range sd.Methods {
|
| 233 | 234 |
d := &sd.Methods[i] |
| ... | ... |
@@ -240,6 +262,52 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) {
|
| 240 | 240 |
s.m[sd.ServiceName] = srv |
| 241 | 241 |
} |
| 242 | 242 |
|
| 243 |
+// MethodInfo contains the information of an RPC including its method name and type. |
|
| 244 |
+type MethodInfo struct {
|
|
| 245 |
+ // Name is the method name only, without the service name or package name. |
|
| 246 |
+ Name string |
|
| 247 |
+ // IsClientStream indicates whether the RPC is a client streaming RPC. |
|
| 248 |
+ IsClientStream bool |
|
| 249 |
+ // IsServerStream indicates whether the RPC is a server streaming RPC. |
|
| 250 |
+ IsServerStream bool |
|
| 251 |
+} |
|
| 252 |
+ |
|
| 253 |
+// ServiceInfo contains unary RPC method info, streaming RPC methid info and metadata for a service. |
|
| 254 |
+type ServiceInfo struct {
|
|
| 255 |
+ Methods []MethodInfo |
|
| 256 |
+ // Metadata is the metadata specified in ServiceDesc when registering service. |
|
| 257 |
+ Metadata interface{}
|
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+// GetServiceInfo returns a map from service names to ServiceInfo. |
|
| 261 |
+// Service names include the package names, in the form of <package>.<service>. |
|
| 262 |
+func (s *Server) GetServiceInfo() map[string]ServiceInfo {
|
|
| 263 |
+ ret := make(map[string]ServiceInfo) |
|
| 264 |
+ for n, srv := range s.m {
|
|
| 265 |
+ methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd)) |
|
| 266 |
+ for m := range srv.md {
|
|
| 267 |
+ methods = append(methods, MethodInfo{
|
|
| 268 |
+ Name: m, |
|
| 269 |
+ IsClientStream: false, |
|
| 270 |
+ IsServerStream: false, |
|
| 271 |
+ }) |
|
| 272 |
+ } |
|
| 273 |
+ for m, d := range srv.sd {
|
|
| 274 |
+ methods = append(methods, MethodInfo{
|
|
| 275 |
+ Name: m, |
|
| 276 |
+ IsClientStream: d.ClientStreams, |
|
| 277 |
+ IsServerStream: d.ServerStreams, |
|
| 278 |
+ }) |
|
| 279 |
+ } |
|
| 280 |
+ |
|
| 281 |
+ ret[n] = ServiceInfo{
|
|
| 282 |
+ Methods: methods, |
|
| 283 |
+ Metadata: srv.mdata, |
|
| 284 |
+ } |
|
| 285 |
+ } |
|
| 286 |
+ return ret |
|
| 287 |
+} |
|
| 288 |
+ |
|
| 243 | 289 |
var ( |
| 244 | 290 |
// ErrServerStopped indicates that the operation is now illegal because of |
| 245 | 291 |
// the server being stopped. |
| ... | ... |
@@ -247,30 +315,33 @@ var ( |
| 247 | 247 |
) |
| 248 | 248 |
|
| 249 | 249 |
func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
| 250 |
- creds, ok := s.opts.creds.(credentials.TransportAuthenticator) |
|
| 251 |
- if !ok {
|
|
| 250 |
+ if s.opts.creds == nil {
|
|
| 252 | 251 |
return rawConn, nil, nil |
| 253 | 252 |
} |
| 254 |
- return creds.ServerHandshake(rawConn) |
|
| 253 |
+ return s.opts.creds.ServerHandshake(rawConn) |
|
| 255 | 254 |
} |
| 256 | 255 |
|
| 257 | 256 |
// Serve accepts incoming connections on the listener lis, creating a new |
| 258 | 257 |
// ServerTransport and service goroutine for each. The service goroutines |
| 259 | 258 |
// read gRPC requests and then call the registered handlers to reply to them. |
| 260 |
-// Service returns when lis.Accept fails. |
|
| 259 |
+// Service returns when lis.Accept fails. lis will be closed when |
|
| 260 |
+// this method returns. |
|
| 261 | 261 |
func (s *Server) Serve(lis net.Listener) error {
|
| 262 | 262 |
s.mu.Lock() |
| 263 | 263 |
s.printf("serving")
|
| 264 | 264 |
if s.lis == nil {
|
| 265 | 265 |
s.mu.Unlock() |
| 266 |
+ lis.Close() |
|
| 266 | 267 |
return ErrServerStopped |
| 267 | 268 |
} |
| 268 | 269 |
s.lis[lis] = true |
| 269 | 270 |
s.mu.Unlock() |
| 270 | 271 |
defer func() {
|
| 271 |
- lis.Close() |
|
| 272 | 272 |
s.mu.Lock() |
| 273 |
- delete(s.lis, lis) |
|
| 273 |
+ if s.lis != nil && s.lis[lis] {
|
|
| 274 |
+ lis.Close() |
|
| 275 |
+ delete(s.lis, lis) |
|
| 276 |
+ } |
|
| 274 | 277 |
s.mu.Unlock() |
| 275 | 278 |
}() |
| 276 | 279 |
for {
|
| ... | ... |
@@ -414,7 +485,7 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea |
| 414 | 414 |
func (s *Server) addConn(c io.Closer) bool {
|
| 415 | 415 |
s.mu.Lock() |
| 416 | 416 |
defer s.mu.Unlock() |
| 417 |
- if s.conns == nil {
|
|
| 417 |
+ if s.conns == nil || s.drain {
|
|
| 418 | 418 |
return false |
| 419 | 419 |
} |
| 420 | 420 |
s.conns[c] = true |
| ... | ... |
@@ -426,6 +497,7 @@ func (s *Server) removeConn(c io.Closer) {
|
| 426 | 426 |
defer s.mu.Unlock() |
| 427 | 427 |
if s.conns != nil {
|
| 428 | 428 |
delete(s.conns, c) |
| 429 |
+ s.cv.Signal() |
|
| 429 | 430 |
} |
| 430 | 431 |
} |
| 431 | 432 |
|
| ... | ... |
@@ -460,9 +532,13 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. |
| 460 | 460 |
} |
| 461 | 461 |
}() |
| 462 | 462 |
} |
| 463 |
+ if s.opts.cp != nil {
|
|
| 464 |
+ // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. |
|
| 465 |
+ stream.SetSendCompress(s.opts.cp.Type()) |
|
| 466 |
+ } |
|
| 463 | 467 |
p := &parser{r: stream}
|
| 464 | 468 |
for {
|
| 465 |
- pf, req, err := p.recvMsg() |
|
| 469 |
+ pf, req, err := p.recvMsg(s.opts.maxMsgSize) |
|
| 466 | 470 |
if err == io.EOF {
|
| 467 | 471 |
// The entire stream is done (for unary RPC only). |
| 468 | 472 |
return err |
| ... | ... |
@@ -472,6 +548,10 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. |
| 472 | 472 |
} |
| 473 | 473 |
if err != nil {
|
| 474 | 474 |
switch err := err.(type) {
|
| 475 |
+ case *rpcError: |
|
| 476 |
+ if err := t.WriteStatus(stream, err.code, err.desc); err != nil {
|
|
| 477 |
+ grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err)
|
|
| 478 |
+ } |
|
| 475 | 479 |
case transport.ConnectionError: |
| 476 | 480 |
// Nothing to do here. |
| 477 | 481 |
case transport.StreamError: |
| ... | ... |
@@ -511,6 +591,12 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. |
| 511 | 511 |
return err |
| 512 | 512 |
} |
| 513 | 513 |
} |
| 514 |
+ if len(req) > s.opts.maxMsgSize {
|
|
| 515 |
+ // TODO: Revisit the error code. Currently keep it consistent with |
|
| 516 |
+ // java implementation. |
|
| 517 |
+ statusCode = codes.Internal |
|
| 518 |
+ statusDesc = fmt.Sprintf("grpc: server received a message of %d bytes exceeding %d limit", len(req), s.opts.maxMsgSize)
|
|
| 519 |
+ } |
|
| 514 | 520 |
if err := s.opts.codec.Unmarshal(req, v); err != nil {
|
| 515 | 521 |
return err |
| 516 | 522 |
} |
| ... | ... |
@@ -521,7 +607,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. |
| 521 | 521 |
} |
| 522 | 522 |
reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) |
| 523 | 523 |
if appErr != nil {
|
| 524 |
- if err, ok := appErr.(rpcError); ok {
|
|
| 524 |
+ if err, ok := appErr.(*rpcError); ok {
|
|
| 525 | 525 |
statusCode = err.code |
| 526 | 526 |
statusDesc = err.desc |
| 527 | 527 |
} else {
|
| ... | ... |
@@ -545,9 +631,6 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. |
| 545 | 545 |
Last: true, |
| 546 | 546 |
Delay: false, |
| 547 | 547 |
} |
| 548 |
- if s.opts.cp != nil {
|
|
| 549 |
- stream.SetSendCompress(s.opts.cp.Type()) |
|
| 550 |
- } |
|
| 551 | 548 |
if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil {
|
| 552 | 549 |
switch err := err.(type) {
|
| 553 | 550 |
case transport.ConnectionError: |
| ... | ... |
@@ -573,13 +656,14 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp |
| 573 | 573 |
stream.SetSendCompress(s.opts.cp.Type()) |
| 574 | 574 |
} |
| 575 | 575 |
ss := &serverStream{
|
| 576 |
- t: t, |
|
| 577 |
- s: stream, |
|
| 578 |
- p: &parser{r: stream},
|
|
| 579 |
- codec: s.opts.codec, |
|
| 580 |
- cp: s.opts.cp, |
|
| 581 |
- dc: s.opts.dc, |
|
| 582 |
- trInfo: trInfo, |
|
| 576 |
+ t: t, |
|
| 577 |
+ s: stream, |
|
| 578 |
+ p: &parser{r: stream},
|
|
| 579 |
+ codec: s.opts.codec, |
|
| 580 |
+ cp: s.opts.cp, |
|
| 581 |
+ dc: s.opts.dc, |
|
| 582 |
+ maxMsgSize: s.opts.maxMsgSize, |
|
| 583 |
+ trInfo: trInfo, |
|
| 583 | 584 |
} |
| 584 | 585 |
if ss.cp != nil {
|
| 585 | 586 |
ss.cbuf = new(bytes.Buffer) |
| ... | ... |
@@ -609,7 +693,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp |
| 609 | 609 |
appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler) |
| 610 | 610 |
} |
| 611 | 611 |
if appErr != nil {
|
| 612 |
- if err, ok := appErr.(rpcError); ok {
|
|
| 612 |
+ if err, ok := appErr.(*rpcError); ok {
|
|
| 613 | 613 |
ss.statusCode = err.code |
| 614 | 614 |
ss.statusDesc = err.desc |
| 615 | 615 |
} else if err, ok := appErr.(transport.StreamError); ok {
|
| ... | ... |
@@ -711,14 +795,16 @@ func (s *Server) Stop() {
|
| 711 | 711 |
s.mu.Lock() |
| 712 | 712 |
listeners := s.lis |
| 713 | 713 |
s.lis = nil |
| 714 |
- cs := s.conns |
|
| 714 |
+ st := s.conns |
|
| 715 | 715 |
s.conns = nil |
| 716 |
+ // interrupt GracefulStop if Stop and GracefulStop are called concurrently. |
|
| 717 |
+ s.cv.Signal() |
|
| 716 | 718 |
s.mu.Unlock() |
| 717 | 719 |
|
| 718 | 720 |
for lis := range listeners {
|
| 719 | 721 |
lis.Close() |
| 720 | 722 |
} |
| 721 |
- for c := range cs {
|
|
| 723 |
+ for c := range st {
|
|
| 722 | 724 |
c.Close() |
| 723 | 725 |
} |
| 724 | 726 |
|
| ... | ... |
@@ -730,6 +816,32 @@ func (s *Server) Stop() {
|
| 730 | 730 |
s.mu.Unlock() |
| 731 | 731 |
} |
| 732 | 732 |
|
| 733 |
+// GracefulStop stops the gRPC server gracefully. It stops the server to accept new |
|
| 734 |
+// connections and RPCs and blocks until all the pending RPCs are finished. |
|
| 735 |
+func (s *Server) GracefulStop() {
|
|
| 736 |
+ s.mu.Lock() |
|
| 737 |
+ defer s.mu.Unlock() |
|
| 738 |
+ if s.drain == true || s.conns == nil {
|
|
| 739 |
+ return |
|
| 740 |
+ } |
|
| 741 |
+ s.drain = true |
|
| 742 |
+ for lis := range s.lis {
|
|
| 743 |
+ lis.Close() |
|
| 744 |
+ } |
|
| 745 |
+ s.lis = nil |
|
| 746 |
+ for c := range s.conns {
|
|
| 747 |
+ c.(transport.ServerTransport).Drain() |
|
| 748 |
+ } |
|
| 749 |
+ for len(s.conns) != 0 {
|
|
| 750 |
+ s.cv.Wait() |
|
| 751 |
+ } |
|
| 752 |
+ s.conns = nil |
|
| 753 |
+ if s.events != nil {
|
|
| 754 |
+ s.events.Finish() |
|
| 755 |
+ s.events = nil |
|
| 756 |
+ } |
|
| 757 |
+} |
|
| 758 |
+ |
|
| 733 | 759 |
func init() {
|
| 734 | 760 |
internal.TestingCloseConns = func(arg interface{}) {
|
| 735 | 761 |
arg.(*Server).testingCloseConns() |
| ... | ... |
@@ -37,6 +37,7 @@ import ( |
| 37 | 37 |
"bytes" |
| 38 | 38 |
"errors" |
| 39 | 39 |
"io" |
| 40 |
+ "math" |
|
| 40 | 41 |
"sync" |
| 41 | 42 |
"time" |
| 42 | 43 |
|
| ... | ... |
@@ -79,17 +80,14 @@ type Stream interface {
|
| 79 | 79 |
RecvMsg(m interface{}) error
|
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 |
-// ClientStream defines the interface a client stream has to satify. |
|
| 82 |
+// ClientStream defines the interface a client stream has to satisfy. |
|
| 83 | 83 |
type ClientStream interface {
|
| 84 | 84 |
// Header returns the header metadata received from the server if there |
| 85 | 85 |
// is any. It blocks if the metadata is not ready to read. |
| 86 | 86 |
Header() (metadata.MD, error) |
| 87 |
- // Trailer returns the trailer metadata from the server. It must be called |
|
| 88 |
- // after stream.Recv() returns non-nil error (including io.EOF) for |
|
| 89 |
- // bi-directional streaming and server streaming or stream.CloseAndRecv() |
|
| 90 |
- // returns for client streaming in order to receive trailer metadata if |
|
| 91 |
- // present. Otherwise, it could returns an empty MD even though trailer |
|
| 92 |
- // is present. |
|
| 87 |
+ // Trailer returns the trailer metadata from the server, if there is any. |
|
| 88 |
+ // It must only be called after stream.CloseAndRecv has returned, or |
|
| 89 |
+ // stream.Recv has returned a non-nil error (including io.EOF). |
|
| 93 | 90 |
Trailer() metadata.MD |
| 94 | 91 |
// CloseSend closes the send direction of the stream. It closes the stream |
| 95 | 92 |
// when non-nil error is met. |
| ... | ... |
@@ -99,16 +97,18 @@ type ClientStream interface {
|
| 99 | 99 |
|
| 100 | 100 |
// NewClientStream creates a new Stream for the client side. This is called |
| 101 | 101 |
// by generated code. |
| 102 |
-func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
|
|
| 102 |
+func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) {
|
|
| 103 | 103 |
var ( |
| 104 | 104 |
t transport.ClientTransport |
| 105 |
- err error |
|
| 105 |
+ s *transport.Stream |
|
| 106 |
+ put func() |
|
| 106 | 107 |
) |
| 107 |
- t, err = cc.dopts.picker.Pick(ctx) |
|
| 108 |
- if err != nil {
|
|
| 109 |
- return nil, toRPCErr(err) |
|
| 108 |
+ c := defaultCallInfo |
|
| 109 |
+ for _, o := range opts {
|
|
| 110 |
+ if err := o.before(&c); err != nil {
|
|
| 111 |
+ return nil, toRPCErr(err) |
|
| 112 |
+ } |
|
| 110 | 113 |
} |
| 111 |
- // TODO(zhaoq): CallOption is omitted. Add support when it is needed. |
|
| 112 | 114 |
callHdr := &transport.CallHdr{
|
| 113 | 115 |
Host: cc.authority, |
| 114 | 116 |
Method: method, |
| ... | ... |
@@ -117,40 +117,98 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth |
| 117 | 117 |
if cc.dopts.cp != nil {
|
| 118 | 118 |
callHdr.SendCompress = cc.dopts.cp.Type() |
| 119 | 119 |
} |
| 120 |
+ var trInfo traceInfo |
|
| 121 |
+ if EnableTracing {
|
|
| 122 |
+ trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
|
|
| 123 |
+ trInfo.firstLine.client = true |
|
| 124 |
+ if deadline, ok := ctx.Deadline(); ok {
|
|
| 125 |
+ trInfo.firstLine.deadline = deadline.Sub(time.Now()) |
|
| 126 |
+ } |
|
| 127 |
+ trInfo.tr.LazyLog(&trInfo.firstLine, false) |
|
| 128 |
+ ctx = trace.NewContext(ctx, trInfo.tr) |
|
| 129 |
+ defer func() {
|
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ // Need to call tr.finish() if error is returned. |
|
| 132 |
+ // Because tr will not be returned to caller. |
|
| 133 |
+ trInfo.tr.LazyPrintf("RPC: [%v]", err)
|
|
| 134 |
+ trInfo.tr.SetError() |
|
| 135 |
+ trInfo.tr.Finish() |
|
| 136 |
+ } |
|
| 137 |
+ }() |
|
| 138 |
+ } |
|
| 139 |
+ gopts := BalancerGetOptions{
|
|
| 140 |
+ BlockingWait: !c.failFast, |
|
| 141 |
+ } |
|
| 142 |
+ for {
|
|
| 143 |
+ t, put, err = cc.getTransport(ctx, gopts) |
|
| 144 |
+ if err != nil {
|
|
| 145 |
+ // TODO(zhaoq): Probably revisit the error handling. |
|
| 146 |
+ if _, ok := err.(*rpcError); ok {
|
|
| 147 |
+ return nil, err |
|
| 148 |
+ } |
|
| 149 |
+ if err == errConnClosing || err == errConnUnavailable {
|
|
| 150 |
+ if c.failFast {
|
|
| 151 |
+ return nil, Errorf(codes.Unavailable, "%v", err) |
|
| 152 |
+ } |
|
| 153 |
+ continue |
|
| 154 |
+ } |
|
| 155 |
+ // All the other errors are treated as Internal errors. |
|
| 156 |
+ return nil, Errorf(codes.Internal, "%v", err) |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ s, err = t.NewStream(ctx, callHdr) |
|
| 160 |
+ if err != nil {
|
|
| 161 |
+ if put != nil {
|
|
| 162 |
+ put() |
|
| 163 |
+ put = nil |
|
| 164 |
+ } |
|
| 165 |
+ if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain {
|
|
| 166 |
+ if c.failFast {
|
|
| 167 |
+ return nil, toRPCErr(err) |
|
| 168 |
+ } |
|
| 169 |
+ continue |
|
| 170 |
+ } |
|
| 171 |
+ return nil, toRPCErr(err) |
|
| 172 |
+ } |
|
| 173 |
+ break |
|
| 174 |
+ } |
|
| 120 | 175 |
cs := &clientStream{
|
| 121 |
- desc: desc, |
|
| 122 |
- codec: cc.dopts.codec, |
|
| 123 |
- cp: cc.dopts.cp, |
|
| 124 |
- dc: cc.dopts.dc, |
|
| 176 |
+ opts: opts, |
|
| 177 |
+ c: c, |
|
| 178 |
+ desc: desc, |
|
| 179 |
+ codec: cc.dopts.codec, |
|
| 180 |
+ cp: cc.dopts.cp, |
|
| 181 |
+ dc: cc.dopts.dc, |
|
| 182 |
+ |
|
| 183 |
+ put: put, |
|
| 184 |
+ t: t, |
|
| 185 |
+ s: s, |
|
| 186 |
+ p: &parser{r: s},
|
|
| 187 |
+ |
|
| 125 | 188 |
tracing: EnableTracing, |
| 189 |
+ trInfo: trInfo, |
|
| 126 | 190 |
} |
| 127 | 191 |
if cc.dopts.cp != nil {
|
| 128 |
- callHdr.SendCompress = cc.dopts.cp.Type() |
|
| 129 | 192 |
cs.cbuf = new(bytes.Buffer) |
| 130 | 193 |
} |
| 131 |
- if cs.tracing {
|
|
| 132 |
- cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
|
|
| 133 |
- cs.trInfo.firstLine.client = true |
|
| 134 |
- if deadline, ok := ctx.Deadline(); ok {
|
|
| 135 |
- cs.trInfo.firstLine.deadline = deadline.Sub(time.Now()) |
|
| 136 |
- } |
|
| 137 |
- cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false) |
|
| 138 |
- ctx = trace.NewContext(ctx, cs.trInfo.tr) |
|
| 139 |
- } |
|
| 140 |
- s, err := t.NewStream(ctx, callHdr) |
|
| 141 |
- if err != nil {
|
|
| 142 |
- cs.finish(err) |
|
| 143 |
- return nil, toRPCErr(err) |
|
| 144 |
- } |
|
| 145 |
- cs.t = t |
|
| 146 |
- cs.s = s |
|
| 147 |
- cs.p = &parser{r: s}
|
|
| 148 |
- // Listen on ctx.Done() to detect cancellation when there is no pending |
|
| 149 |
- // I/O operations on this stream. |
|
| 194 |
+ // Listen on ctx.Done() to detect cancellation and s.Done() to detect normal termination |
|
| 195 |
+ // when there is no pending I/O operations on this stream. |
|
| 150 | 196 |
go func() {
|
| 151 | 197 |
select {
|
| 152 | 198 |
case <-t.Error(): |
| 153 | 199 |
// Incur transport error, simply exit. |
| 200 |
+ case <-s.Done(): |
|
| 201 |
+ // TODO: The trace of the RPC is terminated here when there is no pending |
|
| 202 |
+ // I/O, which is probably not the optimal solution. |
|
| 203 |
+ if s.StatusCode() == codes.OK {
|
|
| 204 |
+ cs.finish(nil) |
|
| 205 |
+ } else {
|
|
| 206 |
+ cs.finish(Errorf(s.StatusCode(), "%s", s.StatusDesc())) |
|
| 207 |
+ } |
|
| 208 |
+ cs.closeTransportStream(nil) |
|
| 209 |
+ case <-s.GoAway(): |
|
| 210 |
+ cs.finish(errConnDrain) |
|
| 211 |
+ cs.closeTransportStream(errConnDrain) |
|
| 154 | 212 |
case <-s.Context().Done(): |
| 155 | 213 |
err := s.Context().Err() |
| 156 | 214 |
cs.finish(err) |
| ... | ... |
@@ -162,6 +220,8 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth |
| 162 | 162 |
|
| 163 | 163 |
// clientStream implements a client side Stream. |
| 164 | 164 |
type clientStream struct {
|
| 165 |
+ opts []CallOption |
|
| 166 |
+ c callInfo |
|
| 165 | 167 |
t transport.ClientTransport |
| 166 | 168 |
s *transport.Stream |
| 167 | 169 |
p *parser |
| ... | ... |
@@ -174,6 +234,7 @@ type clientStream struct {
|
| 174 | 174 |
tracing bool // set to EnableTracing when the clientStream is created. |
| 175 | 175 |
|
| 176 | 176 |
mu sync.Mutex |
| 177 |
+ put func() |
|
| 177 | 178 |
closed bool |
| 178 | 179 |
// trInfo.tr is set when the clientStream is created (if EnableTracing is true), |
| 179 | 180 |
// and is set to nil when the clientStream's finish method is called. |
| ... | ... |
@@ -210,7 +271,17 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
|
| 210 | 210 |
if err != nil {
|
| 211 | 211 |
cs.finish(err) |
| 212 | 212 |
} |
| 213 |
- if err == nil || err == io.EOF {
|
|
| 213 |
+ if err == nil {
|
|
| 214 |
+ return |
|
| 215 |
+ } |
|
| 216 |
+ if err == io.EOF {
|
|
| 217 |
+ // Specialize the process for server streaming. SendMesg is only called |
|
| 218 |
+ // once when creating the stream object. io.EOF needs to be skipped when |
|
| 219 |
+ // the rpc is early finished (before the stream object is created.). |
|
| 220 |
+ // TODO: It is probably better to move this into the generated code. |
|
| 221 |
+ if !cs.desc.ClientStreams && cs.desc.ServerStreams {
|
|
| 222 |
+ err = nil |
|
| 223 |
+ } |
|
| 214 | 224 |
return |
| 215 | 225 |
} |
| 216 | 226 |
if _, ok := err.(transport.ConnectionError); !ok {
|
| ... | ... |
@@ -231,7 +302,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
|
| 231 | 231 |
} |
| 232 | 232 |
|
| 233 | 233 |
func (cs *clientStream) RecvMsg(m interface{}) (err error) {
|
| 234 |
- err = recv(cs.p, cs.codec, cs.s, cs.dc, m) |
|
| 234 |
+ err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) |
|
| 235 | 235 |
defer func() {
|
| 236 | 236 |
// err != nil indicates the termination of the stream. |
| 237 | 237 |
if err != nil {
|
| ... | ... |
@@ -250,7 +321,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) {
|
| 250 | 250 |
return |
| 251 | 251 |
} |
| 252 | 252 |
// Special handling for client streaming rpc. |
| 253 |
- err = recv(cs.p, cs.codec, cs.s, cs.dc, m) |
|
| 253 |
+ err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) |
|
| 254 | 254 |
cs.closeTransportStream(err) |
| 255 | 255 |
if err == nil {
|
| 256 | 256 |
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
|
| ... | ... |
@@ -285,7 +356,7 @@ func (cs *clientStream) CloseSend() (err error) {
|
| 285 | 285 |
} |
| 286 | 286 |
}() |
| 287 | 287 |
if err == nil || err == io.EOF {
|
| 288 |
- return |
|
| 288 |
+ return nil |
|
| 289 | 289 |
} |
| 290 | 290 |
if _, ok := err.(transport.ConnectionError); !ok {
|
| 291 | 291 |
cs.closeTransportStream(err) |
| ... | ... |
@@ -306,11 +377,18 @@ func (cs *clientStream) closeTransportStream(err error) {
|
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
func (cs *clientStream) finish(err error) {
|
| 309 |
+ cs.mu.Lock() |
|
| 310 |
+ defer cs.mu.Unlock() |
|
| 311 |
+ for _, o := range cs.opts {
|
|
| 312 |
+ o.after(&cs.c) |
|
| 313 |
+ } |
|
| 314 |
+ if cs.put != nil {
|
|
| 315 |
+ cs.put() |
|
| 316 |
+ cs.put = nil |
|
| 317 |
+ } |
|
| 309 | 318 |
if !cs.tracing {
|
| 310 | 319 |
return |
| 311 | 320 |
} |
| 312 |
- cs.mu.Lock() |
|
| 313 |
- defer cs.mu.Unlock() |
|
| 314 | 321 |
if cs.trInfo.tr != nil {
|
| 315 | 322 |
if err == nil || err == io.EOF {
|
| 316 | 323 |
cs.trInfo.tr.LazyPrintf("RPC: [OK]")
|
| ... | ... |
@@ -344,6 +422,7 @@ type serverStream struct {
|
| 344 | 344 |
cp Compressor |
| 345 | 345 |
dc Decompressor |
| 346 | 346 |
cbuf *bytes.Buffer |
| 347 |
+ maxMsgSize int |
|
| 347 | 348 |
statusCode codes.Code |
| 348 | 349 |
statusDesc string |
| 349 | 350 |
trInfo *traceInfo |
| ... | ... |
@@ -410,5 +489,5 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
|
| 410 | 410 |
ss.mu.Unlock() |
| 411 | 411 |
} |
| 412 | 412 |
}() |
| 413 |
- return recv(ss.p, ss.codec, ss.s, ss.dc, m) |
|
| 413 |
+ return recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxMsgSize) |
|
| 414 | 414 |
} |
| ... | ... |
@@ -101,9 +101,8 @@ type payload struct {
|
| 101 | 101 |
func (p payload) String() string {
|
| 102 | 102 |
if p.sent {
|
| 103 | 103 |
return fmt.Sprintf("sent: %v", p.msg)
|
| 104 |
- } else {
|
|
| 105 |
- return fmt.Sprintf("recv: %v", p.msg)
|
|
| 106 | 104 |
} |
| 105 |
+ return fmt.Sprintf("recv: %v", p.msg)
|
|
| 107 | 106 |
} |
| 108 | 107 |
|
| 109 | 108 |
type fmtStringer struct {
|
| 78 | 83 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+// +build go1.6,!go1.7 |
|
| 1 |
+ |
|
| 2 |
+/* |
|
| 3 |
+ * Copyright 2016, Google Inc. |
|
| 4 |
+ * All rights reserved. |
|
| 5 |
+ * |
|
| 6 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 7 |
+ * modification, are permitted provided that the following conditions are |
|
| 8 |
+ * met: |
|
| 9 |
+ * |
|
| 10 |
+ * * Redistributions of source code must retain the above copyright |
|
| 11 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 12 |
+ * * Redistributions in binary form must reproduce the above |
|
| 13 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 14 |
+ * in the documentation and/or other materials provided with the |
|
| 15 |
+ * distribution. |
|
| 16 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 17 |
+ * contributors may be used to endorse or promote products derived from |
|
| 18 |
+ * this software without specific prior written permission. |
|
| 19 |
+ * |
|
| 20 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 21 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 22 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 23 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 24 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 25 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 26 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 27 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 28 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 29 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 30 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 31 |
+ * |
|
| 32 |
+ */ |
|
| 33 |
+ |
|
| 34 |
+package transport |
|
| 35 |
+ |
|
| 36 |
+import ( |
|
| 37 |
+ "net" |
|
| 38 |
+ |
|
| 39 |
+ "golang.org/x/net/context" |
|
| 40 |
+) |
|
| 41 |
+ |
|
| 42 |
+// dialContext connects to the address on the named network. |
|
| 43 |
+func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
|
| 44 |
+ return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
|
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+// +build go1.7 |
|
| 1 |
+ |
|
| 2 |
+/* |
|
| 3 |
+ * Copyright 2016, Google Inc. |
|
| 4 |
+ * All rights reserved. |
|
| 5 |
+ * |
|
| 6 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 7 |
+ * modification, are permitted provided that the following conditions are |
|
| 8 |
+ * met: |
|
| 9 |
+ * |
|
| 10 |
+ * * Redistributions of source code must retain the above copyright |
|
| 11 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 12 |
+ * * Redistributions in binary form must reproduce the above |
|
| 13 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 14 |
+ * in the documentation and/or other materials provided with the |
|
| 15 |
+ * distribution. |
|
| 16 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 17 |
+ * contributors may be used to endorse or promote products derived from |
|
| 18 |
+ * this software without specific prior written permission. |
|
| 19 |
+ * |
|
| 20 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 21 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 22 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 23 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 24 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 25 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 26 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 27 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 28 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 29 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 30 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 31 |
+ * |
|
| 32 |
+ */ |
|
| 33 |
+ |
|
| 34 |
+package transport |
|
| 35 |
+ |
|
| 36 |
+import ( |
|
| 37 |
+ "net" |
|
| 38 |
+ |
|
| 39 |
+ "golang.org/x/net/context" |
|
| 40 |
+) |
|
| 41 |
+ |
|
| 42 |
+// dialContext connects to the address on the named network. |
|
| 43 |
+func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
|
| 44 |
+ return (&net.Dialer{}).DialContext(ctx, network, address)
|
|
| 45 |
+} |
| ... | ... |
@@ -65,7 +65,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr |
| 65 | 65 |
if r.Method != "POST" {
|
| 66 | 66 |
return nil, errors.New("invalid gRPC request method")
|
| 67 | 67 |
} |
| 68 |
- if !strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
|
|
| 68 |
+ if !validContentType(r.Header.Get("Content-Type")) {
|
|
| 69 | 69 |
return nil, errors.New("invalid gRPC request content-type")
|
| 70 | 70 |
} |
| 71 | 71 |
if _, ok := w.(http.Flusher); !ok {
|
| ... | ... |
@@ -83,7 +83,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 | 85 |
if v := r.Header.Get("grpc-timeout"); v != "" {
|
| 86 |
- to, err := timeoutDecode(v) |
|
| 86 |
+ to, err := decodeTimeout(v) |
|
| 87 | 87 |
if err != nil {
|
| 88 | 88 |
return nil, StreamErrorf(codes.Internal, "malformed time-out: %v", err) |
| 89 | 89 |
} |
| ... | ... |
@@ -92,9 +92,12 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr |
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 | 94 |
var metakv []string |
| 95 |
+ if r.Host != "" {
|
|
| 96 |
+ metakv = append(metakv, ":authority", r.Host) |
|
| 97 |
+ } |
|
| 95 | 98 |
for k, vv := range r.Header {
|
| 96 | 99 |
k = strings.ToLower(k) |
| 97 |
- if isReservedHeader(k) {
|
|
| 100 |
+ if isReservedHeader(k) && !isWhitelistedPseudoHeader(k) {
|
|
| 98 | 101 |
continue |
| 99 | 102 |
} |
| 100 | 103 |
for _, v := range vv {
|
| ... | ... |
@@ -108,7 +111,6 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr |
| 108 | 108 |
} |
| 109 | 109 |
} |
| 110 | 110 |
metakv = append(metakv, k, v) |
| 111 |
- |
|
| 112 | 111 |
} |
| 113 | 112 |
} |
| 114 | 113 |
st.headerMD = metadata.Pairs(metakv...) |
| ... | ... |
@@ -192,10 +194,14 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, statusCode codes.Code, |
| 192 | 192 |
h := ht.rw.Header() |
| 193 | 193 |
h.Set("Grpc-Status", fmt.Sprintf("%d", statusCode))
|
| 194 | 194 |
if statusDesc != "" {
|
| 195 |
- h.Set("Grpc-Message", statusDesc)
|
|
| 195 |
+ h.Set("Grpc-Message", encodeGrpcMessage(statusDesc))
|
|
| 196 | 196 |
} |
| 197 | 197 |
if md := s.Trailer(); len(md) > 0 {
|
| 198 | 198 |
for k, vv := range md {
|
| 199 |
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent. |
|
| 200 |
+ if isReservedHeader(k) {
|
|
| 201 |
+ continue |
|
| 202 |
+ } |
|
| 199 | 203 |
for _, v := range vv {
|
| 200 | 204 |
// http2 ResponseWriter mechanism to |
| 201 | 205 |
// send undeclared Trailers after the |
| ... | ... |
@@ -249,6 +255,10 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
|
| 249 | 249 |
ht.writeCommonHeaders(s) |
| 250 | 250 |
h := ht.rw.Header() |
| 251 | 251 |
for k, vv := range md {
|
| 252 |
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent. |
|
| 253 |
+ if isReservedHeader(k) {
|
|
| 254 |
+ continue |
|
| 255 |
+ } |
|
| 252 | 256 |
for _, v := range vv {
|
| 253 | 257 |
h.Add(k, v) |
| 254 | 258 |
} |
| ... | ... |
@@ -302,7 +312,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) {
|
| 302 | 302 |
Addr: ht.RemoteAddr(), |
| 303 | 303 |
} |
| 304 | 304 |
if req.TLS != nil {
|
| 305 |
- pr.AuthInfo = credentials.TLSInfo{*req.TLS}
|
|
| 305 |
+ pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
|
|
| 306 | 306 |
} |
| 307 | 307 |
ctx = metadata.NewContext(ctx, ht.headerMD) |
| 308 | 308 |
ctx = peer.NewContext(ctx, pr) |
| ... | ... |
@@ -360,6 +370,10 @@ func (ht *serverHandlerTransport) runStream() {
|
| 360 | 360 |
} |
| 361 | 361 |
} |
| 362 | 362 |
|
| 363 |
+func (ht *serverHandlerTransport) Drain() {
|
|
| 364 |
+ panic("Drain() is not implemented")
|
|
| 365 |
+} |
|
| 366 |
+ |
|
| 363 | 367 |
// mapRecvMsgError returns the non-nil err into the appropriate |
| 364 | 368 |
// error value as expected by callers of *grpc.parser.recvMsg. |
| 365 | 369 |
// In particular, in can only be: |
| ... | ... |
@@ -35,7 +35,7 @@ package transport |
| 35 | 35 |
|
| 36 | 36 |
import ( |
| 37 | 37 |
"bytes" |
| 38 |
- "errors" |
|
| 38 |
+ "fmt" |
|
| 39 | 39 |
"io" |
| 40 | 40 |
"math" |
| 41 | 41 |
"net" |
| ... | ... |
@@ -72,6 +72,9 @@ type http2Client struct {
|
| 72 | 72 |
shutdownChan chan struct{}
|
| 73 | 73 |
// errorChan is closed to notify the I/O error to the caller. |
| 74 | 74 |
errorChan chan struct{}
|
| 75 |
+ // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor) |
|
| 76 |
+ // that the server sent GoAway on this transport. |
|
| 77 |
+ goAway chan struct{}
|
|
| 75 | 78 |
|
| 76 | 79 |
framer *framer |
| 77 | 80 |
hBuf *bytes.Buffer // the buffer for HPACK encoding |
| ... | ... |
@@ -89,7 +92,7 @@ type http2Client struct {
|
| 89 | 89 |
// The scheme used: https if TLS is on, http otherwise. |
| 90 | 90 |
scheme string |
| 91 | 91 |
|
| 92 |
- authCreds []credentials.Credentials |
|
| 92 |
+ creds []credentials.PerRPCCredentials |
|
| 93 | 93 |
|
| 94 | 94 |
mu sync.Mutex // guard the following variables |
| 95 | 95 |
state transportState // the state of underlying connection |
| ... | ... |
@@ -98,48 +101,44 @@ type http2Client struct {
|
| 98 | 98 |
maxStreams int |
| 99 | 99 |
// the per-stream outbound flow control window size set by the peer. |
| 100 | 100 |
streamSendQuota uint32 |
| 101 |
+ // goAwayID records the Last-Stream-ID in the GoAway frame from the server. |
|
| 102 |
+ goAwayID uint32 |
|
| 103 |
+ // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame. |
|
| 104 |
+ prevGoAwayID uint32 |
|
| 105 |
+} |
|
| 106 |
+ |
|
| 107 |
+func dial(fn func(context.Context, string) (net.Conn, error), ctx context.Context, addr string) (net.Conn, error) {
|
|
| 108 |
+ if fn != nil {
|
|
| 109 |
+ return fn(ctx, addr) |
|
| 110 |
+ } |
|
| 111 |
+ return dialContext(ctx, "tcp", addr) |
|
| 101 | 112 |
} |
| 102 | 113 |
|
| 103 | 114 |
// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 |
| 104 | 115 |
// and starts to receive messages on it. Non-nil error returns if construction |
| 105 | 116 |
// fails. |
| 106 |
-func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err error) {
|
|
| 107 |
- if opts.Dialer == nil {
|
|
| 108 |
- // Set the default Dialer. |
|
| 109 |
- opts.Dialer = func(addr string, timeout time.Duration) (net.Conn, error) {
|
|
| 110 |
- return net.DialTimeout("tcp", addr, timeout)
|
|
| 111 |
- } |
|
| 112 |
- } |
|
| 117 |
+func newHTTP2Client(ctx context.Context, addr string, opts ConnectOptions) (_ ClientTransport, err error) {
|
|
| 113 | 118 |
scheme := "http" |
| 114 |
- startT := time.Now() |
|
| 115 |
- timeout := opts.Timeout |
|
| 116 |
- conn, connErr := opts.Dialer(addr, timeout) |
|
| 119 |
+ conn, connErr := dial(opts.Dialer, ctx, addr) |
|
| 117 | 120 |
if connErr != nil {
|
| 118 |
- return nil, ConnectionErrorf("transport: %v", connErr)
|
|
| 121 |
+ return nil, ConnectionErrorf(true, connErr, "transport: %v", connErr) |
|
| 119 | 122 |
} |
| 120 |
- var authInfo credentials.AuthInfo |
|
| 121 |
- for _, c := range opts.AuthOptions {
|
|
| 122 |
- if ccreds, ok := c.(credentials.TransportAuthenticator); ok {
|
|
| 123 |
- scheme = "https" |
|
| 124 |
- // TODO(zhaoq): Now the first TransportAuthenticator is used if there are |
|
| 125 |
- // multiple ones provided. Revisit this if it is not appropriate. Probably |
|
| 126 |
- // place the ClientTransport construction into a separate function to make |
|
| 127 |
- // things clear. |
|
| 128 |
- if timeout > 0 {
|
|
| 129 |
- timeout -= time.Since(startT) |
|
| 130 |
- } |
|
| 131 |
- conn, authInfo, connErr = ccreds.ClientHandshake(addr, conn, timeout) |
|
| 132 |
- break |
|
| 123 |
+ // Any further errors will close the underlying connection |
|
| 124 |
+ defer func(conn net.Conn) {
|
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ conn.Close() |
|
| 133 | 127 |
} |
| 128 |
+ }(conn) |
|
| 129 |
+ var authInfo credentials.AuthInfo |
|
| 130 |
+ if creds := opts.TransportCredentials; creds != nil {
|
|
| 131 |
+ scheme = "https" |
|
| 132 |
+ conn, authInfo, connErr = creds.ClientHandshake(ctx, addr, conn) |
|
| 134 | 133 |
} |
| 135 | 134 |
if connErr != nil {
|
| 136 |
- return nil, ConnectionErrorf("transport: %v", connErr)
|
|
| 135 |
+ // Credentials handshake error is not a temporary error (unless the error |
|
| 136 |
+ // was the connection closing). |
|
| 137 |
+ return nil, ConnectionErrorf(connErr == io.EOF, connErr, "transport: %v", connErr) |
|
| 137 | 138 |
} |
| 138 |
- defer func() {
|
|
| 139 |
- if err != nil {
|
|
| 140 |
- conn.Close() |
|
| 141 |
- } |
|
| 142 |
- }() |
|
| 143 | 139 |
ua := primaryUA |
| 144 | 140 |
if opts.UserAgent != "" {
|
| 145 | 141 |
ua = opts.UserAgent + " " + ua |
| ... | ... |
@@ -155,6 +154,7 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e |
| 155 | 155 |
writableChan: make(chan int, 1), |
| 156 | 156 |
shutdownChan: make(chan struct{}),
|
| 157 | 157 |
errorChan: make(chan struct{}),
|
| 158 |
+ goAway: make(chan struct{}),
|
|
| 158 | 159 |
framer: newFramer(conn), |
| 159 | 160 |
hBuf: &buf, |
| 160 | 161 |
hEnc: hpack.NewEncoder(&buf), |
| ... | ... |
@@ -164,7 +164,7 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e |
| 164 | 164 |
scheme: scheme, |
| 165 | 165 |
state: reachable, |
| 166 | 166 |
activeStreams: make(map[uint32]*Stream), |
| 167 |
- authCreds: opts.AuthOptions, |
|
| 167 |
+ creds: opts.PerRPCCredentials, |
|
| 168 | 168 |
maxStreams: math.MaxInt32, |
| 169 | 169 |
streamSendQuota: defaultWindowSize, |
| 170 | 170 |
} |
| ... | ... |
@@ -176,26 +176,29 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e |
| 176 | 176 |
n, err := t.conn.Write(clientPreface) |
| 177 | 177 |
if err != nil {
|
| 178 | 178 |
t.Close() |
| 179 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 179 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 180 | 180 |
} |
| 181 | 181 |
if n != len(clientPreface) {
|
| 182 | 182 |
t.Close() |
| 183 |
- return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
|
|
| 183 |
+ return nil, ConnectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) |
|
| 184 | 184 |
} |
| 185 | 185 |
if initialWindowSize != defaultWindowSize {
|
| 186 |
- err = t.framer.writeSettings(true, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)})
|
|
| 186 |
+ err = t.framer.writeSettings(true, http2.Setting{
|
|
| 187 |
+ ID: http2.SettingInitialWindowSize, |
|
| 188 |
+ Val: uint32(initialWindowSize), |
|
| 189 |
+ }) |
|
| 187 | 190 |
} else {
|
| 188 | 191 |
err = t.framer.writeSettings(true) |
| 189 | 192 |
} |
| 190 | 193 |
if err != nil {
|
| 191 | 194 |
t.Close() |
| 192 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 195 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 193 | 196 |
} |
| 194 | 197 |
// Adjust the connection flow control window if needed. |
| 195 | 198 |
if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 {
|
| 196 | 199 |
if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil {
|
| 197 | 200 |
t.Close() |
| 198 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 201 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 199 | 202 |
} |
| 200 | 203 |
} |
| 201 | 204 |
go t.controller() |
| ... | ... |
@@ -207,6 +210,8 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
|
| 207 | 207 |
// TODO(zhaoq): Handle uint32 overflow of Stream.id. |
| 208 | 208 |
s := &Stream{
|
| 209 | 209 |
id: t.nextID, |
| 210 |
+ done: make(chan struct{}),
|
|
| 211 |
+ goAway: make(chan struct{}),
|
|
| 210 | 212 |
method: callHdr.Method, |
| 211 | 213 |
sendCompress: callHdr.SendCompress, |
| 212 | 214 |
buf: newRecvBuffer(), |
| ... | ... |
@@ -221,8 +226,9 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
|
| 221 | 221 |
// Make a stream be able to cancel the pending operations by itself. |
| 222 | 222 |
s.ctx, s.cancel = context.WithCancel(ctx) |
| 223 | 223 |
s.dec = &recvBufferReader{
|
| 224 |
- ctx: s.ctx, |
|
| 225 |
- recv: s.buf, |
|
| 224 |
+ ctx: s.ctx, |
|
| 225 |
+ goAway: s.goAway, |
|
| 226 |
+ recv: s.buf, |
|
| 226 | 227 |
} |
| 227 | 228 |
return s |
| 228 | 229 |
} |
| ... | ... |
@@ -249,7 +255,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 249 | 249 |
} |
| 250 | 250 |
ctx = peer.NewContext(ctx, pr) |
| 251 | 251 |
authData := make(map[string]string) |
| 252 |
- for _, c := range t.authCreds {
|
|
| 252 |
+ for _, c := range t.creds {
|
|
| 253 | 253 |
// Construct URI required to get auth request metadata. |
| 254 | 254 |
var port string |
| 255 | 255 |
if pos := strings.LastIndex(t.target, ":"); pos != -1 {
|
| ... | ... |
@@ -272,6 +278,14 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 272 | 272 |
} |
| 273 | 273 |
} |
| 274 | 274 |
t.mu.Lock() |
| 275 |
+ if t.activeStreams == nil {
|
|
| 276 |
+ t.mu.Unlock() |
|
| 277 |
+ return nil, ErrConnClosing |
|
| 278 |
+ } |
|
| 279 |
+ if t.state == draining {
|
|
| 280 |
+ t.mu.Unlock() |
|
| 281 |
+ return nil, ErrStreamDrain |
|
| 282 |
+ } |
|
| 275 | 283 |
if t.state != reachable {
|
| 276 | 284 |
t.mu.Unlock() |
| 277 | 285 |
return nil, ErrConnClosing |
| ... | ... |
@@ -279,7 +293,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 279 | 279 |
checkStreamsQuota := t.streamsQuota != nil |
| 280 | 280 |
t.mu.Unlock() |
| 281 | 281 |
if checkStreamsQuota {
|
| 282 |
- sq, err := wait(ctx, t.shutdownChan, t.streamsQuota.acquire()) |
|
| 282 |
+ sq, err := wait(ctx, nil, nil, t.shutdownChan, t.streamsQuota.acquire()) |
|
| 283 | 283 |
if err != nil {
|
| 284 | 284 |
return nil, err |
| 285 | 285 |
} |
| ... | ... |
@@ -288,11 +302,23 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 288 | 288 |
t.streamsQuota.add(sq - 1) |
| 289 | 289 |
} |
| 290 | 290 |
} |
| 291 |
- if _, err := wait(ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 292 |
- // t.streamsQuota will be updated when t.CloseStream is invoked. |
|
| 291 |
+ if _, err := wait(ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
|
|
| 292 |
+ // Return the quota back now because there is no stream returned to the caller. |
|
| 293 |
+ if _, ok := err.(StreamError); ok && checkStreamsQuota {
|
|
| 294 |
+ t.streamsQuota.add(1) |
|
| 295 |
+ } |
|
| 293 | 296 |
return nil, err |
| 294 | 297 |
} |
| 295 | 298 |
t.mu.Lock() |
| 299 |
+ if t.state == draining {
|
|
| 300 |
+ t.mu.Unlock() |
|
| 301 |
+ if checkStreamsQuota {
|
|
| 302 |
+ t.streamsQuota.add(1) |
|
| 303 |
+ } |
|
| 304 |
+ // Need to make t writable again so that the rpc in flight can still proceed. |
|
| 305 |
+ t.writableChan <- 0 |
|
| 306 |
+ return nil, ErrStreamDrain |
|
| 307 |
+ } |
|
| 296 | 308 |
if t.state != reachable {
|
| 297 | 309 |
t.mu.Unlock() |
| 298 | 310 |
return nil, ErrConnClosing |
| ... | ... |
@@ -327,7 +353,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 327 | 327 |
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress})
|
| 328 | 328 |
} |
| 329 | 329 |
if timeout > 0 {
|
| 330 |
- t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: timeoutEncode(timeout)})
|
|
| 330 |
+ t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)})
|
|
| 331 | 331 |
} |
| 332 | 332 |
for k, v := range authData {
|
| 333 | 333 |
// Capital header names are illegal in HTTP/2. |
| ... | ... |
@@ -341,6 +367,10 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 341 | 341 |
if md, ok := metadata.FromContext(ctx); ok {
|
| 342 | 342 |
hasMD = true |
| 343 | 343 |
for k, v := range md {
|
| 344 |
+ // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set. |
|
| 345 |
+ if isReservedHeader(k) {
|
|
| 346 |
+ continue |
|
| 347 |
+ } |
|
| 344 | 348 |
for _, entry := range v {
|
| 345 | 349 |
t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry})
|
| 346 | 350 |
} |
| ... | ... |
@@ -378,7 +408,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 378 | 378 |
} |
| 379 | 379 |
if err != nil {
|
| 380 | 380 |
t.notifyError(err) |
| 381 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 381 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 382 | 382 |
} |
| 383 | 383 |
} |
| 384 | 384 |
t.writableChan <- 0 |
| ... | ... |
@@ -390,19 +420,24 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea |
| 390 | 390 |
func (t *http2Client) CloseStream(s *Stream, err error) {
|
| 391 | 391 |
var updateStreams bool |
| 392 | 392 |
t.mu.Lock() |
| 393 |
+ if t.activeStreams == nil {
|
|
| 394 |
+ t.mu.Unlock() |
|
| 395 |
+ return |
|
| 396 |
+ } |
|
| 393 | 397 |
if t.streamsQuota != nil {
|
| 394 | 398 |
updateStreams = true |
| 395 | 399 |
} |
| 396 | 400 |
delete(t.activeStreams, s.id) |
| 401 |
+ if t.state == draining && len(t.activeStreams) == 0 {
|
|
| 402 |
+ // The transport is draining and s is the last live stream on t. |
|
| 403 |
+ t.mu.Unlock() |
|
| 404 |
+ t.Close() |
|
| 405 |
+ return |
|
| 406 |
+ } |
|
| 397 | 407 |
t.mu.Unlock() |
| 398 | 408 |
if updateStreams {
|
| 399 | 409 |
t.streamsQuota.add(1) |
| 400 | 410 |
} |
| 401 |
- // In case stream sending and receiving are invoked in separate |
|
| 402 |
- // goroutines (e.g., bi-directional streaming), the caller needs |
|
| 403 |
- // to call cancel on the stream to interrupt the blocking on |
|
| 404 |
- // other goroutines. |
|
| 405 |
- s.cancel() |
|
| 406 | 411 |
s.mu.Lock() |
| 407 | 412 |
if q := s.fc.resetPendingData(); q > 0 {
|
| 408 | 413 |
if n := t.fc.onRead(q); n > 0 {
|
| ... | ... |
@@ -429,12 +464,12 @@ func (t *http2Client) CloseStream(s *Stream, err error) {
|
| 429 | 429 |
// accessed any more. |
| 430 | 430 |
func (t *http2Client) Close() (err error) {
|
| 431 | 431 |
t.mu.Lock() |
| 432 |
- if t.state == reachable {
|
|
| 433 |
- close(t.errorChan) |
|
| 434 |
- } |
|
| 435 | 432 |
if t.state == closing {
|
| 436 | 433 |
t.mu.Unlock() |
| 437 |
- return errors.New("transport: Close() was already called")
|
|
| 434 |
+ return |
|
| 435 |
+ } |
|
| 436 |
+ if t.state == reachable || t.state == draining {
|
|
| 437 |
+ close(t.errorChan) |
|
| 438 | 438 |
} |
| 439 | 439 |
t.state = closing |
| 440 | 440 |
t.mu.Unlock() |
| ... | ... |
@@ -457,6 +492,50 @@ func (t *http2Client) Close() (err error) {
|
| 457 | 457 |
return |
| 458 | 458 |
} |
| 459 | 459 |
|
| 460 |
+func (t *http2Client) GracefulClose() error {
|
|
| 461 |
+ t.mu.Lock() |
|
| 462 |
+ switch t.state {
|
|
| 463 |
+ case unreachable: |
|
| 464 |
+ // The server may close the connection concurrently. t is not available for |
|
| 465 |
+ // any streams. Close it now. |
|
| 466 |
+ t.mu.Unlock() |
|
| 467 |
+ t.Close() |
|
| 468 |
+ return nil |
|
| 469 |
+ case closing: |
|
| 470 |
+ t.mu.Unlock() |
|
| 471 |
+ return nil |
|
| 472 |
+ } |
|
| 473 |
+ // Notify the streams which were initiated after the server sent GOAWAY. |
|
| 474 |
+ select {
|
|
| 475 |
+ case <-t.goAway: |
|
| 476 |
+ n := t.prevGoAwayID |
|
| 477 |
+ if n == 0 && t.nextID > 1 {
|
|
| 478 |
+ n = t.nextID - 2 |
|
| 479 |
+ } |
|
| 480 |
+ m := t.goAwayID + 2 |
|
| 481 |
+ if m == 2 {
|
|
| 482 |
+ m = 1 |
|
| 483 |
+ } |
|
| 484 |
+ for i := m; i <= n; i += 2 {
|
|
| 485 |
+ if s, ok := t.activeStreams[i]; ok {
|
|
| 486 |
+ close(s.goAway) |
|
| 487 |
+ } |
|
| 488 |
+ } |
|
| 489 |
+ default: |
|
| 490 |
+ } |
|
| 491 |
+ if t.state == draining {
|
|
| 492 |
+ t.mu.Unlock() |
|
| 493 |
+ return nil |
|
| 494 |
+ } |
|
| 495 |
+ t.state = draining |
|
| 496 |
+ active := len(t.activeStreams) |
|
| 497 |
+ t.mu.Unlock() |
|
| 498 |
+ if active == 0 {
|
|
| 499 |
+ return t.Close() |
|
| 500 |
+ } |
|
| 501 |
+ return nil |
|
| 502 |
+} |
|
| 503 |
+ |
|
| 460 | 504 |
// Write formats the data into HTTP2 data frame(s) and sends it out. The caller |
| 461 | 505 |
// should proceed only if Write returns nil. |
| 462 | 506 |
// TODO(zhaoq): opts.Delay is ignored in this implementation. Support it later |
| ... | ... |
@@ -469,15 +548,15 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error {
|
| 469 | 469 |
size := http2MaxFrameLen |
| 470 | 470 |
s.sendQuotaPool.add(0) |
| 471 | 471 |
// Wait until the stream has some quota to send the data. |
| 472 |
- sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) |
|
| 472 |
+ sq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, s.sendQuotaPool.acquire()) |
|
| 473 | 473 |
if err != nil {
|
| 474 | 474 |
return err |
| 475 | 475 |
} |
| 476 | 476 |
t.sendQuotaPool.add(0) |
| 477 | 477 |
// Wait until the transport has some quota to send the data. |
| 478 |
- tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) |
|
| 478 |
+ tq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.sendQuotaPool.acquire()) |
|
| 479 | 479 |
if err != nil {
|
| 480 |
- if _, ok := err.(StreamError); ok {
|
|
| 480 |
+ if _, ok := err.(StreamError); ok || err == io.EOF {
|
|
| 481 | 481 |
t.sendQuotaPool.cancel() |
| 482 | 482 |
} |
| 483 | 483 |
return err |
| ... | ... |
@@ -509,8 +588,8 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error {
|
| 509 | 509 |
// Indicate there is a writer who is about to write a data frame. |
| 510 | 510 |
t.framer.adjustNumWriters(1) |
| 511 | 511 |
// Got some quota. Try to acquire writing privilege on the transport. |
| 512 |
- if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 513 |
- if _, ok := err.(StreamError); ok {
|
|
| 512 |
+ if _, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.writableChan); err != nil {
|
|
| 513 |
+ if _, ok := err.(StreamError); ok || err == io.EOF {
|
|
| 514 | 514 |
// Return the connection quota back. |
| 515 | 515 |
t.sendQuotaPool.add(len(p)) |
| 516 | 516 |
} |
| ... | ... |
@@ -543,7 +622,7 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error {
|
| 543 | 543 |
// invoked. |
| 544 | 544 |
if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil {
|
| 545 | 545 |
t.notifyError(err) |
| 546 |
- return ConnectionErrorf("transport: %v", err)
|
|
| 546 |
+ return ConnectionErrorf(true, err, "transport: %v", err) |
|
| 547 | 547 |
} |
| 548 | 548 |
if t.framer.adjustNumWriters(-1) == 0 {
|
| 549 | 549 |
t.framer.flushWrite() |
| ... | ... |
@@ -558,11 +637,7 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error {
|
| 558 | 558 |
} |
| 559 | 559 |
s.mu.Lock() |
| 560 | 560 |
if s.state != streamDone {
|
| 561 |
- if s.state == streamReadDone {
|
|
| 562 |
- s.state = streamDone |
|
| 563 |
- } else {
|
|
| 564 |
- s.state = streamWriteDone |
|
| 565 |
- } |
|
| 561 |
+ s.state = streamWriteDone |
|
| 566 | 562 |
} |
| 567 | 563 |
s.mu.Unlock() |
| 568 | 564 |
return nil |
| ... | ... |
@@ -595,7 +670,7 @@ func (t *http2Client) updateWindow(s *Stream, n uint32) {
|
| 595 | 595 |
func (t *http2Client) handleData(f *http2.DataFrame) {
|
| 596 | 596 |
size := len(f.Data()) |
| 597 | 597 |
if err := t.fc.onData(uint32(size)); err != nil {
|
| 598 |
- t.notifyError(ConnectionErrorf("%v", err))
|
|
| 598 |
+ t.notifyError(ConnectionErrorf(true, err, "%v", err)) |
|
| 599 | 599 |
return |
| 600 | 600 |
} |
| 601 | 601 |
// Select the right stream to dispatch. |
| ... | ... |
@@ -620,6 +695,7 @@ func (t *http2Client) handleData(f *http2.DataFrame) {
|
| 620 | 620 |
s.state = streamDone |
| 621 | 621 |
s.statusCode = codes.Internal |
| 622 | 622 |
s.statusDesc = err.Error() |
| 623 |
+ close(s.done) |
|
| 623 | 624 |
s.mu.Unlock() |
| 624 | 625 |
s.write(recvMsg{err: io.EOF})
|
| 625 | 626 |
t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl})
|
| ... | ... |
@@ -637,13 +713,14 @@ func (t *http2Client) handleData(f *http2.DataFrame) {
|
| 637 | 637 |
// the read direction is closed, and set the status appropriately. |
| 638 | 638 |
if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
|
| 639 | 639 |
s.mu.Lock() |
| 640 |
- if s.state == streamWriteDone {
|
|
| 641 |
- s.state = streamDone |
|
| 642 |
- } else {
|
|
| 643 |
- s.state = streamReadDone |
|
| 640 |
+ if s.state == streamDone {
|
|
| 641 |
+ s.mu.Unlock() |
|
| 642 |
+ return |
|
| 644 | 643 |
} |
| 644 |
+ s.state = streamDone |
|
| 645 | 645 |
s.statusCode = codes.Internal |
| 646 | 646 |
s.statusDesc = "server closed the stream without sending trailers" |
| 647 |
+ close(s.done) |
|
| 647 | 648 |
s.mu.Unlock() |
| 648 | 649 |
s.write(recvMsg{err: io.EOF})
|
| 649 | 650 |
} |
| ... | ... |
@@ -669,6 +746,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
|
| 669 | 669 |
grpclog.Println("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error ", f.ErrCode)
|
| 670 | 670 |
s.statusCode = codes.Unknown |
| 671 | 671 |
} |
| 672 |
+ s.statusDesc = fmt.Sprintf("stream terminated by RST_STREAM with error code: %d", f.ErrCode)
|
|
| 673 |
+ close(s.done) |
|
| 672 | 674 |
s.mu.Unlock() |
| 673 | 675 |
s.write(recvMsg{err: io.EOF})
|
| 674 | 676 |
} |
| ... | ... |
@@ -693,7 +772,32 @@ func (t *http2Client) handlePing(f *http2.PingFrame) {
|
| 693 | 693 |
} |
| 694 | 694 |
|
| 695 | 695 |
func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
| 696 |
- // TODO(zhaoq): GoAwayFrame handler to be implemented |
|
| 696 |
+ t.mu.Lock() |
|
| 697 |
+ if t.state == reachable || t.state == draining {
|
|
| 698 |
+ if f.LastStreamID > 0 && f.LastStreamID%2 != 1 {
|
|
| 699 |
+ t.mu.Unlock() |
|
| 700 |
+ t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: stream ID %d is even", f.LastStreamID)) |
|
| 701 |
+ return |
|
| 702 |
+ } |
|
| 703 |
+ select {
|
|
| 704 |
+ case <-t.goAway: |
|
| 705 |
+ id := t.goAwayID |
|
| 706 |
+ // t.goAway has been closed (i.e.,multiple GoAways). |
|
| 707 |
+ if id < f.LastStreamID {
|
|
| 708 |
+ t.mu.Unlock() |
|
| 709 |
+ t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: previously recv GOAWAY frame with LastStramID %d, currently recv %d", id, f.LastStreamID)) |
|
| 710 |
+ return |
|
| 711 |
+ } |
|
| 712 |
+ t.prevGoAwayID = id |
|
| 713 |
+ t.goAwayID = f.LastStreamID |
|
| 714 |
+ t.mu.Unlock() |
|
| 715 |
+ return |
|
| 716 |
+ default: |
|
| 717 |
+ } |
|
| 718 |
+ t.goAwayID = f.LastStreamID |
|
| 719 |
+ close(t.goAway) |
|
| 720 |
+ } |
|
| 721 |
+ t.mu.Unlock() |
|
| 697 | 722 |
} |
| 698 | 723 |
|
| 699 | 724 |
func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
|
| ... | ... |
@@ -745,11 +849,11 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
|
| 745 | 745 |
if len(state.mdata) > 0 {
|
| 746 | 746 |
s.trailer = state.mdata |
| 747 | 747 |
} |
| 748 |
- s.state = streamDone |
|
| 749 | 748 |
s.statusCode = state.statusCode |
| 750 | 749 |
s.statusDesc = state.statusDesc |
| 750 |
+ close(s.done) |
|
| 751 |
+ s.state = streamDone |
|
| 751 | 752 |
s.mu.Unlock() |
| 752 |
- |
|
| 753 | 753 |
s.write(recvMsg{err: io.EOF})
|
| 754 | 754 |
} |
| 755 | 755 |
|
| ... | ... |
@@ -902,13 +1006,22 @@ func (t *http2Client) Error() <-chan struct{} {
|
| 902 | 902 |
return t.errorChan |
| 903 | 903 |
} |
| 904 | 904 |
|
| 905 |
+func (t *http2Client) GoAway() <-chan struct{} {
|
|
| 906 |
+ return t.goAway |
|
| 907 |
+} |
|
| 908 |
+ |
|
| 905 | 909 |
func (t *http2Client) notifyError(err error) {
|
| 906 | 910 |
t.mu.Lock() |
| 907 |
- defer t.mu.Unlock() |
|
| 908 | 911 |
// make sure t.errorChan is closed only once. |
| 912 |
+ if t.state == draining {
|
|
| 913 |
+ t.mu.Unlock() |
|
| 914 |
+ t.Close() |
|
| 915 |
+ return |
|
| 916 |
+ } |
|
| 909 | 917 |
if t.state == reachable {
|
| 910 | 918 |
t.state = unreachable |
| 911 | 919 |
close(t.errorChan) |
| 912 | 920 |
grpclog.Printf("transport: http2Client.notifyError got notified that the client transport was broken %v.", err)
|
| 913 | 921 |
} |
| 922 |
+ t.mu.Unlock() |
|
| 914 | 923 |
} |
| ... | ... |
@@ -100,18 +100,23 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI |
| 100 | 100 |
if maxStreams == 0 {
|
| 101 | 101 |
maxStreams = math.MaxUint32 |
| 102 | 102 |
} else {
|
| 103 |
- settings = append(settings, http2.Setting{http2.SettingMaxConcurrentStreams, maxStreams})
|
|
| 103 |
+ settings = append(settings, http2.Setting{
|
|
| 104 |
+ ID: http2.SettingMaxConcurrentStreams, |
|
| 105 |
+ Val: maxStreams, |
|
| 106 |
+ }) |
|
| 104 | 107 |
} |
| 105 | 108 |
if initialWindowSize != defaultWindowSize {
|
| 106 |
- settings = append(settings, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)})
|
|
| 109 |
+ settings = append(settings, http2.Setting{
|
|
| 110 |
+ ID: http2.SettingInitialWindowSize, |
|
| 111 |
+ Val: uint32(initialWindowSize)}) |
|
| 107 | 112 |
} |
| 108 | 113 |
if err := framer.writeSettings(true, settings...); err != nil {
|
| 109 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 114 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 110 | 115 |
} |
| 111 | 116 |
// Adjust the connection flow control window if needed. |
| 112 | 117 |
if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 {
|
| 113 | 118 |
if err := framer.writeWindowUpdate(true, 0, delta); err != nil {
|
| 114 |
- return nil, ConnectionErrorf("transport: %v", err)
|
|
| 119 |
+ return nil, ConnectionErrorf(true, err, "transport: %v", err) |
|
| 115 | 120 |
} |
| 116 | 121 |
} |
| 117 | 122 |
var buf bytes.Buffer |
| ... | ... |
@@ -137,7 +142,7 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
// operateHeader takes action on the decoded headers. |
| 140 |
-func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) {
|
|
| 140 |
+func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) (close bool) {
|
|
| 141 | 141 |
buf := newRecvBuffer() |
| 142 | 142 |
s := &Stream{
|
| 143 | 143 |
id: frame.Header().StreamID, |
| ... | ... |
@@ -200,6 +205,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( |
| 200 | 200 |
t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream})
|
| 201 | 201 |
return |
| 202 | 202 |
} |
| 203 |
+ if s.id%2 != 1 || s.id <= t.maxStreamID {
|
|
| 204 |
+ t.mu.Unlock() |
|
| 205 |
+ // illegal gRPC stream id. |
|
| 206 |
+ grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", s.id)
|
|
| 207 |
+ return true |
|
| 208 |
+ } |
|
| 209 |
+ t.maxStreamID = s.id |
|
| 203 | 210 |
s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) |
| 204 | 211 |
t.activeStreams[s.id] = s |
| 205 | 212 |
t.mu.Unlock() |
| ... | ... |
@@ -207,6 +219,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( |
| 207 | 207 |
t.updateWindow(s, uint32(n)) |
| 208 | 208 |
} |
| 209 | 209 |
handle(s) |
| 210 |
+ return |
|
| 210 | 211 |
} |
| 211 | 212 |
|
| 212 | 213 |
// HandleStreams receives incoming streams using the given handler. This is |
| ... | ... |
@@ -226,6 +239,10 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
|
| 226 | 226 |
} |
| 227 | 227 |
|
| 228 | 228 |
frame, err := t.framer.readFrame() |
| 229 |
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
|
|
| 230 |
+ t.Close() |
|
| 231 |
+ return |
|
| 232 |
+ } |
|
| 229 | 233 |
if err != nil {
|
| 230 | 234 |
grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err)
|
| 231 | 235 |
t.Close() |
| ... | ... |
@@ -252,20 +269,20 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
|
| 252 | 252 |
t.controlBuf.put(&resetStream{se.StreamID, se.Code})
|
| 253 | 253 |
continue |
| 254 | 254 |
} |
| 255 |
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
|
|
| 256 |
+ t.Close() |
|
| 257 |
+ return |
|
| 258 |
+ } |
|
| 259 |
+ grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err)
|
|
| 255 | 260 |
t.Close() |
| 256 | 261 |
return |
| 257 | 262 |
} |
| 258 | 263 |
switch frame := frame.(type) {
|
| 259 | 264 |
case *http2.MetaHeadersFrame: |
| 260 |
- id := frame.Header().StreamID |
|
| 261 |
- if id%2 != 1 || id <= t.maxStreamID {
|
|
| 262 |
- // illegal gRPC stream id. |
|
| 263 |
- grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", id)
|
|
| 265 |
+ if t.operateHeaders(frame, handle) {
|
|
| 264 | 266 |
t.Close() |
| 265 | 267 |
break |
| 266 | 268 |
} |
| 267 |
- t.maxStreamID = id |
|
| 268 |
- t.operateHeaders(frame, handle) |
|
| 269 | 269 |
case *http2.DataFrame: |
| 270 | 270 |
t.handleData(frame) |
| 271 | 271 |
case *http2.RSTStreamFrame: |
| ... | ... |
@@ -277,7 +294,7 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
|
| 277 | 277 |
case *http2.WindowUpdateFrame: |
| 278 | 278 |
t.handleWindowUpdate(frame) |
| 279 | 279 |
case *http2.GoAwayFrame: |
| 280 |
- break |
|
| 280 |
+ // TODO: Handle GoAway from the client appropriately. |
|
| 281 | 281 |
default: |
| 282 | 282 |
grpclog.Printf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame)
|
| 283 | 283 |
} |
| ... | ... |
@@ -359,11 +376,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
|
| 359 | 359 |
// Received the end of stream from the client. |
| 360 | 360 |
s.mu.Lock() |
| 361 | 361 |
if s.state != streamDone {
|
| 362 |
- if s.state == streamWriteDone {
|
|
| 363 |
- s.state = streamDone |
|
| 364 |
- } else {
|
|
| 365 |
- s.state = streamReadDone |
|
| 366 |
- } |
|
| 362 |
+ s.state = streamReadDone |
|
| 367 | 363 |
} |
| 368 | 364 |
s.mu.Unlock() |
| 369 | 365 |
s.write(recvMsg{err: io.EOF})
|
| ... | ... |
@@ -435,7 +448,7 @@ func (t *http2Server) writeHeaders(s *Stream, b *bytes.Buffer, endStream bool) e |
| 435 | 435 |
} |
| 436 | 436 |
if err != nil {
|
| 437 | 437 |
t.Close() |
| 438 |
- return ConnectionErrorf("transport: %v", err)
|
|
| 438 |
+ return ConnectionErrorf(true, err, "transport: %v", err) |
|
| 439 | 439 |
} |
| 440 | 440 |
} |
| 441 | 441 |
return nil |
| ... | ... |
@@ -450,7 +463,7 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
|
| 450 | 450 |
} |
| 451 | 451 |
s.headerOk = true |
| 452 | 452 |
s.mu.Unlock() |
| 453 |
- if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 453 |
+ if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
|
|
| 454 | 454 |
return err |
| 455 | 455 |
} |
| 456 | 456 |
t.hBuf.Reset() |
| ... | ... |
@@ -460,6 +473,10 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
|
| 460 | 460 |
t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress})
|
| 461 | 461 |
} |
| 462 | 462 |
for k, v := range md {
|
| 463 |
+ if isReservedHeader(k) {
|
|
| 464 |
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent. |
|
| 465 |
+ continue |
|
| 466 |
+ } |
|
| 463 | 467 |
for _, entry := range v {
|
| 464 | 468 |
t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry})
|
| 465 | 469 |
} |
| ... | ... |
@@ -486,7 +503,7 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s |
| 486 | 486 |
headersSent = true |
| 487 | 487 |
} |
| 488 | 488 |
s.mu.Unlock() |
| 489 |
- if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 489 |
+ if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
|
|
| 490 | 490 |
return err |
| 491 | 491 |
} |
| 492 | 492 |
t.hBuf.Reset() |
| ... | ... |
@@ -499,9 +516,13 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s |
| 499 | 499 |
Name: "grpc-status", |
| 500 | 500 |
Value: strconv.Itoa(int(statusCode)), |
| 501 | 501 |
}) |
| 502 |
- t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: statusDesc})
|
|
| 502 |
+ t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(statusDesc)})
|
|
| 503 | 503 |
// Attach the trailer metadata. |
| 504 | 504 |
for k, v := range s.trailer {
|
| 505 |
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent. |
|
| 506 |
+ if isReservedHeader(k) {
|
|
| 507 |
+ continue |
|
| 508 |
+ } |
|
| 505 | 509 |
for _, entry := range v {
|
| 506 | 510 |
t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry})
|
| 507 | 511 |
} |
| ... | ... |
@@ -531,7 +552,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
|
| 531 | 531 |
} |
| 532 | 532 |
s.mu.Unlock() |
| 533 | 533 |
if writeHeaderFrame {
|
| 534 |
- if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 534 |
+ if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
|
|
| 535 | 535 |
return err |
| 536 | 536 |
} |
| 537 | 537 |
t.hBuf.Reset() |
| ... | ... |
@@ -547,7 +568,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
|
| 547 | 547 |
} |
| 548 | 548 |
if err := t.framer.writeHeaders(false, p); err != nil {
|
| 549 | 549 |
t.Close() |
| 550 |
- return ConnectionErrorf("transport: %v", err)
|
|
| 550 |
+ return ConnectionErrorf(true, err, "transport: %v", err) |
|
| 551 | 551 |
} |
| 552 | 552 |
t.writableChan <- 0 |
| 553 | 553 |
} |
| ... | ... |
@@ -559,13 +580,13 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
|
| 559 | 559 |
size := http2MaxFrameLen |
| 560 | 560 |
s.sendQuotaPool.add(0) |
| 561 | 561 |
// Wait until the stream has some quota to send the data. |
| 562 |
- sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) |
|
| 562 |
+ sq, err := wait(s.ctx, nil, nil, t.shutdownChan, s.sendQuotaPool.acquire()) |
|
| 563 | 563 |
if err != nil {
|
| 564 | 564 |
return err |
| 565 | 565 |
} |
| 566 | 566 |
t.sendQuotaPool.add(0) |
| 567 | 567 |
// Wait until the transport has some quota to send the data. |
| 568 |
- tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) |
|
| 568 |
+ tq, err := wait(s.ctx, nil, nil, t.shutdownChan, t.sendQuotaPool.acquire()) |
|
| 569 | 569 |
if err != nil {
|
| 570 | 570 |
if _, ok := err.(StreamError); ok {
|
| 571 | 571 |
t.sendQuotaPool.cancel() |
| ... | ... |
@@ -591,7 +612,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
|
| 591 | 591 |
t.framer.adjustNumWriters(1) |
| 592 | 592 |
// Got some quota. Try to acquire writing privilege on the |
| 593 | 593 |
// transport. |
| 594 |
- if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil {
|
|
| 594 |
+ if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
|
|
| 595 | 595 |
if _, ok := err.(StreamError); ok {
|
| 596 | 596 |
// Return the connection quota back. |
| 597 | 597 |
t.sendQuotaPool.add(ps) |
| ... | ... |
@@ -621,7 +642,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error {
|
| 621 | 621 |
} |
| 622 | 622 |
if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil {
|
| 623 | 623 |
t.Close() |
| 624 |
- return ConnectionErrorf("transport: %v", err)
|
|
| 624 |
+ return ConnectionErrorf(true, err, "transport: %v", err) |
|
| 625 | 625 |
} |
| 626 | 626 |
if t.framer.adjustNumWriters(-1) == 0 {
|
| 627 | 627 |
t.framer.flushWrite() |
| ... | ... |
@@ -666,6 +687,17 @@ func (t *http2Server) controller() {
|
| 666 | 666 |
} |
| 667 | 667 |
case *resetStream: |
| 668 | 668 |
t.framer.writeRSTStream(true, i.streamID, i.code) |
| 669 |
+ case *goAway: |
|
| 670 |
+ t.mu.Lock() |
|
| 671 |
+ if t.state == closing {
|
|
| 672 |
+ t.mu.Unlock() |
|
| 673 |
+ // The transport is closing. |
|
| 674 |
+ return |
|
| 675 |
+ } |
|
| 676 |
+ sid := t.maxStreamID |
|
| 677 |
+ t.state = draining |
|
| 678 |
+ t.mu.Unlock() |
|
| 679 |
+ t.framer.writeGoAway(true, sid, http2.ErrCodeNo, nil) |
|
| 669 | 680 |
case *flushIO: |
| 670 | 681 |
t.framer.flushWrite() |
| 671 | 682 |
case *ping: |
| ... | ... |
@@ -711,6 +743,9 @@ func (t *http2Server) Close() (err error) {
|
| 711 | 711 |
func (t *http2Server) closeStream(s *Stream) {
|
| 712 | 712 |
t.mu.Lock() |
| 713 | 713 |
delete(t.activeStreams, s.id) |
| 714 |
+ if t.state == draining && len(t.activeStreams) == 0 {
|
|
| 715 |
+ defer t.Close() |
|
| 716 |
+ } |
|
| 714 | 717 |
t.mu.Unlock() |
| 715 | 718 |
// In case stream sending and receiving are invoked in separate |
| 716 | 719 |
// goroutines (e.g., bi-directional streaming), cancel needs to be |
| ... | ... |
@@ -733,3 +768,7 @@ func (t *http2Server) closeStream(s *Stream) {
|
| 733 | 733 |
func (t *http2Server) RemoteAddr() net.Addr {
|
| 734 | 734 |
return t.conn.RemoteAddr() |
| 735 | 735 |
} |
| 736 |
+ |
|
| 737 |
+func (t *http2Server) Drain() {
|
|
| 738 |
+ t.controlBuf.put(&goAway{})
|
|
| 739 |
+} |
| ... | ... |
@@ -35,6 +35,7 @@ package transport |
| 35 | 35 |
|
| 36 | 36 |
import ( |
| 37 | 37 |
"bufio" |
| 38 |
+ "bytes" |
|
| 38 | 39 |
"fmt" |
| 39 | 40 |
"io" |
| 40 | 41 |
"net" |
| ... | ... |
@@ -52,7 +53,7 @@ import ( |
| 52 | 52 |
|
| 53 | 53 |
const ( |
| 54 | 54 |
// The primary user agent |
| 55 |
- primaryUA = "grpc-go/0.11" |
|
| 55 |
+ primaryUA = "grpc-go/1.0" |
|
| 56 | 56 |
// http2MaxFrameLen specifies the max length of a HTTP2 frame. |
| 57 | 57 |
http2MaxFrameLen = 16384 // 16KB frame |
| 58 | 58 |
// http://http2.github.io/http2-spec/#SettingValues |
| ... | ... |
@@ -127,16 +128,40 @@ func isReservedHeader(hdr string) bool {
|
| 127 | 127 |
} |
| 128 | 128 |
} |
| 129 | 129 |
|
| 130 |
+// isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders |
|
| 131 |
+// that should be propagated into metadata visible to users. |
|
| 132 |
+func isWhitelistedPseudoHeader(hdr string) bool {
|
|
| 133 |
+ switch hdr {
|
|
| 134 |
+ case ":authority": |
|
| 135 |
+ return true |
|
| 136 |
+ default: |
|
| 137 |
+ return false |
|
| 138 |
+ } |
|
| 139 |
+} |
|
| 140 |
+ |
|
| 130 | 141 |
func (d *decodeState) setErr(err error) {
|
| 131 | 142 |
if d.err == nil {
|
| 132 | 143 |
d.err = err |
| 133 | 144 |
} |
| 134 | 145 |
} |
| 135 | 146 |
|
| 147 |
+func validContentType(t string) bool {
|
|
| 148 |
+ e := "application/grpc" |
|
| 149 |
+ if !strings.HasPrefix(t, e) {
|
|
| 150 |
+ return false |
|
| 151 |
+ } |
|
| 152 |
+ // Support variations on the content-type |
|
| 153 |
+ // (e.g. "application/grpc+blah", "application/grpc;blah"). |
|
| 154 |
+ if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' {
|
|
| 155 |
+ return false |
|
| 156 |
+ } |
|
| 157 |
+ return true |
|
| 158 |
+} |
|
| 159 |
+ |
|
| 136 | 160 |
func (d *decodeState) processHeaderField(f hpack.HeaderField) {
|
| 137 | 161 |
switch f.Name {
|
| 138 | 162 |
case "content-type": |
| 139 |
- if !strings.Contains(f.Value, "application/grpc") {
|
|
| 163 |
+ if !validContentType(f.Value) {
|
|
| 140 | 164 |
d.setErr(StreamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value)) |
| 141 | 165 |
return |
| 142 | 166 |
} |
| ... | ... |
@@ -150,11 +175,11 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) {
|
| 150 | 150 |
} |
| 151 | 151 |
d.statusCode = codes.Code(code) |
| 152 | 152 |
case "grpc-message": |
| 153 |
- d.statusDesc = f.Value |
|
| 153 |
+ d.statusDesc = decodeGrpcMessage(f.Value) |
|
| 154 | 154 |
case "grpc-timeout": |
| 155 | 155 |
d.timeoutSet = true |
| 156 | 156 |
var err error |
| 157 |
- d.timeout, err = timeoutDecode(f.Value) |
|
| 157 |
+ d.timeout, err = decodeTimeout(f.Value) |
|
| 158 | 158 |
if err != nil {
|
| 159 | 159 |
d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err)) |
| 160 | 160 |
return |
| ... | ... |
@@ -162,7 +187,7 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) {
|
| 162 | 162 |
case ":path": |
| 163 | 163 |
d.method = f.Value |
| 164 | 164 |
default: |
| 165 |
- if !isReservedHeader(f.Name) {
|
|
| 165 |
+ if !isReservedHeader(f.Name) || isWhitelistedPseudoHeader(f.Name) {
|
|
| 166 | 166 |
if f.Name == "user-agent" {
|
| 167 | 167 |
i := strings.LastIndex(f.Value, " ") |
| 168 | 168 |
if i == -1 {
|
| ... | ... |
@@ -227,7 +252,7 @@ func div(d, r time.Duration) int64 {
|
| 227 | 227 |
} |
| 228 | 228 |
|
| 229 | 229 |
// TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it. |
| 230 |
-func timeoutEncode(t time.Duration) string {
|
|
| 230 |
+func encodeTimeout(t time.Duration) string {
|
|
| 231 | 231 |
if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
|
| 232 | 232 |
return strconv.FormatInt(d, 10) + "n" |
| 233 | 233 |
} |
| ... | ... |
@@ -247,7 +272,7 @@ func timeoutEncode(t time.Duration) string {
|
| 247 | 247 |
return strconv.FormatInt(div(t, time.Hour), 10) + "H" |
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 |
-func timeoutDecode(s string) (time.Duration, error) {
|
|
| 250 |
+func decodeTimeout(s string) (time.Duration, error) {
|
|
| 251 | 251 |
size := len(s) |
| 252 | 252 |
if size < 2 {
|
| 253 | 253 |
return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
|
| ... | ... |
@@ -264,6 +289,80 @@ func timeoutDecode(s string) (time.Duration, error) {
|
| 264 | 264 |
return d * time.Duration(t), nil |
| 265 | 265 |
} |
| 266 | 266 |
|
| 267 |
+const ( |
|
| 268 |
+ spaceByte = ' ' |
|
| 269 |
+ tildaByte = '~' |
|
| 270 |
+ percentByte = '%' |
|
| 271 |
+) |
|
| 272 |
+ |
|
| 273 |
+// encodeGrpcMessage is used to encode status code in header field |
|
| 274 |
+// "grpc-message". |
|
| 275 |
+// It checks to see if each individual byte in msg is an |
|
| 276 |
+// allowable byte, and then either percent encoding or passing it through. |
|
| 277 |
+// When percent encoding, the byte is converted into hexadecimal notation |
|
| 278 |
+// with a '%' prepended. |
|
| 279 |
+func encodeGrpcMessage(msg string) string {
|
|
| 280 |
+ if msg == "" {
|
|
| 281 |
+ return "" |
|
| 282 |
+ } |
|
| 283 |
+ lenMsg := len(msg) |
|
| 284 |
+ for i := 0; i < lenMsg; i++ {
|
|
| 285 |
+ c := msg[i] |
|
| 286 |
+ if !(c >= spaceByte && c < tildaByte && c != percentByte) {
|
|
| 287 |
+ return encodeGrpcMessageUnchecked(msg) |
|
| 288 |
+ } |
|
| 289 |
+ } |
|
| 290 |
+ return msg |
|
| 291 |
+} |
|
| 292 |
+ |
|
| 293 |
+func encodeGrpcMessageUnchecked(msg string) string {
|
|
| 294 |
+ var buf bytes.Buffer |
|
| 295 |
+ lenMsg := len(msg) |
|
| 296 |
+ for i := 0; i < lenMsg; i++ {
|
|
| 297 |
+ c := msg[i] |
|
| 298 |
+ if c >= spaceByte && c < tildaByte && c != percentByte {
|
|
| 299 |
+ buf.WriteByte(c) |
|
| 300 |
+ } else {
|
|
| 301 |
+ buf.WriteString(fmt.Sprintf("%%%02X", c))
|
|
| 302 |
+ } |
|
| 303 |
+ } |
|
| 304 |
+ return buf.String() |
|
| 305 |
+} |
|
| 306 |
+ |
|
| 307 |
+// decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage. |
|
| 308 |
+func decodeGrpcMessage(msg string) string {
|
|
| 309 |
+ if msg == "" {
|
|
| 310 |
+ return "" |
|
| 311 |
+ } |
|
| 312 |
+ lenMsg := len(msg) |
|
| 313 |
+ for i := 0; i < lenMsg; i++ {
|
|
| 314 |
+ if msg[i] == percentByte && i+2 < lenMsg {
|
|
| 315 |
+ return decodeGrpcMessageUnchecked(msg) |
|
| 316 |
+ } |
|
| 317 |
+ } |
|
| 318 |
+ return msg |
|
| 319 |
+} |
|
| 320 |
+ |
|
| 321 |
+func decodeGrpcMessageUnchecked(msg string) string {
|
|
| 322 |
+ var buf bytes.Buffer |
|
| 323 |
+ lenMsg := len(msg) |
|
| 324 |
+ for i := 0; i < lenMsg; i++ {
|
|
| 325 |
+ c := msg[i] |
|
| 326 |
+ if c == percentByte && i+2 < lenMsg {
|
|
| 327 |
+ parsed, err := strconv.ParseInt(msg[i+1:i+3], 16, 8) |
|
| 328 |
+ if err != nil {
|
|
| 329 |
+ buf.WriteByte(c) |
|
| 330 |
+ } else {
|
|
| 331 |
+ buf.WriteByte(byte(parsed)) |
|
| 332 |
+ i += 2 |
|
| 333 |
+ } |
|
| 334 |
+ } else {
|
|
| 335 |
+ buf.WriteByte(c) |
|
| 336 |
+ } |
|
| 337 |
+ } |
|
| 338 |
+ return buf.String() |
|
| 339 |
+} |
|
| 340 |
+ |
|
| 267 | 341 |
type framer struct {
|
| 268 | 342 |
numWriters int32 |
| 269 | 343 |
reader io.Reader |
| 270 | 344 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,51 @@ |
| 0 |
+// +build !go1.6 |
|
| 1 |
+ |
|
| 2 |
+/* |
|
| 3 |
+ * Copyright 2016, Google Inc. |
|
| 4 |
+ * All rights reserved. |
|
| 5 |
+ * |
|
| 6 |
+ * Redistribution and use in source and binary forms, with or without |
|
| 7 |
+ * modification, are permitted provided that the following conditions are |
|
| 8 |
+ * met: |
|
| 9 |
+ * |
|
| 10 |
+ * * Redistributions of source code must retain the above copyright |
|
| 11 |
+ * notice, this list of conditions and the following disclaimer. |
|
| 12 |
+ * * Redistributions in binary form must reproduce the above |
|
| 13 |
+ * copyright notice, this list of conditions and the following disclaimer |
|
| 14 |
+ * in the documentation and/or other materials provided with the |
|
| 15 |
+ * distribution. |
|
| 16 |
+ * * Neither the name of Google Inc. nor the names of its |
|
| 17 |
+ * contributors may be used to endorse or promote products derived from |
|
| 18 |
+ * this software without specific prior written permission. |
|
| 19 |
+ * |
|
| 20 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 21 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 22 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 23 |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 24 |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 25 |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 26 |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 27 |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 28 |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 29 |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 30 |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 31 |
+ * |
|
| 32 |
+ */ |
|
| 33 |
+ |
|
| 34 |
+package transport |
|
| 35 |
+ |
|
| 36 |
+import ( |
|
| 37 |
+ "net" |
|
| 38 |
+ "time" |
|
| 39 |
+ |
|
| 40 |
+ "golang.org/x/net/context" |
|
| 41 |
+) |
|
| 42 |
+ |
|
| 43 |
+// dialContext connects to the address on the named network. |
|
| 44 |
+func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
|
| 45 |
+ var dialer net.Dialer |
|
| 46 |
+ if deadline, ok := ctx.Deadline(); ok {
|
|
| 47 |
+ dialer.Timeout = deadline.Sub(time.Now()) |
|
| 48 |
+ } |
|
| 49 |
+ return dialer.Dial(network, address) |
|
| 50 |
+} |
| ... | ... |
@@ -44,7 +44,6 @@ import ( |
| 44 | 44 |
"io" |
| 45 | 45 |
"net" |
| 46 | 46 |
"sync" |
| 47 |
- "time" |
|
| 48 | 47 |
|
| 49 | 48 |
"golang.org/x/net/context" |
| 50 | 49 |
"golang.org/x/net/trace" |
| ... | ... |
@@ -120,10 +119,11 @@ func (b *recvBuffer) get() <-chan item {
|
| 120 | 120 |
// recvBufferReader implements io.Reader interface to read the data from |
| 121 | 121 |
// recvBuffer. |
| 122 | 122 |
type recvBufferReader struct {
|
| 123 |
- ctx context.Context |
|
| 124 |
- recv *recvBuffer |
|
| 125 |
- last *bytes.Reader // Stores the remaining data in the previous calls. |
|
| 126 |
- err error |
|
| 123 |
+ ctx context.Context |
|
| 124 |
+ goAway chan struct{}
|
|
| 125 |
+ recv *recvBuffer |
|
| 126 |
+ last *bytes.Reader // Stores the remaining data in the previous calls. |
|
| 127 |
+ err error |
|
| 127 | 128 |
} |
| 128 | 129 |
|
| 129 | 130 |
// Read reads the next len(p) bytes from last. If last is drained, it tries to |
| ... | ... |
@@ -141,6 +141,8 @@ func (r *recvBufferReader) Read(p []byte) (n int, err error) {
|
| 141 | 141 |
select {
|
| 142 | 142 |
case <-r.ctx.Done(): |
| 143 | 143 |
return 0, ContextErr(r.ctx.Err()) |
| 144 |
+ case <-r.goAway: |
|
| 145 |
+ return 0, ErrStreamDrain |
|
| 144 | 146 |
case i := <-r.recv.get(): |
| 145 | 147 |
r.recv.load() |
| 146 | 148 |
m := i.(*recvMsg) |
| ... | ... |
@@ -158,7 +160,7 @@ const ( |
| 158 | 158 |
streamActive streamState = iota |
| 159 | 159 |
streamWriteDone // EndStream sent |
| 160 | 160 |
streamReadDone // EndStream received |
| 161 |
- streamDone // sendDone and recvDone or RSTStreamFrame is sent or received. |
|
| 161 |
+ streamDone // the entire stream is finished. |
|
| 162 | 162 |
) |
| 163 | 163 |
|
| 164 | 164 |
// Stream represents an RPC in the transport layer. |
| ... | ... |
@@ -169,6 +171,10 @@ type Stream struct {
|
| 169 | 169 |
// ctx is the associated context of the stream. |
| 170 | 170 |
ctx context.Context |
| 171 | 171 |
cancel context.CancelFunc |
| 172 |
+ // done is closed when the final status arrives. |
|
| 173 |
+ done chan struct{}
|
|
| 174 |
+ // goAway is closed when the server sent GoAways signal before this stream was initiated. |
|
| 175 |
+ goAway chan struct{}
|
|
| 172 | 176 |
// method records the associated RPC method of the stream. |
| 173 | 177 |
method string |
| 174 | 178 |
recvCompress string |
| ... | ... |
@@ -214,6 +220,18 @@ func (s *Stream) SetSendCompress(str string) {
|
| 214 | 214 |
s.sendCompress = str |
| 215 | 215 |
} |
| 216 | 216 |
|
| 217 |
+// Done returns a chanel which is closed when it receives the final status |
|
| 218 |
+// from the server. |
|
| 219 |
+func (s *Stream) Done() <-chan struct{} {
|
|
| 220 |
+ return s.done |
|
| 221 |
+} |
|
| 222 |
+ |
|
| 223 |
+// GoAway returns a channel which is closed when the server sent GoAways signal |
|
| 224 |
+// before this stream was initiated. |
|
| 225 |
+func (s *Stream) GoAway() <-chan struct{} {
|
|
| 226 |
+ return s.goAway |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 217 | 229 |
// Header acquires the key-value pairs of header metadata once it |
| 218 | 230 |
// is available. It blocks until i) the metadata is ready or ii) there is no |
| 219 | 231 |
// header metadata or iii) the stream is cancelled/expired. |
| ... | ... |
@@ -221,6 +239,8 @@ func (s *Stream) Header() (metadata.MD, error) {
|
| 221 | 221 |
select {
|
| 222 | 222 |
case <-s.ctx.Done(): |
| 223 | 223 |
return nil, ContextErr(s.ctx.Err()) |
| 224 |
+ case <-s.goAway: |
|
| 225 |
+ return nil, ErrStreamDrain |
|
| 224 | 226 |
case <-s.headerChan: |
| 225 | 227 |
return s.header.Copy(), nil |
| 226 | 228 |
} |
| ... | ... |
@@ -321,6 +341,7 @@ const ( |
| 321 | 321 |
reachable transportState = iota |
| 322 | 322 |
unreachable |
| 323 | 323 |
closing |
| 324 |
+ draining |
|
| 324 | 325 |
) |
| 325 | 326 |
|
| 326 | 327 |
// NewServerTransport creates a ServerTransport with conn or non-nil error |
| ... | ... |
@@ -334,17 +355,17 @@ type ConnectOptions struct {
|
| 334 | 334 |
// UserAgent is the application user agent. |
| 335 | 335 |
UserAgent string |
| 336 | 336 |
// Dialer specifies how to dial a network address. |
| 337 |
- Dialer func(string, time.Duration) (net.Conn, error) |
|
| 338 |
- // AuthOptions stores the credentials required to setup a client connection and/or issue RPCs. |
|
| 339 |
- AuthOptions []credentials.Credentials |
|
| 340 |
- // Timeout specifies the timeout for dialing a client connection. |
|
| 341 |
- Timeout time.Duration |
|
| 337 |
+ Dialer func(context.Context, string) (net.Conn, error) |
|
| 338 |
+ // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. |
|
| 339 |
+ PerRPCCredentials []credentials.PerRPCCredentials |
|
| 340 |
+ // TransportCredentials stores the Authenticator required to setup a client connection. |
|
| 341 |
+ TransportCredentials credentials.TransportCredentials |
|
| 342 | 342 |
} |
| 343 | 343 |
|
| 344 | 344 |
// NewClientTransport establishes the transport with the required ConnectOptions |
| 345 | 345 |
// and returns it to the caller. |
| 346 |
-func NewClientTransport(target string, opts *ConnectOptions) (ClientTransport, error) {
|
|
| 347 |
- return newHTTP2Client(target, opts) |
|
| 346 |
+func NewClientTransport(ctx context.Context, target string, opts ConnectOptions) (ClientTransport, error) {
|
|
| 347 |
+ return newHTTP2Client(ctx, target, opts) |
|
| 348 | 348 |
} |
| 349 | 349 |
|
| 350 | 350 |
// Options provides additional hints and information for message |
| ... | ... |
@@ -391,6 +412,10 @@ type ClientTransport interface {
|
| 391 | 391 |
// is called only once. |
| 392 | 392 |
Close() error |
| 393 | 393 |
|
| 394 |
+ // GracefulClose starts to tear down the transport. It stops accepting |
|
| 395 |
+ // new RPCs and wait the completion of the pending RPCs. |
|
| 396 |
+ GracefulClose() error |
|
| 397 |
+ |
|
| 394 | 398 |
// Write sends the data for the given stream. A nil stream indicates |
| 395 | 399 |
// the write is to be performed on the transport as a whole. |
| 396 | 400 |
Write(s *Stream, data []byte, opts *Options) error |
| ... | ... |
@@ -410,6 +435,11 @@ type ClientTransport interface {
|
| 410 | 410 |
// and create a new one) in error case. It should not return nil |
| 411 | 411 |
// once the transport is initiated. |
| 412 | 412 |
Error() <-chan struct{}
|
| 413 |
+ |
|
| 414 |
+ // GoAway returns a channel that is closed when ClientTranspor |
|
| 415 |
+ // receives the draining signal from the server (e.g., GOAWAY frame in |
|
| 416 |
+ // HTTP/2). |
|
| 417 |
+ GoAway() <-chan struct{}
|
|
| 413 | 418 |
} |
| 414 | 419 |
|
| 415 | 420 |
// ServerTransport is the common interface for all gRPC server-side transport |
| ... | ... |
@@ -441,6 +471,9 @@ type ServerTransport interface {
|
| 441 | 441 |
|
| 442 | 442 |
// RemoteAddr returns the remote network address. |
| 443 | 443 |
RemoteAddr() net.Addr |
| 444 |
+ |
|
| 445 |
+ // Drain notifies the client this ServerTransport stops accepting new RPCs. |
|
| 446 |
+ Drain() |
|
| 444 | 447 |
} |
| 445 | 448 |
|
| 446 | 449 |
// StreamErrorf creates an StreamError with the specified error code and description. |
| ... | ... |
@@ -452,9 +485,11 @@ func StreamErrorf(c codes.Code, format string, a ...interface{}) StreamError {
|
| 452 | 452 |
} |
| 453 | 453 |
|
| 454 | 454 |
// ConnectionErrorf creates an ConnectionError with the specified error description. |
| 455 |
-func ConnectionErrorf(format string, a ...interface{}) ConnectionError {
|
|
| 455 |
+func ConnectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError {
|
|
| 456 | 456 |
return ConnectionError{
|
| 457 | 457 |
Desc: fmt.Sprintf(format, a...), |
| 458 |
+ temp: temp, |
|
| 459 |
+ err: e, |
|
| 458 | 460 |
} |
| 459 | 461 |
} |
| 460 | 462 |
|
| ... | ... |
@@ -462,14 +497,36 @@ func ConnectionErrorf(format string, a ...interface{}) ConnectionError {
|
| 462 | 462 |
// entire connection and the retry of all the active streams. |
| 463 | 463 |
type ConnectionError struct {
|
| 464 | 464 |
Desc string |
| 465 |
+ temp bool |
|
| 466 |
+ err error |
|
| 465 | 467 |
} |
| 466 | 468 |
|
| 467 | 469 |
func (e ConnectionError) Error() string {
|
| 468 | 470 |
return fmt.Sprintf("connection error: desc = %q", e.Desc)
|
| 469 | 471 |
} |
| 470 | 472 |
|
| 471 |
-// Define some common ConnectionErrors. |
|
| 472 |
-var ErrConnClosing = ConnectionError{Desc: "transport is closing"}
|
|
| 473 |
+// Temporary indicates if this connection error is temporary or fatal. |
|
| 474 |
+func (e ConnectionError) Temporary() bool {
|
|
| 475 |
+ return e.temp |
|
| 476 |
+} |
|
| 477 |
+ |
|
| 478 |
+// Origin returns the original error of this connection error. |
|
| 479 |
+func (e ConnectionError) Origin() error {
|
|
| 480 |
+ // Never return nil error here. |
|
| 481 |
+ // If the original error is nil, return itself. |
|
| 482 |
+ if e.err == nil {
|
|
| 483 |
+ return e |
|
| 484 |
+ } |
|
| 485 |
+ return e.err |
|
| 486 |
+} |
|
| 487 |
+ |
|
| 488 |
+var ( |
|
| 489 |
+ // ErrConnClosing indicates that the transport is closing. |
|
| 490 |
+ ErrConnClosing = ConnectionError{Desc: "transport is closing", temp: true}
|
|
| 491 |
+ // ErrStreamDrain indicates that the stream is rejected by the server because |
|
| 492 |
+ // the server stops accepting new RPCs. |
|
| 493 |
+ ErrStreamDrain = StreamErrorf(codes.Unavailable, "the server stops accepting new RPCs") |
|
| 494 |
+) |
|
| 473 | 495 |
|
| 474 | 496 |
// StreamError is an error that only affects one stream within a connection. |
| 475 | 497 |
type StreamError struct {
|
| ... | ... |
@@ -494,12 +551,25 @@ func ContextErr(err error) StreamError {
|
| 494 | 494 |
|
| 495 | 495 |
// wait blocks until it can receive from ctx.Done, closing, or proceed. |
| 496 | 496 |
// If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. |
| 497 |
+// If it receives from done, it returns 0, io.EOF if ctx is not done; otherwise |
|
| 498 |
+// it return the StreamError for ctx.Err. |
|
| 499 |
+// If it receives from goAway, it returns 0, ErrStreamDrain. |
|
| 497 | 500 |
// If it receives from closing, it returns 0, ErrConnClosing. |
| 498 | 501 |
// If it receives from proceed, it returns the received integer, nil. |
| 499 |
-func wait(ctx context.Context, closing <-chan struct{}, proceed <-chan int) (int, error) {
|
|
| 502 |
+func wait(ctx context.Context, done, goAway, closing <-chan struct{}, proceed <-chan int) (int, error) {
|
|
| 500 | 503 |
select {
|
| 501 | 504 |
case <-ctx.Done(): |
| 502 | 505 |
return 0, ContextErr(ctx.Err()) |
| 506 |
+ case <-done: |
|
| 507 |
+ // User cancellation has precedence. |
|
| 508 |
+ select {
|
|
| 509 |
+ case <-ctx.Done(): |
|
| 510 |
+ return 0, ContextErr(ctx.Err()) |
|
| 511 |
+ default: |
|
| 512 |
+ } |
|
| 513 |
+ return 0, io.EOF |
|
| 514 |
+ case <-goAway: |
|
| 515 |
+ return 0, ErrStreamDrain |
|
| 503 | 516 |
case <-closing: |
| 504 | 517 |
return 0, ErrConnClosing |
| 505 | 518 |
case i := <-proceed: |