mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 23:22:26 -05:00 
			
		
		
		
	[feature] Support OTLP HTTP, drop Jaeger (#2184)
* [feature] Add http trace exporter, drop Jaeger Jaeger supports ingesting traces using the OpenTelemetry gRPC or HTTP methods. The Jaeger project has deprecated the old jaeger transport. * Add support for submitting traces over HTTP * Drop support for the old Jaeger protocol * Upgrade the trace libraries to v1.17 Fixes: #2176 Fixes: #2179
This commit is contained in:
		
					parent
					
						
							
								916c6d07ba
							
						
					
				
			
			
				commit
				
					
						14ef098099
					
				
			
		
					 199 changed files with 12972 additions and 18581 deletions
				
			
		|  | @ -18,21 +18,20 @@ request-id-header: "X-Request-Id" | |||
| # Default: false | ||||
| tracing-enabled: false | ||||
| 
 | ||||
| # String. Set the transport protocol for the tracing system. Can either be "grpc" for | ||||
| # OTLP gRPC or "jaeger" for jaeger based ingesters. | ||||
| # Options: ["grpc", "jaeger"] | ||||
| # String. Set the transport protocol for the tracing system. Can either be "grpc"  | ||||
| # for OTLP gRPC, or "http" for OTLP HTTP. | ||||
| # Options: ["grpc", "http"] | ||||
| # Default: "grpc" | ||||
| tracing-transport: "grpc" | ||||
| 
 | ||||
| # String. Endpoint of the trace ingester. When using the gRPC based transport, the | ||||
| # endpoint is usually a single address/port combination. For the jaeger transport it | ||||
| # should be a fully qualified URL. | ||||
| # OTLP gRPC or "jaeger" for jaeger based ingesters | ||||
| # Examples: ["localhost:4317", "http://localhost:14268/api/traces"] | ||||
| # String. Endpoint of the trace ingester. When using the gRPC or HTTP based  | ||||
| # transports, provide the endpoint as a single address/port combination without a  | ||||
| # protocol scheme. | ||||
| # Examples: ["localhost:4317"] | ||||
| # Default: "" | ||||
| tracing-endpoint: "" | ||||
| 
 | ||||
| # Bool. Disable HTTPS for the gRPC transport protocol. | ||||
| # Bool. Disable TLS for the gRPC and HTTP transport protocols. | ||||
| # Default: false | ||||
| tracing-insecure-transport: false | ||||
| ``` | ||||
|  |  | |||
|  | @ -724,21 +724,19 @@ request-id-header: "X-Request-Id" | |||
| # Default: false | ||||
| tracing-enabled: false | ||||
| 
 | ||||
| # String. Set the transport protocol for the tracing system. Can either be "grpc" for | ||||
| # OTLP gRPC or "jaeger" for jaeger based ingesters. | ||||
| # Options: ["grpc", "jaeger"] | ||||
| # String. Set the transport protocol for the tracing system. Can either be "grpc" | ||||
| # for OTLP gRPC, or "http" for OTLP HTTP. | ||||
| # Options: ["grpc", "http"] | ||||
| # Default: "grpc" | ||||
| tracing-transport: "grpc" | ||||
| 
 | ||||
| # String. Endpoint of the trace ingester. When using the gRPC based transport, the | ||||
| # endpoint is usually a single address/port combination. For the jaeger transport it | ||||
| # should be a fully qualified URL. | ||||
| # OTLP gRPC or "jaeger" for jaeger based ingesters | ||||
| # Examples: ["localhost:4317", "http://localhost:14268/api/traces"] | ||||
| # String. Endpoint of the trace ingester. When using the gRPC or HTTP based transports, | ||||
| # provide the endpoint as a single address/port combination without a protocol scheme. | ||||
| # Examples: ["localhost:4317"] | ||||
| # Default: "" | ||||
| tracing-endpoint: "" | ||||
| 
 | ||||
| # Bool. Disable HTTPS for the gRPC transport protocol. | ||||
| # Bool. Disable TLS for the gRPC and HTTP transport protocols. | ||||
| # Default: false | ||||
| tracing-insecure-transport: false | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										24
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -53,11 +53,11 @@ require ( | |||
| 	github.com/uptrace/bun/extra/bunotel v1.1.14 | ||||
| 	github.com/wagslane/go-password-validator v0.3.0 | ||||
| 	github.com/yuin/goldmark v1.5.6 | ||||
| 	go.opentelemetry.io/otel v1.16.0 | ||||
| 	go.opentelemetry.io/otel/exporters/jaeger v1.16.0 | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 | ||||
| 	go.opentelemetry.io/otel/sdk v1.16.0 | ||||
| 	go.opentelemetry.io/otel/trace v1.16.0 | ||||
| 	go.opentelemetry.io/otel v1.17.0 | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0 | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.17.0 | ||||
| 	go.opentelemetry.io/otel/sdk v1.17.0 | ||||
| 	go.opentelemetry.io/otel/trace v1.17.0 | ||||
| 	go.uber.org/automaxprocs v1.5.3 | ||||
| 	golang.org/x/crypto v0.12.0 | ||||
| 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 | ||||
|  | @ -118,7 +118,7 @@ require ( | |||
| 	github.com/gorilla/css v1.0.0 // indirect | ||||
| 	github.com/gorilla/securecookie v1.1.1 // indirect | ||||
| 	github.com/gorilla/sessions v1.2.1 // indirect | ||||
| 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect | ||||
| 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect | ||||
| 	github.com/hashicorp/hcl v1.0.0 // indirect | ||||
| 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||||
| 	github.com/jackc/chunkreader/v2 v2.0.1 // indirect | ||||
|  | @ -159,17 +159,17 @@ require ( | |||
| 	github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.1 // indirect | ||||
| 	github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect | ||||
| 	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect | ||||
| 	go.opentelemetry.io/otel/metric v1.16.0 // indirect | ||||
| 	go.opentelemetry.io/proto/otlp v0.19.0 // indirect | ||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 // indirect | ||||
| 	go.opentelemetry.io/otel/metric v1.17.0 // indirect | ||||
| 	go.opentelemetry.io/proto/otlp v1.0.0 // indirect | ||||
| 	golang.org/x/arch v0.3.0 // indirect | ||||
| 	golang.org/x/mod v0.10.0 // indirect | ||||
| 	golang.org/x/sys v0.11.0 // indirect | ||||
| 	golang.org/x/tools v0.6.0 // indirect | ||||
| 	google.golang.org/appengine v1.6.7 // indirect | ||||
| 	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect | ||||
| 	google.golang.org/grpc v1.55.0 // indirect | ||||
| 	google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect | ||||
| 	google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect | ||||
| 	google.golang.org/grpc v1.57.0 // indirect | ||||
| 	google.golang.org/protobuf v1.31.0 // indirect | ||||
| 	gopkg.in/ini.v1 v1.67.0 // indirect | ||||
| 	gopkg.in/yaml.v2 v2.4.0 // indirect | ||||
|  |  | |||
							
								
								
									
										82
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										82
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -91,14 +91,12 @@ github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW5 | |||
| github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0= | ||||
| github.com/KimMachineGun/automemlimit v0.3.0 h1:khgwM5ESVN85cE6Bq2ozMAAWDfrOEwQ51D/YlmThE04= | ||||
| github.com/KimMachineGun/automemlimit v0.3.0/go.mod h1:pJhTW/nWJMj6SnWSU2TEKSlCaM+1N5Mej+IfS/5/Ol0= | ||||
| github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= | ||||
| github.com/abema/go-mp4 v0.13.0 h1:gjEZLt7g0ePpYA5sUDrI2r8X+WuI8o+USkgG5wMgmkI= | ||||
| github.com/abema/go-mp4 v0.13.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws= | ||||
| github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= | ||||
| github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= | ||||
| github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= | ||||
| github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= | ||||
| github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= | ||||
| github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= | ||||
| github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= | ||||
| github.com/buckket/go-blurhash v1.1.0 h1:X5M6r0LIvwdvKiUtiNcRL2YlmOfMzYobI3VCKCZc9Do= | ||||
|  | @ -109,8 +107,6 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX | |||
| github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= | ||||
| github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= | ||||
| github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | ||||
| github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= | ||||
| github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= | ||||
|  | @ -123,11 +119,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk | |||
| github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= | ||||
| github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= | ||||
| github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= | ||||
| github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= | ||||
| github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= | ||||
| github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= | ||||
| github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= | ||||
| github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= | ||||
| github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= | ||||
| github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= | ||||
| github.com/containerd/cgroups/v3 v3.0.1 h1:4hfGvu8rfGIwVIDd+nLzn/B9ZXx4BcCjzt5ToenJRaE= | ||||
|  | @ -175,8 +166,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m | |||
| github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= | ||||
| github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= | ||||
| github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= | ||||
| github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= | ||||
|  | @ -191,7 +180,6 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q | |||
| github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= | ||||
| github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= | ||||
| github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= | ||||
| github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||||
| github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g= | ||||
| github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs= | ||||
| github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= | ||||
|  | @ -251,7 +239,6 @@ github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgR | |||
| github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= | ||||
| github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= | ||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||||
| github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= | ||||
| github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= | ||||
| github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||||
| github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||||
|  | @ -281,7 +268,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD | |||
| github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
| github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
| github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | ||||
| github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | ||||
| github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= | ||||
| github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | ||||
| github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | ||||
|  | @ -296,7 +282,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||
| github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= | ||||
| github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= | ||||
| github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | ||||
|  | @ -338,9 +323,8 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z | |||
| github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | ||||
| github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= | ||||
| github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= | ||||
| github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= | ||||
| github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= | ||||
| github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= | ||||
| github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= | ||||
| github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= | ||||
| github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= | ||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||
|  | @ -494,7 +478,6 @@ github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTep | |||
| github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= | ||||
| github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= | ||||
| github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= | ||||
| github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= | ||||
| github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||||
| github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= | ||||
| github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= | ||||
|  | @ -518,7 +501,6 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE | |||
| github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | ||||
| github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= | ||||
| github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | ||||
| github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= | ||||
| github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= | ||||
| github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= | ||||
| github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= | ||||
|  | @ -535,7 +517,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ | |||
| github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | ||||
| github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||
| github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= | ||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||
| github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
|  | @ -647,25 +628,22 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||
| go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= | ||||
| go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= | ||||
| go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= | ||||
| go.opentelemetry.io/otel/exporters/jaeger v1.16.0 h1:YhxxmXZ011C0aDZKoNw+juVWAmEfv/0W2XBOv9aHTaA= | ||||
| go.opentelemetry.io/otel/exporters/jaeger v1.16.0/go.mod h1:grYbBo/5afWlPpdPZYhyn78Bk04hnvxn2+hvxQhKIQM= | ||||
| go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= | ||||
| go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= | ||||
| go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= | ||||
| go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= | ||||
| go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= | ||||
| go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= | ||||
| go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= | ||||
| go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= | ||||
| go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= | ||||
| go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= | ||||
| go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= | ||||
| go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= | ||||
| go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 h1:U5GYackKpVKlPrd/5gKMlrTlP2dCESAAFU682VCpieY= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0/go.mod h1:aFsJfCEnLzEu9vRRAcUiB/cpRTbVsNdF3OHSPpdjxZQ= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0 h1:iGeIsSYwpYSvh5UGzWrJfTDJvPjrXtxl3GUppj6IXQU= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0/go.mod h1:1j3H3G1SBYpZFti6OI4P0uRQCW20MXkG5v4UWXppLLE= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.17.0 h1:kvWMtSUNVylLVrOE4WLUmBtgziYoCIYUNSpTYtMzVJI= | ||||
| go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.17.0/go.mod h1:SExUrRYIXhDgEKG4tkiQovd2HTaELiHUsuK08s5Nqx4= | ||||
| go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= | ||||
| go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= | ||||
| go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= | ||||
| go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= | ||||
| go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= | ||||
| go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= | ||||
| go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= | ||||
| go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= | ||||
| go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||||
| go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||||
| go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= | ||||
|  | @ -771,7 +749,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY | |||
| golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||||
| golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | ||||
|  | @ -787,7 +764,6 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ | |||
| golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= | ||||
| golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= | ||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
|  | @ -848,10 +824,8 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w | |||
| golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
|  | @ -875,7 +849,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 | |||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||
| golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||||
|  | @ -993,7 +966,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG | |||
| google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= | ||||
| google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | ||||
| google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= | ||||
|  | @ -1007,9 +979,11 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D | |||
| google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= | ||||
| google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= | ||||
| google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= | ||||
| google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= | ||||
| google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= | ||||
| google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= | ||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||
| google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= | ||||
| google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= | ||||
|  | @ -1023,15 +997,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji | |||
| google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= | ||||
| google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= | ||||
| google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= | ||||
| google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= | ||||
| google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= | ||||
| google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= | ||||
| google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= | ||||
| google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= | ||||
| google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= | ||||
| google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= | ||||
| google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= | ||||
| google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= | ||||
| google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= | ||||
| google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= | ||||
| google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||||
| google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||
| google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
|  | @ -1044,7 +1014,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj | |||
| google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | ||||
| google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | ||||
| google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||
| google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||
| google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||
| google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= | ||||
| google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||
|  | @ -1064,7 +1033,6 @@ gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg | |||
| gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= | ||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
|  |  | |||
|  | @ -131,9 +131,9 @@ type Configuration struct { | |||
| 	OIDCAdminGroups      []string `name:"oidc-admin-groups" usage:"Membership of one of the listed groups makes someone a GtS admin"` | ||||
| 
 | ||||
| 	TracingEnabled           bool   `name:"tracing-enabled" usage:"Enable OTLP Tracing"` | ||||
| 	TracingTransport         string `name:"tracing-transport" usage:"grpc or jaeger"` | ||||
| 	TracingEndpoint          string `name:"tracing-endpoint" usage:"Endpoint of your trace collector. Eg., 'localhost:4317' for gRPC, 'http://localhost:14268/api/traces' for jaeger"` | ||||
| 	TracingInsecureTransport bool   `name:"tracing-insecure" usage:"Disable HTTPS for the gRPC transport protocol"` | ||||
| 	TracingTransport         string `name:"tracing-transport" usage:"grpc or http"` | ||||
| 	TracingEndpoint          string `name:"tracing-endpoint" usage:"Endpoint of your trace collector. Eg., 'localhost:4317' for gRPC, 'localhost:4318' for http"` | ||||
| 	TracingInsecureTransport bool   `name:"tracing-insecure-transport" usage:"Disable TLS for the gRPC or HTTP transport protocol"` | ||||
| 
 | ||||
| 	SMTPHost               string `name:"smtp-host" usage:"Host of the smtp server. Eg., 'smtp.eu.mailgun.org'"` | ||||
| 	SMTPPort               int    `name:"smtp-port" usage:"Port of the smtp server. Eg., 587"` | ||||
|  |  | |||
|  | @ -1991,7 +1991,7 @@ func (st *ConfigState) SetTracingInsecureTransport(v bool) { | |||
| } | ||||
| 
 | ||||
| // TracingInsecureTransportFlag returns the flag name for the 'TracingInsecureTransport' field | ||||
| func TracingInsecureTransportFlag() string { return "tracing-insecure" } | ||||
| func TracingInsecureTransportFlag() string { return "tracing-insecure-transport" } | ||||
| 
 | ||||
| // GetTracingInsecureTransport safely fetches the value for global configuration 'TracingInsecureTransport' field | ||||
| func GetTracingInsecureTransport() bool { return global.GetTracingInsecureTransport() } | ||||
|  |  | |||
|  | @ -29,8 +29,8 @@ import ( | |||
| 	"github.com/uptrace/bun/extra/bunotel" | ||||
| 	"go.opentelemetry.io/otel" | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" | ||||
| 	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" | ||||
| 	"go.opentelemetry.io/otel/propagation" | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| 	"go.opentelemetry.io/otel/sdk/trace" | ||||
|  | @ -69,8 +69,14 @@ func Initialize() error { | |||
| 			return fmt.Errorf("building tracing exporter: %w", err) | ||||
| 		} | ||||
| 		tpo = trace.WithBatcher(exp) | ||||
| 	case "jaeger": | ||||
| 		exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(config.GetTracingEndpoint()))) | ||||
| 	case "http": | ||||
| 		opts := []otlptracehttp.Option{ | ||||
| 			otlptracehttp.WithEndpoint(config.GetTracingEndpoint()), | ||||
| 		} | ||||
| 		if insecure { | ||||
| 			opts = append(opts, otlptracehttp.WithInsecure()) | ||||
| 		} | ||||
| 		exp, err := otlptracehttp.New(context.Background(), opts...) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("building tracing exporter: %w", err) | ||||
| 		} | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ EXPECT=$(cat << "EOF" | |||
|     "tls-certificate-key": "", | ||||
|     "tracing-enabled": false, | ||||
|     "tracing-endpoint": "localhost:4317", | ||||
|     "tracing-insecure": false, | ||||
|     "tracing-insecure-transport": true, | ||||
|     "tracing-transport": "grpc", | ||||
|     "trusted-proxies": [ | ||||
|         "127.0.0.1/32", | ||||
|  | @ -242,6 +242,7 @@ GTS_SYSLOG_ENABLED=true \ | |||
| GTS_SYSLOG_PROTOCOL='udp' \ | ||||
| GTS_SYSLOG_ADDRESS='127.0.0.1:6969' \ | ||||
| GTS_TRACING_ENDPOINT='localhost:4317' \ | ||||
| GTS_TRACING_INSECURE_TRANSPORT=true \ | ||||
| GTS_ADVANCED_COOKIES_SAMESITE='strict' \ | ||||
| GTS_ADVANCED_RATE_LIMIT_EXCEPTIONS="192.0.2.0/24,127.0.0.1/32" \ | ||||
| GTS_ADVANCED_RATE_LIMIT_REQUESTS=6969 \ | ||||
|  |  | |||
							
								
								
									
										4
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,10 +1,10 @@ | |||
| //go:build gofuzz | ||||
| // +build gofuzz | ||||
| 
 | ||||
| package httprule | ||||
| 
 | ||||
| func Fuzz(data []byte) int { | ||||
| 	_, err := Parse(string(data)) | ||||
| 	if err != nil { | ||||
| 	if _, err := Parse(string(data)); err != nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return 0 | ||||
|  |  | |||
							
								
								
									
										30
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/parse.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/parse.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,7 @@ | |||
| package httprule | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
|  | @ -164,9 +165,9 @@ func (p *parser) segment() (segment, error) { | |||
| 
 | ||||
| 	v, err := p.variable() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("segment neither wildcards, literal or variable: %v", err) | ||||
| 		return nil, fmt.Errorf("segment neither wildcards, literal or variable: %w", err) | ||||
| 	} | ||||
| 	return v, err | ||||
| 	return v, nil | ||||
| } | ||||
| 
 | ||||
| func (p *parser) literal() (segment, error) { | ||||
|  | @ -191,7 +192,7 @@ func (p *parser) variable() (segment, error) { | |||
| 	if _, err := p.accept("="); err == nil { | ||||
| 		segs, err = p.segments() | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("invalid segment in variable %q: %v", path, err) | ||||
| 			return nil, fmt.Errorf("invalid segment in variable %q: %w", path, err) | ||||
| 		} | ||||
| 	} else { | ||||
| 		segs = []segment{wildcard{}} | ||||
|  | @ -213,12 +214,12 @@ func (p *parser) fieldPath() (string, error) { | |||
| 	} | ||||
| 	components := []string{c} | ||||
| 	for { | ||||
| 		if _, err = p.accept("."); err != nil { | ||||
| 		if _, err := p.accept("."); err != nil { | ||||
| 			return strings.Join(components, "."), nil | ||||
| 		} | ||||
| 		c, err := p.accept(typeIdent) | ||||
| 		if err != nil { | ||||
| 			return "", fmt.Errorf("invalid field path component: %v", err) | ||||
| 			return "", fmt.Errorf("invalid field path component: %w", err) | ||||
| 		} | ||||
| 		components = append(components, c) | ||||
| 	} | ||||
|  | @ -237,10 +238,8 @@ const ( | |||
| 	typeEOF     = termType("$") | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// eof is the terminal symbol which always appears at the end of token sequence. | ||||
| 	eof = "\u0000" | ||||
| ) | ||||
| // eof is the terminal symbol which always appears at the end of token sequence. | ||||
| const eof = "\u0000" | ||||
| 
 | ||||
| // accept tries to accept a token in "p". | ||||
| // This function consumes a token and returns it if it matches to the specified "term". | ||||
|  | @ -275,11 +274,12 @@ func (p *parser) accept(term termType) (string, error) { | |||
| // expectPChars determines if "t" consists of only pchars defined in RFC3986. | ||||
| // | ||||
| // https://www.ietf.org/rfc/rfc3986.txt, P.49 | ||||
| //   pchar         = unreserved / pct-encoded / sub-delims / ":" / "@" | ||||
| //   unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~" | ||||
| //   sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" | ||||
| //                 / "*" / "+" / "," / ";" / "=" | ||||
| //   pct-encoded   = "%" HEXDIG HEXDIG | ||||
| // | ||||
| //	pchar         = unreserved / pct-encoded / sub-delims / ":" / "@" | ||||
| //	unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~" | ||||
| //	sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" | ||||
| //	              / "*" / "+" / "," / ";" / "=" | ||||
| //	pct-encoded   = "%" HEXDIG HEXDIG | ||||
| func expectPChars(t string) error { | ||||
| 	const ( | ||||
| 		init = iota | ||||
|  | @ -333,7 +333,7 @@ func expectPChars(t string) error { | |||
| // expectIdent determines if "ident" is a valid identifier in .proto schema ([[:alpha:]_][[:alphanum:]_]*). | ||||
| func expectIdent(ident string) error { | ||||
| 	if ident == "" { | ||||
| 		return fmt.Errorf("empty identifier") | ||||
| 		return errors.New("empty identifier") | ||||
| 	} | ||||
| 	for pos, r := range ident { | ||||
| 		switch { | ||||
|  |  | |||
							
								
								
									
										10
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -27,9 +27,9 @@ go_library( | |||
|         "//internal/httprule", | ||||
|         "//utilities", | ||||
|         "@go_googleapis//google/api:httpbody_go_proto", | ||||
|         "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", | ||||
|         "@org_golang_google_grpc//codes", | ||||
|         "@org_golang_google_grpc//grpclog", | ||||
|         "@org_golang_google_grpc//health/grpc_health_v1", | ||||
|         "@org_golang_google_grpc//metadata", | ||||
|         "@org_golang_google_grpc//status", | ||||
|         "@org_golang_google_protobuf//encoding/protojson", | ||||
|  | @ -37,6 +37,8 @@ go_library( | |||
|         "@org_golang_google_protobuf//reflect/protoreflect", | ||||
|         "@org_golang_google_protobuf//reflect/protoregistry", | ||||
|         "@org_golang_google_protobuf//types/known/durationpb", | ||||
|         "@org_golang_google_protobuf//types/known/fieldmaskpb", | ||||
|         "@org_golang_google_protobuf//types/known/structpb", | ||||
|         "@org_golang_google_protobuf//types/known/timestamppb", | ||||
|         "@org_golang_google_protobuf//types/known/wrapperspb", | ||||
|     ], | ||||
|  | @ -56,8 +58,10 @@ go_test( | |||
|         "marshal_jsonpb_test.go", | ||||
|         "marshal_proto_test.go", | ||||
|         "marshaler_registry_test.go", | ||||
|         "mux_internal_test.go", | ||||
|         "mux_test.go", | ||||
|         "pattern_test.go", | ||||
|         "query_fuzz_test.go", | ||||
|         "query_test.go", | ||||
|     ], | ||||
|     embed = [":runtime"], | ||||
|  | @ -69,8 +73,9 @@ go_test( | |||
|         "@go_googleapis//google/api:httpbody_go_proto", | ||||
|         "@go_googleapis//google/rpc:errdetails_go_proto", | ||||
|         "@go_googleapis//google/rpc:status_go_proto", | ||||
|         "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", | ||||
|         "@org_golang_google_grpc//:go_default_library", | ||||
|         "@org_golang_google_grpc//codes", | ||||
|         "@org_golang_google_grpc//health/grpc_health_v1", | ||||
|         "@org_golang_google_grpc//metadata", | ||||
|         "@org_golang_google_grpc//status", | ||||
|         "@org_golang_google_protobuf//encoding/protojson", | ||||
|  | @ -78,6 +83,7 @@ go_test( | |||
|         "@org_golang_google_protobuf//testing/protocmp", | ||||
|         "@org_golang_google_protobuf//types/known/durationpb", | ||||
|         "@org_golang_google_protobuf//types/known/emptypb", | ||||
|         "@org_golang_google_protobuf//types/known/fieldmaskpb", | ||||
|         "@org_golang_google_protobuf//types/known/structpb", | ||||
|         "@org_golang_google_protobuf//types/known/timestamppb", | ||||
|         "@org_golang_google_protobuf//types/known/wrapperspb", | ||||
|  |  | |||
							
								
								
									
										72
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -13,6 +13,7 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/grpclog" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | @ -35,11 +36,15 @@ const metadataHeaderBinarySuffix = "-Bin" | |||
| const xForwardedFor = "X-Forwarded-For" | ||||
| const xForwardedHost = "X-Forwarded-Host" | ||||
| 
 | ||||
| var ( | ||||
| 	// DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound | ||||
| 	// header isn't present. If the value is 0 the sent `context` will not have a timeout. | ||||
| 	DefaultContextTimeout = 0 * time.Second | ||||
| ) | ||||
| // DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound | ||||
| // header isn't present. If the value is 0 the sent `context` will not have a timeout. | ||||
| var DefaultContextTimeout = 0 * time.Second | ||||
| 
 | ||||
| // malformedHTTPHeaders lists the headers that the gRPC server may reject outright as malformed. | ||||
| // See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more context. | ||||
| var malformedHTTPHeaders = map[string]struct{}{ | ||||
| 	"connection": {}, | ||||
| } | ||||
| 
 | ||||
| type ( | ||||
| 	rpcMethodKey       struct{} | ||||
|  | @ -95,12 +100,43 @@ func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Reque | |||
| 	return metadata.NewIncomingContext(ctx, md), nil | ||||
| } | ||||
| 
 | ||||
| func isValidGRPCMetadataKey(key string) bool { | ||||
| 	// Must be a valid gRPC "Header-Name" as defined here: | ||||
| 	//   https://github.com/grpc/grpc/blob/4b05dc88b724214d0c725c8e7442cbc7a61b1374/doc/PROTOCOL-HTTP2.md | ||||
| 	// This means 0-9 a-z _ - . | ||||
| 	// Only lowercase letters are valid in the wire protocol, but the client library will normalize | ||||
| 	// uppercase ASCII to lowercase, so uppercase ASCII is also acceptable. | ||||
| 	bytes := []byte(key) // gRPC validates strings on the byte level, not Unicode. | ||||
| 	for _, ch := range bytes { | ||||
| 		validLowercaseLetter := ch >= 'a' && ch <= 'z' | ||||
| 		validUppercaseLetter := ch >= 'A' && ch <= 'Z' | ||||
| 		validDigit := ch >= '0' && ch <= '9' | ||||
| 		validOther := ch == '.' || ch == '-' || ch == '_' | ||||
| 		if !validLowercaseLetter && !validUppercaseLetter && !validDigit && !validOther { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func isValidGRPCMetadataTextValue(textValue string) bool { | ||||
| 	// Must be a valid gRPC "ASCII-Value" as defined here: | ||||
| 	//   https://github.com/grpc/grpc/blob/4b05dc88b724214d0c725c8e7442cbc7a61b1374/doc/PROTOCOL-HTTP2.md | ||||
| 	// This means printable ASCII (including/plus spaces); 0x20 to 0x7E inclusive. | ||||
| 	bytes := []byte(textValue) // gRPC validates strings on the byte level, not Unicode. | ||||
| 	for _, ch := range bytes { | ||||
| 		if ch < 0x20 || ch > 0x7E { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, metadata.MD, error) { | ||||
| 	ctx = withRPCMethod(ctx, rpcMethodName) | ||||
| 	for _, o := range options { | ||||
| 		ctx = o(ctx) | ||||
| 	} | ||||
| 	var pairs []string | ||||
| 	timeout := DefaultContextTimeout | ||||
| 	if tm := req.Header.Get(metadataGrpcTimeout); tm != "" { | ||||
| 		var err error | ||||
|  | @ -109,7 +145,7 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM | |||
| 			return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var pairs []string | ||||
| 	for key, vals := range req.Header { | ||||
| 		key = textproto.CanonicalMIMEHeaderKey(key) | ||||
| 		for _, val := range vals { | ||||
|  | @ -118,6 +154,10 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM | |||
| 				pairs = append(pairs, "authorization", val) | ||||
| 			} | ||||
| 			if h, ok := mux.incomingHeaderMatcher(key); ok { | ||||
| 				if !isValidGRPCMetadataKey(h) { | ||||
| 					grpclog.Errorf("HTTP header name %q is not valid as gRPC metadata key; skipping", h) | ||||
| 					continue | ||||
| 				} | ||||
| 				// Handles "-bin" metadata in grpc, since grpc will do another base64 | ||||
| 				// encode before sending to server, we need to decode it first. | ||||
| 				if strings.HasSuffix(key, metadataHeaderBinarySuffix) { | ||||
|  | @ -127,6 +167,9 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM | |||
| 					} | ||||
| 
 | ||||
| 					val = string(b) | ||||
| 				} else if !isValidGRPCMetadataTextValue(val) { | ||||
| 					grpclog.Errorf("Value of HTTP header %q contains non-ASCII value (not valid as gRPC metadata): skipping", h) | ||||
| 					continue | ||||
| 				} | ||||
| 				pairs = append(pairs, h, val) | ||||
| 			} | ||||
|  | @ -172,11 +215,17 @@ type serverMetadataKey struct{} | |||
| 
 | ||||
| // NewServerMetadataContext creates a new context with ServerMetadata | ||||
| func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context { | ||||
| 	if ctx == nil { | ||||
| 		ctx = context.Background() | ||||
| 	} | ||||
| 	return context.WithValue(ctx, serverMetadataKey{}, md) | ||||
| } | ||||
| 
 | ||||
| // ServerMetadataFromContext returns the ServerMetadata in ctx | ||||
| func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) { | ||||
| 	if ctx == nil { | ||||
| 		return md, false | ||||
| 	} | ||||
| 	md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata) | ||||
| 	return | ||||
| } | ||||
|  | @ -269,8 +318,8 @@ func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) { | |||
| 	case 'n': | ||||
| 		return time.Nanosecond, true | ||||
| 	default: | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // isPermanentHTTPHeader checks whether hdr belongs to the list of | ||||
|  | @ -308,6 +357,13 @@ func isPermanentHTTPHeader(hdr string) bool { | |||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // isMalformedHTTPHeader checks whether header belongs to the list of | ||||
| // "malformed headers" and would be rejected by the gRPC server. | ||||
| func isMalformedHTTPHeader(header string) bool { | ||||
| 	_, isMalformed := malformedHTTPHeaders[strings.ToLower(header)] | ||||
| 	return isMalformed | ||||
| } | ||||
| 
 | ||||
| // RPCMethod returns the method string for the server context. The returned | ||||
| // string is in the format of "/package.service/method". | ||||
| func RPCMethod(ctx context.Context) (string, bool) { | ||||
|  |  | |||
							
								
								
									
										46
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -37,7 +37,7 @@ func BoolSlice(val, sep string) ([]bool, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Bool(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -57,7 +57,7 @@ func Float64Slice(val, sep string) ([]float64, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Float64(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -81,7 +81,7 @@ func Float32Slice(val, sep string) ([]float32, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Float32(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -101,7 +101,7 @@ func Int64Slice(val, sep string) ([]int64, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Int64(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -125,7 +125,7 @@ func Int32Slice(val, sep string) ([]int32, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Int32(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -145,7 +145,7 @@ func Uint64Slice(val, sep string) ([]uint64, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Uint64(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -169,7 +169,7 @@ func Uint32Slice(val, sep string) ([]uint32, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Uint32(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -197,7 +197,7 @@ func BytesSlice(val, sep string) ([][]byte, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Bytes(v) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
|  | @ -209,8 +209,7 @@ func Timestamp(val string) (*timestamppb.Timestamp, error) { | |||
| 	var r timestamppb.Timestamp | ||||
| 	val = strconv.Quote(strings.Trim(val, `"`)) | ||||
| 	unmarshaler := &protojson.UnmarshalOptions{} | ||||
| 	err := unmarshaler.Unmarshal([]byte(val), &r) | ||||
| 	if err != nil { | ||||
| 	if err := unmarshaler.Unmarshal([]byte(val), &r); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &r, nil | ||||
|  | @ -221,8 +220,7 @@ func Duration(val string) (*durationpb.Duration, error) { | |||
| 	var r durationpb.Duration | ||||
| 	val = strconv.Quote(strings.Trim(val, `"`)) | ||||
| 	unmarshaler := &protojson.UnmarshalOptions{} | ||||
| 	err := unmarshaler.Unmarshal([]byte(val), &r) | ||||
| 	if err != nil { | ||||
| 	if err := unmarshaler.Unmarshal([]byte(val), &r); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &r, nil | ||||
|  | @ -257,66 +255,64 @@ func EnumSlice(val, sep string, enumValMap map[string]int32) ([]int32, error) { | |||
| 	for i, v := range s { | ||||
| 		value, err := Enum(v, enumValMap) | ||||
| 		if err != nil { | ||||
| 			return values, err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		values[i] = value | ||||
| 	} | ||||
| 	return values, nil | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| 	Support fot google.protobuf.wrappers on top of primitive types | ||||
| */ | ||||
| // Support for google.protobuf.wrappers on top of primitive types | ||||
| 
 | ||||
| // StringValue well-known type support as wrapper around string type | ||||
| func StringValue(val string) (*wrapperspb.StringValue, error) { | ||||
| 	return &wrapperspb.StringValue{Value: val}, nil | ||||
| 	return wrapperspb.String(val), nil | ||||
| } | ||||
| 
 | ||||
| // FloatValue well-known type support as wrapper around float32 type | ||||
| func FloatValue(val string) (*wrapperspb.FloatValue, error) { | ||||
| 	parsedVal, err := Float32(val) | ||||
| 	return &wrapperspb.FloatValue{Value: parsedVal}, err | ||||
| 	return wrapperspb.Float(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // DoubleValue well-known type support as wrapper around float64 type | ||||
| func DoubleValue(val string) (*wrapperspb.DoubleValue, error) { | ||||
| 	parsedVal, err := Float64(val) | ||||
| 	return &wrapperspb.DoubleValue{Value: parsedVal}, err | ||||
| 	return wrapperspb.Double(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // BoolValue well-known type support as wrapper around bool type | ||||
| func BoolValue(val string) (*wrapperspb.BoolValue, error) { | ||||
| 	parsedVal, err := Bool(val) | ||||
| 	return &wrapperspb.BoolValue{Value: parsedVal}, err | ||||
| 	return wrapperspb.Bool(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // Int32Value well-known type support as wrapper around int32 type | ||||
| func Int32Value(val string) (*wrapperspb.Int32Value, error) { | ||||
| 	parsedVal, err := Int32(val) | ||||
| 	return &wrapperspb.Int32Value{Value: parsedVal}, err | ||||
| 	return wrapperspb.Int32(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // UInt32Value well-known type support as wrapper around uint32 type | ||||
| func UInt32Value(val string) (*wrapperspb.UInt32Value, error) { | ||||
| 	parsedVal, err := Uint32(val) | ||||
| 	return &wrapperspb.UInt32Value{Value: parsedVal}, err | ||||
| 	return wrapperspb.UInt32(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // Int64Value well-known type support as wrapper around int64 type | ||||
| func Int64Value(val string) (*wrapperspb.Int64Value, error) { | ||||
| 	parsedVal, err := Int64(val) | ||||
| 	return &wrapperspb.Int64Value{Value: parsedVal}, err | ||||
| 	return wrapperspb.Int64(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // UInt64Value well-known type support as wrapper around uint64 type | ||||
| func UInt64Value(val string) (*wrapperspb.UInt64Value, error) { | ||||
| 	parsedVal, err := Uint64(val) | ||||
| 	return &wrapperspb.UInt64Value{Value: parsedVal}, err | ||||
| 	return wrapperspb.UInt64(parsedVal), err | ||||
| } | ||||
| 
 | ||||
| // BytesValue well-known type support as wrapper around bytes[] type | ||||
| func BytesValue(val string) (*wrapperspb.BytesValue, error) { | ||||
| 	parsedVal, err := Bytes(val) | ||||
| 	return &wrapperspb.BytesValue{Value: parsedVal}, err | ||||
| 	return wrapperspb.Bytes(parsedVal), err | ||||
| } | ||||
|  |  | |||
							
								
								
									
										17
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -38,7 +38,7 @@ func HTTPStatusFromCode(code codes.Code) int { | |||
| 	case codes.OK: | ||||
| 		return http.StatusOK | ||||
| 	case codes.Canceled: | ||||
| 		return http.StatusRequestTimeout | ||||
| 		return 499 | ||||
| 	case codes.Unknown: | ||||
| 		return http.StatusInternalServerError | ||||
| 	case codes.InvalidArgument: | ||||
|  | @ -70,10 +70,10 @@ func HTTPStatusFromCode(code codes.Code) int { | |||
| 		return http.StatusServiceUnavailable | ||||
| 	case codes.DataLoss: | ||||
| 		return http.StatusInternalServerError | ||||
| 	default: | ||||
| 		grpclog.Infof("Unknown gRPC error code: %v", code) | ||||
| 		return http.StatusInternalServerError | ||||
| 	} | ||||
| 
 | ||||
| 	grpclog.Infof("Unknown gRPC error code: %v", code) | ||||
| 	return http.StatusInternalServerError | ||||
| } | ||||
| 
 | ||||
| // HTTPError uses the mux-configured error handler. | ||||
|  | @ -162,10 +162,11 @@ func DefaultStreamErrorHandler(_ context.Context, err error) *status.Status { | |||
| 
 | ||||
| // DefaultRoutingErrorHandler is our default handler for routing errors. | ||||
| // By default http error codes mapped on the following error codes: | ||||
| //   NotFound -> grpc.NotFound | ||||
| //   StatusBadRequest -> grpc.InvalidArgument | ||||
| //   MethodNotAllowed -> grpc.Unimplemented | ||||
| //   Other -> grpc.Internal, method is not expecting to be called for anything else | ||||
| // | ||||
| //	NotFound -> grpc.NotFound | ||||
| //	StatusBadRequest -> grpc.InvalidArgument | ||||
| //	MethodNotAllowed -> grpc.Unimplemented | ||||
| //	Other -> grpc.Internal, method is not expecting to be called for anything else | ||||
| func DefaultRoutingErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, httpStatus int) { | ||||
| 	sterr := status.Error(codes.Internal, "Unexpected routing error") | ||||
| 	switch httpStatus { | ||||
|  |  | |||
							
								
								
									
										9
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -2,13 +2,14 @@ package runtime | |||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"sort" | ||||
| 
 | ||||
| 	"google.golang.org/genproto/protobuf/field_mask" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	field_mask "google.golang.org/protobuf/types/known/fieldmaskpb" | ||||
| ) | ||||
| 
 | ||||
| func getFieldByName(fields protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor { | ||||
|  | @ -44,7 +45,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field | |||
| 			// if the item is an object, then enqueue all of its children | ||||
| 			for k, v := range m { | ||||
| 				if item.msg == nil { | ||||
| 					return nil, fmt.Errorf("JSON structure did not match request type") | ||||
| 					return nil, errors.New("JSON structure did not match request type") | ||||
| 				} | ||||
| 
 | ||||
| 				fd := getFieldByName(item.msg.Descriptor().Fields(), k) | ||||
|  | @ -53,7 +54,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field | |||
| 				} | ||||
| 
 | ||||
| 				if isDynamicProtoMessage(fd.Message()) { | ||||
| 					for _, p := range buildPathsBlindly(k, v) { | ||||
| 					for _, p := range buildPathsBlindly(string(fd.FullName().Name()), v) { | ||||
| 						newPath := p | ||||
| 						if item.path != "" { | ||||
| 							newPath = item.path + "." + newPath | ||||
|  | @ -63,7 +64,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field | |||
| 					continue | ||||
| 				} | ||||
| 
 | ||||
| 				if isProtobufAnyMessage(fd.Message()) { | ||||
| 				if isProtobufAnyMessage(fd.Message()) && !fd.IsList() { | ||||
| 					_, hasTypeField := v.(map[string]interface{})["@type"] | ||||
| 					if hasTypeField { | ||||
| 						queue = append(queue, fieldMaskPathItem{path: k}) | ||||
|  |  | |||
							
								
								
									
										26
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -52,11 +52,11 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal | |||
| 			return | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter) | ||||
| 			return | ||||
| 		} | ||||
| 		if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
|  | @ -82,15 +82,15 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal | |||
| 
 | ||||
| 		if err != nil { | ||||
| 			grpclog.Infof("Failed to marshal response chunk: %v", err) | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) | ||||
| 			handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter) | ||||
| 			return | ||||
| 		} | ||||
| 		if _, err = w.Write(buf); err != nil { | ||||
| 		if _, err := w.Write(buf); err != nil { | ||||
| 			grpclog.Infof("Failed to send response chunk: %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 		wroteHeader = true | ||||
| 		if _, err = w.Write(delimiter); err != nil { | ||||
| 		if _, err := w.Write(delimiter); err != nil { | ||||
| 			grpclog.Infof("Failed to send delimiter chunk: %v", err) | ||||
| 			return | ||||
| 		} | ||||
|  | @ -200,20 +200,24 @@ func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, re | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, marshaler Marshaler, w http.ResponseWriter, req *http.Request, mux *ServeMux, err error) { | ||||
| func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, marshaler Marshaler, w http.ResponseWriter, req *http.Request, mux *ServeMux, err error, delimiter []byte) { | ||||
| 	st := mux.streamErrorHandler(ctx, err) | ||||
| 	msg := errorChunk(st) | ||||
| 	if !wroteHeader { | ||||
| 		w.Header().Set("Content-Type", marshaler.ContentType(msg)) | ||||
| 		w.WriteHeader(HTTPStatusFromCode(st.Code())) | ||||
| 	} | ||||
| 	buf, merr := marshaler.Marshal(msg) | ||||
| 	if merr != nil { | ||||
| 		grpclog.Infof("Failed to marshal an error: %v", merr) | ||||
| 	buf, err := marshaler.Marshal(msg) | ||||
| 	if err != nil { | ||||
| 		grpclog.Infof("Failed to marshal an error: %v", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if _, werr := w.Write(buf); werr != nil { | ||||
| 		grpclog.Infof("Failed to notify error to client: %v", werr) | ||||
| 	if _, err := w.Write(buf); err != nil { | ||||
| 		grpclog.Infof("Failed to notify error to client: %v", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if _, err := w.Write(delimiter); err != nil { | ||||
| 		grpclog.Infof("Failed to send delimiter chunk: %v", err) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										38
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -92,23 +92,20 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { | |||
| 
 | ||||
| 		if rv.Type().Elem().Implements(protoMessageType) { | ||||
| 			var buf bytes.Buffer | ||||
| 			err := buf.WriteByte('[') | ||||
| 			if err != nil { | ||||
| 			if err := buf.WriteByte('['); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			for i := 0; i < rv.Len(); i++ { | ||||
| 				if i != 0 { | ||||
| 					err = buf.WriteByte(',') | ||||
| 					if err != nil { | ||||
| 					if err := buf.WriteByte(','); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				} | ||||
| 				if err = j.marshalTo(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { | ||||
| 				if err := j.marshalTo(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 			} | ||||
| 			err = buf.WriteByte(']') | ||||
| 			if err != nil { | ||||
| 			if err := buf.WriteByte(']'); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
|  | @ -117,17 +114,16 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { | |||
| 
 | ||||
| 		if rv.Type().Elem().Implements(typeProtoEnum) { | ||||
| 			var buf bytes.Buffer | ||||
| 			err := buf.WriteByte('[') | ||||
| 			if err != nil { | ||||
| 			if err := buf.WriteByte('['); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			for i := 0; i < rv.Len(); i++ { | ||||
| 				if i != 0 { | ||||
| 					err = buf.WriteByte(',') | ||||
| 					if err != nil { | ||||
| 					if err := buf.WriteByte(','); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				} | ||||
| 				var err error | ||||
| 				if j.UseEnumNumbers { | ||||
| 					_, err = buf.WriteString(strconv.FormatInt(rv.Index(i).Int(), 10)) | ||||
| 				} else { | ||||
|  | @ -137,8 +133,7 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { | |||
| 					return nil, err | ||||
| 				} | ||||
| 			} | ||||
| 			err = buf.WriteByte(']') | ||||
| 			if err != nil { | ||||
| 			if err := buf.WriteByte(']'); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
|  | @ -219,8 +214,7 @@ func decodeJSONPb(d *json.Decoder, unmarshaler protojson.UnmarshalOptions, v int | |||
| 
 | ||||
| 	// Decode into bytes for marshalling | ||||
| 	var b json.RawMessage | ||||
| 	err := d.Decode(&b) | ||||
| 	if err != nil { | ||||
| 	if err := d.Decode(&b); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
|  | @ -239,8 +233,7 @@ func decodeNonProtoField(d *json.Decoder, unmarshaler protojson.UnmarshalOptions | |||
| 		if rv.Type().ConvertibleTo(typeProtoMessage) { | ||||
| 			// Decode into bytes for marshalling | ||||
| 			var b json.RawMessage | ||||
| 			err := d.Decode(&b) | ||||
| 			if err != nil { | ||||
| 			if err := d.Decode(&b); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 
 | ||||
|  | @ -280,6 +273,17 @@ func decodeNonProtoField(d *json.Decoder, unmarshaler protojson.UnmarshalOptions | |||
| 		return nil | ||||
| 	} | ||||
| 	if rv.Kind() == reflect.Slice { | ||||
| 		if rv.Type().Elem().Kind() == reflect.Uint8 { | ||||
| 			var sl []byte | ||||
| 			if err := d.Decode(&sl); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if sl != nil { | ||||
| 				rv.SetBytes(sl) | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		var sl []json.RawMessage | ||||
| 		if err := d.Decode(&sl); err != nil { | ||||
| 			return err | ||||
|  |  | |||
							
								
								
									
										9
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_proto.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_proto.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,10 +1,8 @@ | |||
| package runtime | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| 
 | ||||
| 	"errors" | ||||
| 	"io/ioutil" | ||||
| 	"io" | ||||
| 
 | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
|  | @ -38,7 +36,7 @@ func (*ProtoMarshaller) Unmarshal(data []byte, value interface{}) error { | |||
| // NewDecoder returns a Decoder which reads proto stream from "reader". | ||||
| func (marshaller *ProtoMarshaller) NewDecoder(reader io.Reader) Decoder { | ||||
| 	return DecoderFunc(func(value interface{}) error { | ||||
| 		buffer, err := ioutil.ReadAll(reader) | ||||
| 		buffer, err := io.ReadAll(reader) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | @ -53,8 +51,7 @@ func (marshaller *ProtoMarshaller) NewEncoder(writer io.Writer) Encoder { | |||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		_, err = writer.Write(buffer) | ||||
| 		if err != nil { | ||||
| 		if _, err := writer.Write(buffer); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										162
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										162
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -6,10 +6,13 @@ import ( | |||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/textproto" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/grpclog" | ||||
| 	"google.golang.org/grpc/health/grpc_health_v1" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
|  | @ -23,15 +26,15 @@ const ( | |||
| 	// path string before doing any routing. | ||||
| 	UnescapingModeLegacy UnescapingMode = iota | ||||
| 
 | ||||
| 	// EscapingTypeExceptReserved unescapes all path parameters except RFC 6570 | ||||
| 	// UnescapingModeAllExceptReserved unescapes all path parameters except RFC 6570 | ||||
| 	// reserved characters. | ||||
| 	UnescapingModeAllExceptReserved | ||||
| 
 | ||||
| 	// EscapingTypeExceptSlash unescapes URL path parameters except path | ||||
| 	// seperators, which will be left as "%2F". | ||||
| 	// UnescapingModeAllExceptSlash unescapes URL path parameters except path | ||||
| 	// separators, which will be left as "%2F". | ||||
| 	UnescapingModeAllExceptSlash | ||||
| 
 | ||||
| 	// URL path parameters will be fully decoded. | ||||
| 	// UnescapingModeAllCharacters unescapes all URL path parameters. | ||||
| 	UnescapingModeAllCharacters | ||||
| 
 | ||||
| 	// UnescapingModeDefault is the default escaping type. | ||||
|  | @ -40,6 +43,8 @@ const ( | |||
| 	UnescapingModeDefault = UnescapingModeLegacy | ||||
| ) | ||||
| 
 | ||||
| var encodedPathSplitter = regexp.MustCompile("(/|%2F)") | ||||
| 
 | ||||
| // A HandlerFunc handles a specific pair of path pattern and HTTP method. | ||||
| type HandlerFunc func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) | ||||
| 
 | ||||
|  | @ -75,7 +80,7 @@ func WithForwardResponseOption(forwardResponseOption func(context.Context, http. | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithEscapingType sets the escaping type. See the definitions of UnescapingMode | ||||
| // WithUnescapingMode sets the escaping type. See the definitions of UnescapingMode | ||||
| // for more information. | ||||
| func WithUnescapingMode(mode UnescapingMode) ServeMuxOption { | ||||
| 	return func(serveMux *ServeMux) { | ||||
|  | @ -96,13 +101,14 @@ func SetQueryParameterParser(queryParameterParser QueryParameterParser) ServeMux | |||
| type HeaderMatcherFunc func(string) (string, bool) | ||||
| 
 | ||||
| // DefaultHeaderMatcher is used to pass http request headers to/from gRPC context. This adds permanent HTTP header | ||||
| // keys (as specified by the IANA) to gRPC context with grpcgateway- prefix. HTTP headers that start with | ||||
| // 'Grpc-Metadata-' are mapped to gRPC metadata after removing prefix 'Grpc-Metadata-'. | ||||
| // keys (as specified by the IANA, e.g: Accept, Cookie, Host) to the gRPC metadata with the grpcgateway- prefix. If you want to know which headers are considered permanent, you can view the isPermanentHTTPHeader function. | ||||
| // HTTP headers that start with 'Grpc-Metadata-' are mapped to gRPC metadata after removing the prefix 'Grpc-Metadata-'. | ||||
| // Other headers are not added to the gRPC metadata. | ||||
| func DefaultHeaderMatcher(key string) (string, bool) { | ||||
| 	key = textproto.CanonicalMIMEHeaderKey(key) | ||||
| 	if isPermanentHTTPHeader(key) { | ||||
| 	switch key = textproto.CanonicalMIMEHeaderKey(key); { | ||||
| 	case isPermanentHTTPHeader(key): | ||||
| 		return MetadataPrefix + key, true | ||||
| 	} else if strings.HasPrefix(key, MetadataHeaderPrefix) { | ||||
| 	case strings.HasPrefix(key, MetadataHeaderPrefix): | ||||
| 		return key[len(MetadataHeaderPrefix):], true | ||||
| 	} | ||||
| 	return "", false | ||||
|  | @ -113,11 +119,30 @@ func DefaultHeaderMatcher(key string) (string, bool) { | |||
| // This matcher will be called with each header in http.Request. If matcher returns true, that header will be | ||||
| // passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header. | ||||
| func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { | ||||
| 	for _, header := range fn.matchedMalformedHeaders() { | ||||
| 		grpclog.Warningf("The configured forwarding filter would allow %q to be sent to the gRPC server, which will likely cause errors. See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more information.", header) | ||||
| 	} | ||||
| 
 | ||||
| 	return func(mux *ServeMux) { | ||||
| 		mux.incomingHeaderMatcher = fn | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // matchedMalformedHeaders returns the malformed headers that would be forwarded to gRPC server. | ||||
| func (fn HeaderMatcherFunc) matchedMalformedHeaders() []string { | ||||
| 	if fn == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	headers := make([]string, 0) | ||||
| 	for header := range malformedHTTPHeaders { | ||||
| 		out, accept := fn(header) | ||||
| 		if accept && isMalformedHTTPHeader(out) { | ||||
| 			headers = append(headers, out) | ||||
| 		} | ||||
| 	} | ||||
| 	return headers | ||||
| } | ||||
| 
 | ||||
| // WithOutgoingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway. | ||||
| // | ||||
| // This matcher will be called with each header in response header metadata. If matcher returns true, that header will be | ||||
|  | @ -179,6 +204,56 @@ func WithDisablePathLengthFallback() ServeMuxOption { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithHealthEndpointAt returns a ServeMuxOption that will add an endpoint to the created ServeMux at the path specified by endpointPath. | ||||
| // When called the handler will forward the request to the upstream grpc service health check (defined in the | ||||
| // gRPC Health Checking Protocol). | ||||
| // | ||||
| // See here https://grpc-ecosystem.github.io/grpc-gateway/docs/operations/health_check/ for more information on how | ||||
| // to setup the protocol in the grpc server. | ||||
| // | ||||
| // If you define a service as query parameter, this will also be forwarded as service in the HealthCheckRequest. | ||||
| func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpointPath string) ServeMuxOption { | ||||
| 	return func(s *ServeMux) { | ||||
| 		// error can be ignored since pattern is definitely valid | ||||
| 		_ = s.HandlePath( | ||||
| 			http.MethodGet, endpointPath, func(w http.ResponseWriter, r *http.Request, _ map[string]string, | ||||
| 			) { | ||||
| 				_, outboundMarshaler := MarshalerForRequest(s, r) | ||||
| 
 | ||||
| 				resp, err := healthCheckClient.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{ | ||||
| 					Service: r.URL.Query().Get("service"), | ||||
| 				}) | ||||
| 				if err != nil { | ||||
| 					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err) | ||||
| 					return | ||||
| 				} | ||||
| 
 | ||||
| 				w.Header().Set("Content-Type", "application/json") | ||||
| 
 | ||||
| 				if resp.GetStatus() != grpc_health_v1.HealthCheckResponse_SERVING { | ||||
| 					switch resp.GetStatus() { | ||||
| 					case grpc_health_v1.HealthCheckResponse_NOT_SERVING, grpc_health_v1.HealthCheckResponse_UNKNOWN: | ||||
| 						err = status.Error(codes.Unavailable, resp.String()) | ||||
| 					case grpc_health_v1.HealthCheckResponse_SERVICE_UNKNOWN: | ||||
| 						err = status.Error(codes.NotFound, resp.String()) | ||||
| 					} | ||||
| 
 | ||||
| 					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err) | ||||
| 					return | ||||
| 				} | ||||
| 
 | ||||
| 				_ = outboundMarshaler.NewEncoder(w).Encode(resp) | ||||
| 			}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithHealthzEndpoint returns a ServeMuxOption that will add a /healthz endpoint to the created ServeMux. | ||||
| // | ||||
| // See WithHealthEndpointAt for the general implementation. | ||||
| func WithHealthzEndpoint(healthCheckClient grpc_health_v1.HealthClient) ServeMuxOption { | ||||
| 	return WithHealthEndpointAt(healthCheckClient, "/healthz") | ||||
| } | ||||
| 
 | ||||
| // NewServeMux returns a new ServeMux whose internal mapping is empty. | ||||
| func NewServeMux(opts ...ServeMuxOption) *ServeMux { | ||||
| 	serveMux := &ServeMux{ | ||||
|  | @ -229,7 +304,7 @@ func (s *ServeMux) HandlePath(meth string, pathPattern string, h HandlerFunc) er | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path. | ||||
| // ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.URL.Path. | ||||
| func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	ctx := r.Context() | ||||
| 
 | ||||
|  | @ -245,8 +320,6 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| 		path = r.URL.RawPath | ||||
| 	} | ||||
| 
 | ||||
| 	components := strings.Split(path[1:], "/") | ||||
| 
 | ||||
| 	if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) { | ||||
| 		r.Method = strings.ToUpper(override) | ||||
| 		if err := r.ParseForm(); err != nil { | ||||
|  | @ -257,8 +330,18 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Verb out here is to memoize for the fallback case below | ||||
| 	var verb string | ||||
| 	var pathComponents []string | ||||
| 	// since in UnescapeModeLegacy, the URL will already have been fully unescaped, if we also split on "%2F" | ||||
| 	// in this escaping mode we would be double unescaping but in UnescapingModeAllCharacters, we still do as the | ||||
| 	// path is the RawPath (i.e. unescaped). That does mean that the behavior of this function will change its default | ||||
| 	// behavior when the UnescapingModeDefault gets changed from UnescapingModeLegacy to UnescapingModeAllExceptReserved | ||||
| 	if s.unescapingMode == UnescapingModeAllCharacters { | ||||
| 		pathComponents = encodedPathSplitter.Split(path[1:], -1) | ||||
| 	} else { | ||||
| 		pathComponents = strings.Split(path[1:], "/") | ||||
| 	} | ||||
| 
 | ||||
| 	lastPathComponent := pathComponents[len(pathComponents)-1] | ||||
| 
 | ||||
| 	for _, h := range s.handlers[r.Method] { | ||||
| 		// If the pattern has a verb, explicitly look for a suffix in the last | ||||
|  | @ -269,23 +352,28 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| 		// parser because we know what verb we're looking for, however, there | ||||
| 		// are still some cases that the parser itself cannot disambiguate. See | ||||
| 		// the comment there if interested. | ||||
| 
 | ||||
| 		var verb string | ||||
| 		patVerb := h.pat.Verb() | ||||
| 		l := len(components) | ||||
| 		lastComponent := components[l-1] | ||||
| 		var idx int = -1 | ||||
| 		if patVerb != "" && strings.HasSuffix(lastComponent, ":"+patVerb) { | ||||
| 			idx = len(lastComponent) - len(patVerb) - 1 | ||||
| 
 | ||||
| 		idx := -1 | ||||
| 		if patVerb != "" && strings.HasSuffix(lastPathComponent, ":"+patVerb) { | ||||
| 			idx = len(lastPathComponent) - len(patVerb) - 1 | ||||
| 		} | ||||
| 		if idx == 0 { | ||||
| 			_, outboundMarshaler := MarshalerForRequest(s, r) | ||||
| 			s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusNotFound) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		comps := make([]string, len(pathComponents)) | ||||
| 		copy(comps, pathComponents) | ||||
| 
 | ||||
| 		if idx > 0 { | ||||
| 			components[l-1], verb = lastComponent[:idx], lastComponent[idx+1:] | ||||
| 			comps[len(comps)-1], verb = lastPathComponent[:idx], lastPathComponent[idx+1:] | ||||
| 		} | ||||
| 
 | ||||
| 		pathParams, err := h.pat.MatchAndEscape(components, verb, s.unescapingMode) | ||||
| 		pathParams, err := h.pat.MatchAndEscape(comps, verb, s.unescapingMode) | ||||
| 		if err != nil { | ||||
| 			var mse MalformedSequenceError | ||||
| 			if ok := errors.As(err, &mse); ok { | ||||
|  | @ -301,14 +389,33 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// lookup other methods to handle fallback from GET to POST and | ||||
| 	// to determine if it is NotImplemented or NotFound. | ||||
| 	// if no handler has found for the request, lookup for other methods | ||||
| 	// to handle POST -> GET fallback if the request is subject to path | ||||
| 	// length fallback. | ||||
| 	// Note we are not eagerly checking the request here as we want to return the | ||||
| 	// right HTTP status code, and we need to process the fallback candidates in | ||||
| 	// order to do that. | ||||
| 	for m, handlers := range s.handlers { | ||||
| 		if m == r.Method { | ||||
| 			continue | ||||
| 		} | ||||
| 		for _, h := range handlers { | ||||
| 			pathParams, err := h.pat.MatchAndEscape(components, verb, s.unescapingMode) | ||||
| 			var verb string | ||||
| 			patVerb := h.pat.Verb() | ||||
| 
 | ||||
| 			idx := -1 | ||||
| 			if patVerb != "" && strings.HasSuffix(lastPathComponent, ":"+patVerb) { | ||||
| 				idx = len(lastPathComponent) - len(patVerb) - 1 | ||||
| 			} | ||||
| 
 | ||||
| 			comps := make([]string, len(pathComponents)) | ||||
| 			copy(comps, pathComponents) | ||||
| 
 | ||||
| 			if idx > 0 { | ||||
| 				comps[len(comps)-1], verb = lastPathComponent[:idx], lastPathComponent[idx+1:] | ||||
| 			} | ||||
| 
 | ||||
| 			pathParams, err := h.pat.MatchAndEscape(comps, verb, s.unescapingMode) | ||||
| 			if err != nil { | ||||
| 				var mse MalformedSequenceError | ||||
| 				if ok := errors.As(err, &mse); ok { | ||||
|  | @ -320,8 +427,11 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| 			// X-HTTP-Method-Override is optional. Always allow fallback to POST. | ||||
| 			if s.isPathLengthFallback(r) { | ||||
| 			// Also, only consider POST -> GET fallbacks, and avoid falling back to | ||||
| 			// potentially dangerous operations like DELETE. | ||||
| 			if s.isPathLengthFallback(r) && m == http.MethodGet { | ||||
| 				if err := r.ParseForm(); err != nil { | ||||
| 					_, outboundMarshaler := MarshalerForRequest(s, r) | ||||
| 					sterr := status.Error(codes.InvalidArgument, err.Error()) | ||||
|  |  | |||
							
								
								
									
										2
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/pattern.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/pattern.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -15,8 +15,6 @@ var ( | |||
| 	ErrNotMatch = errors.New("not match to the path pattern") | ||||
| 	// ErrInvalidPattern indicates that the given definition of Pattern is not valid. | ||||
| 	ErrInvalidPattern = errors.New("invalid pattern") | ||||
| 	// ErrMalformedSequence indicates that an escape sequence was malformed. | ||||
| 	ErrMalformedSequence = errors.New("malformed escape sequence") | ||||
| ) | ||||
| 
 | ||||
| type MalformedSequenceError string | ||||
|  |  | |||
							
								
								
									
										69
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,7 +1,6 @@ | |||
| package runtime | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/url" | ||||
|  | @ -11,19 +10,21 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities" | ||||
| 	"google.golang.org/genproto/protobuf/field_mask" | ||||
| 	"google.golang.org/grpc/grpclog" | ||||
| 	"google.golang.org/protobuf/encoding/protojson" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	"google.golang.org/protobuf/reflect/protoregistry" | ||||
| 	"google.golang.org/protobuf/types/known/durationpb" | ||||
| 	field_mask "google.golang.org/protobuf/types/known/fieldmaskpb" | ||||
| 	"google.golang.org/protobuf/types/known/structpb" | ||||
| 	"google.golang.org/protobuf/types/known/timestamppb" | ||||
| 	"google.golang.org/protobuf/types/known/wrapperspb" | ||||
| ) | ||||
| 
 | ||||
| var valuesKeyRegexp = regexp.MustCompile(`^(.*)\[(.*)\]$`) | ||||
| 
 | ||||
| var currentQueryParser QueryParameterParser = &defaultQueryParser{} | ||||
| var currentQueryParser QueryParameterParser = &DefaultQueryParser{} | ||||
| 
 | ||||
| // QueryParameterParser defines interface for all query parameter parsers | ||||
| type QueryParameterParser interface { | ||||
|  | @ -36,14 +37,17 @@ func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utili | |||
| 	return currentQueryParser.Parse(msg, values, filter) | ||||
| } | ||||
| 
 | ||||
| type defaultQueryParser struct{} | ||||
| // DefaultQueryParser is a QueryParameterParser which implements the default | ||||
| // query parameters parsing behavior. | ||||
| // | ||||
| // See https://github.com/grpc-ecosystem/grpc-gateway/issues/2632 for more context. | ||||
| type DefaultQueryParser struct{} | ||||
| 
 | ||||
| // Parse populates "values" into "msg". | ||||
| // A value is ignored if its key starts with one of the elements in "filter". | ||||
| func (*defaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { | ||||
| func (*DefaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { | ||||
| 	for key, values := range values { | ||||
| 		match := valuesKeyRegexp.FindStringSubmatch(key) | ||||
| 		if len(match) == 3 { | ||||
| 		if match := valuesKeyRegexp.FindStringSubmatch(key); len(match) == 3 { | ||||
| 			key = match[1] | ||||
| 			values = append([]string{match[2]}, values...) | ||||
| 		} | ||||
|  | @ -175,10 +179,10 @@ func parseField(fieldDescriptor protoreflect.FieldDescriptor, value string) (pro | |||
| 		return protoreflect.ValueOfBool(v), nil | ||||
| 	case protoreflect.EnumKind: | ||||
| 		enum, err := protoregistry.GlobalTypes.FindEnumByName(fieldDescriptor.Enum().FullName()) | ||||
| 		switch { | ||||
| 		case errors.Is(err, protoregistry.NotFound): | ||||
| 			return protoreflect.Value{}, fmt.Errorf("enum %q is not registered", fieldDescriptor.Enum().FullName()) | ||||
| 		case err != nil: | ||||
| 		if err != nil { | ||||
| 			if errors.Is(err, protoregistry.NotFound) { | ||||
| 				return protoreflect.Value{}, fmt.Errorf("enum %q is not registered", fieldDescriptor.Enum().FullName()) | ||||
| 			} | ||||
| 			return protoreflect.Value{}, fmt.Errorf("failed to look up enum: %w", err) | ||||
| 		} | ||||
| 		// Look for enum by name | ||||
|  | @ -189,8 +193,7 @@ func parseField(fieldDescriptor protoreflect.FieldDescriptor, value string) (pro | |||
| 				return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) | ||||
| 			} | ||||
| 			// Look for enum by number | ||||
| 			v = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i)) | ||||
| 			if v == nil { | ||||
| 			if v = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i)); v == nil { | ||||
| 				return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) | ||||
| 			} | ||||
| 		} | ||||
|  | @ -234,7 +237,7 @@ func parseField(fieldDescriptor protoreflect.FieldDescriptor, value string) (pro | |||
| 	case protoreflect.StringKind: | ||||
| 		return protoreflect.ValueOfString(value), nil | ||||
| 	case protoreflect.BytesKind: | ||||
| 		v, err := base64.URLEncoding.DecodeString(value) | ||||
| 		v, err := Bytes(value) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
|  | @ -250,18 +253,12 @@ func parseMessage(msgDescriptor protoreflect.MessageDescriptor, value string) (p | |||
| 	var msg proto.Message | ||||
| 	switch msgDescriptor.FullName() { | ||||
| 	case "google.protobuf.Timestamp": | ||||
| 		if value == "null" { | ||||
| 			break | ||||
| 		} | ||||
| 		t, err := time.Parse(time.RFC3339Nano, value) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = timestamppb.New(t) | ||||
| 	case "google.protobuf.Duration": | ||||
| 		if value == "null" { | ||||
| 			break | ||||
| 		} | ||||
| 		d, err := time.ParseDuration(value) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
|  | @ -272,55 +269,67 @@ func parseMessage(msgDescriptor protoreflect.MessageDescriptor, value string) (p | |||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.DoubleValue{Value: v} | ||||
| 		msg = wrapperspb.Double(v) | ||||
| 	case "google.protobuf.FloatValue": | ||||
| 		v, err := strconv.ParseFloat(value, 32) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.FloatValue{Value: float32(v)} | ||||
| 		msg = wrapperspb.Float(float32(v)) | ||||
| 	case "google.protobuf.Int64Value": | ||||
| 		v, err := strconv.ParseInt(value, 10, 64) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.Int64Value{Value: v} | ||||
| 		msg = wrapperspb.Int64(v) | ||||
| 	case "google.protobuf.Int32Value": | ||||
| 		v, err := strconv.ParseInt(value, 10, 32) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.Int32Value{Value: int32(v)} | ||||
| 		msg = wrapperspb.Int32(int32(v)) | ||||
| 	case "google.protobuf.UInt64Value": | ||||
| 		v, err := strconv.ParseUint(value, 10, 64) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.UInt64Value{Value: v} | ||||
| 		msg = wrapperspb.UInt64(v) | ||||
| 	case "google.protobuf.UInt32Value": | ||||
| 		v, err := strconv.ParseUint(value, 10, 32) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.UInt32Value{Value: uint32(v)} | ||||
| 		msg = wrapperspb.UInt32(uint32(v)) | ||||
| 	case "google.protobuf.BoolValue": | ||||
| 		v, err := strconv.ParseBool(value) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.BoolValue{Value: v} | ||||
| 		msg = wrapperspb.Bool(v) | ||||
| 	case "google.protobuf.StringValue": | ||||
| 		msg = &wrapperspb.StringValue{Value: value} | ||||
| 		msg = wrapperspb.String(value) | ||||
| 	case "google.protobuf.BytesValue": | ||||
| 		v, err := base64.URLEncoding.DecodeString(value) | ||||
| 		v, err := Bytes(value) | ||||
| 		if err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &wrapperspb.BytesValue{Value: v} | ||||
| 		msg = wrapperspb.Bytes(v) | ||||
| 	case "google.protobuf.FieldMask": | ||||
| 		fm := &field_mask.FieldMask{} | ||||
| 		fm.Paths = append(fm.Paths, strings.Split(value, ",")...) | ||||
| 		msg = fm | ||||
| 	case "google.protobuf.Value": | ||||
| 		var v structpb.Value | ||||
| 		if err := protojson.Unmarshal([]byte(value), &v); err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &v | ||||
| 	case "google.protobuf.Struct": | ||||
| 		var v structpb.Struct | ||||
| 		if err := protojson.Unmarshal([]byte(value), &v); err != nil { | ||||
| 			return protoreflect.Value{}, err | ||||
| 		} | ||||
| 		msg = &v | ||||
| 	default: | ||||
| 		return protoreflect.Value{}, fmt.Errorf("unsupported message type: %q", string(msgDescriptor.FullName())) | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										6
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/BUILD.bazel
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/BUILD.bazel
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -8,6 +8,7 @@ go_library( | |||
|         "doc.go", | ||||
|         "pattern.go", | ||||
|         "readerfactory.go", | ||||
|         "string_array_flag.go", | ||||
|         "trie.go", | ||||
|     ], | ||||
|     importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/utilities", | ||||
|  | @ -16,7 +17,10 @@ go_library( | |||
| go_test( | ||||
|     name = "utilities_test", | ||||
|     size = "small", | ||||
|     srcs = ["trie_test.go"], | ||||
|     srcs = [ | ||||
|         "string_array_flag_test.go", | ||||
|         "trie_test.go", | ||||
|     ], | ||||
|     deps = [":utilities"], | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										3
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/readerfactory.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/readerfactory.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -3,13 +3,12 @@ package utilities | |||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| ) | ||||
| 
 | ||||
| // IOReaderFactory takes in an io.Reader and returns a function that will allow you to create a new reader that begins | ||||
| // at the start of the stream | ||||
| func IOReaderFactory(r io.Reader) (func() io.Reader, error) { | ||||
| 	b, err := ioutil.ReadAll(r) | ||||
| 	b, err := io.ReadAll(r) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										33
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| package utilities | ||||
| 
 | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // flagInterface is an cut down interface to `flag` | ||||
| type flagInterface interface { | ||||
| 	Var(value flag.Value, name string, usage string) | ||||
| } | ||||
| 
 | ||||
| // StringArrayFlag defines a flag with the specified name and usage string. | ||||
| // The return value is the address of a `StringArrayFlags` variable that stores the repeated values of the flag. | ||||
| func StringArrayFlag(f flagInterface, name string, usage string) *StringArrayFlags { | ||||
| 	value := &StringArrayFlags{} | ||||
| 	f.Var(value, name, usage) | ||||
| 	return value | ||||
| } | ||||
| 
 | ||||
| // StringArrayFlags is a wrapper of `[]string` to provider an interface for `flag.Var` | ||||
| type StringArrayFlags []string | ||||
| 
 | ||||
| // String returns a string representation of `StringArrayFlags` | ||||
| func (i *StringArrayFlags) String() string { | ||||
| 	return strings.Join(*i, ",") | ||||
| } | ||||
| 
 | ||||
| // Set appends a value to `StringArrayFlags` | ||||
| func (i *StringArrayFlags) Set(value string) error { | ||||
| 	*i = append(*i, value) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										2
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/trie.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/trie.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -40,7 +40,7 @@ func NewDoubleArray(seqs [][]string) *DoubleArray { | |||
| func registerTokens(da *DoubleArray, seqs [][]string) [][]int { | ||||
| 	var result [][]int | ||||
| 	for _, seq := range seqs { | ||||
| 		var encoded []int | ||||
| 		encoded := make([]int, 0, len(seq)) | ||||
| 		for _, token := range seq { | ||||
| 			if _, ok := da.Encoding[token]; !ok { | ||||
| 				da.Encoding[token] = len(da.Encoding) | ||||
|  |  | |||
							
								
								
									
										84
									
								
								vendor/go.opentelemetry.io/otel/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										84
									
								
								vendor/go.opentelemetry.io/otel/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -61,28 +61,68 @@ issues: | |||
| 
 | ||||
| linters-settings: | ||||
|   depguard: | ||||
|     # Check the list against standard lib. | ||||
|     # Default: false | ||||
|     include-go-root: true | ||||
|     # A list of packages for the list type specified. | ||||
|     # Default: [] | ||||
|     packages: | ||||
|       - "crypto/md5" | ||||
|       - "crypto/sha1" | ||||
|       - "crypto/**/pkix" | ||||
|     ignore-file-rules: | ||||
|       - "**/*_test.go" | ||||
|     additional-guards: | ||||
|       # Do not allow testing packages in non-test files. | ||||
|       - list-type: denylist | ||||
|         include-go-root: true | ||||
|         packages: | ||||
|           - testing | ||||
|           - github.com/stretchr/testify | ||||
|         ignore-file-rules: | ||||
|           - "**/*_test.go" | ||||
|           - "**/*test/*.go" | ||||
|           - "**/internal/matchers/*.go" | ||||
|     rules: | ||||
|       non-tests: | ||||
|         files: | ||||
|           - "!$test" | ||||
|           - "!**/*test/*.go" | ||||
|           - "!**/internal/matchers/*.go" | ||||
|         deny: | ||||
|           - pkg: "testing" | ||||
|           - pkg: "github.com/stretchr/testify" | ||||
|           - pkg: "crypto/md5" | ||||
|           - pkg: "crypto/sha1" | ||||
|           - pkg: "crypto/**/pkix" | ||||
|       otlp-internal: | ||||
|         files: | ||||
|           - "!**/exporters/otlp/internal/**/*.go" | ||||
|           # TODO: remove the following when otlpmetric/internal is removed. | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/oconf/envconfig.go" | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/oconf/options.go" | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/oconf/options_test.go" | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/otest/client_test.go" | ||||
|         deny: | ||||
|           - pkg: "go.opentelemetry.io/otel/exporters/otlp/internal" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|       otlptrace-internal: | ||||
|         files: | ||||
|           - "!**/exporters/otlp/otlptrace/*.go" | ||||
|           - "!**/exporters/otlp/otlptrace/internal/**.go" | ||||
|         deny: | ||||
|           - pkg: "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|       otlpmetric-internal: | ||||
|         files: | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/*.go" | ||||
|           - "!**/exporters/otlp/otlpmetric/internal/**/*.go" | ||||
|         deny: | ||||
|           - pkg: "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|       otel-internal: | ||||
|         files: | ||||
|           - "**/sdk/*.go" | ||||
|           - "**/sdk/**/*.go" | ||||
|           - "**/exporters/*.go" | ||||
|           - "**/exporters/**/*.go" | ||||
|           - "**/schema/*.go" | ||||
|           - "**/schema/**/*.go" | ||||
|           - "**/metric/*.go" | ||||
|           - "**/metric/**/*.go" | ||||
|           - "**/bridge/*.go" | ||||
|           - "**/bridge/**/*.go" | ||||
|           - "**/example/*.go" | ||||
|           - "**/example/**/*.go" | ||||
|           - "**/trace/*.go" | ||||
|           - "**/trace/**/*.go" | ||||
|         deny: | ||||
|           - pkg: "go.opentelemetry.io/otel/internal$" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|           - pkg: "go.opentelemetry.io/otel/internal/attribute" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|           - pkg: "go.opentelemetry.io/otel/internal/internaltest" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|           - pkg: "go.opentelemetry.io/otel/internal/matchers" | ||||
|             desc: Do not use cross-module internal packages. | ||||
|   godot: | ||||
|     exclude: | ||||
|       # Exclude links. | ||||
|  |  | |||
							
								
								
									
										102
									
								
								vendor/go.opentelemetry.io/otel/CHANGELOG.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/go.opentelemetry.io/otel/CHANGELOG.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -8,6 +8,99 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm | |||
| 
 | ||||
| ## [Unreleased] | ||||
| 
 | ||||
| ## [1.17.0/0.40.0/0.0.5] 2023-08-28 | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - Export the `ManualReader` struct in `go.opentelemetry.io/otel/sdk/metric`. (#4244) | ||||
| - Export the `PeriodicReader` struct in `go.opentelemetry.io/otel/sdk/metric`. (#4244) | ||||
| - Add support for exponential histogram aggregations. | ||||
|   A histogram can be configured as an exponential histogram using a view with `"go.opentelemetry.io/otel/sdk/metric".ExponentialHistogram` as the aggregation. (#4245) | ||||
| - Export the `Exporter` struct in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4272) | ||||
| - Export the `Exporter` struct in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4272) | ||||
| - The exporters in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` now support the `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` environment variable. (#4287) | ||||
| - Add `WithoutCounterSuffixes` option in `go.opentelemetry.io/otel/exporters/prometheus` to disable addition of `_total` suffixes. (#4306) | ||||
| - Add info and debug logging to the metric SDK in `go.opentelemetry.io/otel/sdk/metric`. (#4315) | ||||
| - The `go.opentelemetry.io/otel/semconv/v1.21.0` package. | ||||
|   The package contains semantic conventions from the `v1.21.0` version of the OpenTelemetry Semantic Conventions. (#4362) | ||||
| - Accept 201 to 299 HTTP status as success in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` and `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4365) | ||||
| - Document the `Temporality` and `Aggregation` methods of the `"go.opentelemetry.io/otel/sdk/metric".Exporter"` need to be concurrent safe. (#4381) | ||||
| - Expand the set of units supported by the Prometheus exporter, and don't add unit suffixes if they are already present in `go.opentelemetry.op/otel/exporters/prometheus` (#4374) | ||||
| - Move the `Aggregation` interface and its implementations from `go.opentelemetry.io/otel/sdk/metric/aggregation` to `go.opentelemetry.io/otel/sdk/metric`. (#4435) | ||||
| - The exporters in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` now support the `OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION` environment variable. (#4437) | ||||
| - Add the `NewAllowKeysFilter` and `NewDenyKeysFilter` functions to `go.opentelemetry.io/otel/attribute` to allow convenient creation of allow-keys and deny-keys filters. (#4444) | ||||
| - Support Go 1.21. (#4463) | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| - Starting from `v1.21.0` of semantic conventions, `go.opentelemetry.io/otel/semconv/{version}/httpconv` and `go.opentelemetry.io/otel/semconv/{version}/netconv` packages will no longer be published. (#4145) | ||||
| - Log duplicate instrument conflict at a warning level instead of info in `go.opentelemetry.io/otel/sdk/metric`. (#4202) | ||||
| - Return an error on the creation of new instruments in `go.opentelemetry.io/otel/sdk/metric` if their name doesn't pass regexp validation. (#4210) | ||||
| - `NewManualReader` in `go.opentelemetry.io/otel/sdk/metric` returns `*ManualReader` instead of `Reader`. (#4244) | ||||
| - `NewPeriodicReader` in `go.opentelemetry.io/otel/sdk/metric` returns `*PeriodicReader` instead of `Reader`. (#4244) | ||||
| - Count the Collect time in the `PeriodicReader` timeout in `go.opentelemetry.io/otel/sdk/metric`. (#4221) | ||||
| - The function `New` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` returns `*Exporter` instead of `"go.opentelemetry.io/otel/sdk/metric".Exporter`. (#4272) | ||||
| - The function `New` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` returns `*Exporter` instead of `"go.opentelemetry.io/otel/sdk/metric".Exporter`. (#4272) | ||||
| - If an attribute set is omitted from an async callback, the previous value will no longer be exported in `go.opentelemetry.io/otel/sdk/metric`. (#4290) | ||||
| - If an attribute set is observed multiple times in an async callback in `go.opentelemetry.io/otel/sdk/metric`, the values will be summed instead of the last observation winning. (#4289) | ||||
| - Allow the explicit bucket histogram aggregation to be used for the up-down counter, observable counter, observable up-down counter, and observable gauge in the `go.opentelemetry.io/otel/sdk/metric` package. (#4332) | ||||
| - Restrict `Meter`s in `go.opentelemetry.io/otel/sdk/metric` to only register and collect instruments it created. (#4333) | ||||
| - `PeriodicReader.Shutdown` and `PeriodicReader.ForceFlush` in `go.opentelemetry.io/otel/sdk/metric` now apply the periodic reader's timeout to the operation if the user provided context does not contain a deadline. (#4356, #4377) | ||||
| - Upgrade all use of `go.opentelemetry.io/otel/semconv` to use `v1.21.0`. (#4408) | ||||
| - Increase instrument name maximum length from 63 to 255 characters in `go.opentelemetry.io/otel/sdk/metric`. (#4434) | ||||
| - Add `go.opentelemetry.op/otel/sdk/metric.WithProducer` as an `Option` for `"go.opentelemetry.io/otel/sdk/metric".NewManualReader` and `"go.opentelemetry.io/otel/sdk/metric".NewPeriodicReader`. (#4346) | ||||
| 
 | ||||
| ### Removed | ||||
| 
 | ||||
| - Remove `Reader.RegisterProducer` in `go.opentelemetry.io/otel/metric`. | ||||
|   Use the added `WithProducer` option instead. (#4346) | ||||
| - Remove `Reader.ForceFlush` in `go.opentelemetry.io/otel/metric`. | ||||
|   Notice that `PeriodicReader.ForceFlush` is still available. (#4375) | ||||
| 
 | ||||
| ### Fixed | ||||
| 
 | ||||
| - Correctly format log messages from the `go.opentelemetry.io/otel/exporters/zipkin` exporter. (#4143) | ||||
| - Log an error for calls to `NewView` in `go.opentelemetry.io/otel/sdk/metric` that have empty criteria. (#4307) | ||||
| - Fix `"go.opentelemetry.io/otel/sdk/resource".WithHostID()` to not set an empty `host.id`. (#4317) | ||||
| - Use the instrument identifying fields to cache aggregators and determine duplicate instrument registrations in `go.opentelemetry.io/otel/sdk/metric`. (#4337) | ||||
| - Detect duplicate instruments for case-insensitive names in `go.opentelemetry.io/otel/sdk/metric`. (#4338) | ||||
| - The `ManualReader` will not panic if `AggregationSelector` returns `nil` in `go.opentelemetry.io/otel/sdk/metric`. (#4350) | ||||
| - If a `Reader`'s `AggregationSelector` returns `nil` or `DefaultAggregation` the pipeline will use the default aggregation. (#4350) | ||||
| - Log a suggested view that fixes instrument conflicts in `go.opentelemetry.io/otel/sdk/metric`. (#4349) | ||||
| - Fix possible panic, deadlock and race condition in batch span processor in `go.opentelemetry.io/otel/sdk/trace`. (#4353) | ||||
| - Improve context cancellation handling in batch span processor's `ForceFlush` in  `go.opentelemetry.io/otel/sdk/trace`. (#4369) | ||||
| - Decouple `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal` from `go.opentelemetry.io/otel/exporters/otlp/internal` using gotmpl. (#4397, #3846) | ||||
| - Decouple `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal` from `go.opentelemetry.io/otel/exporters/otlp/internal` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal` using gotmpl. (#4404, #3846) | ||||
| - Decouple `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal` from `go.opentelemetry.io/otel/exporters/otlp/internal` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal` using gotmpl. (#4407, #3846) | ||||
| - Decouple `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal` from `go.opentelemetry.io/otel/exporters/otlp/internal` and `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal` using gotmpl. (#4400, #3846) | ||||
| - Decouple `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal` from `go.opentelemetry.io/otel/exporters/otlp/internal` and `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal` using gotmpl. (#4401, #3846) | ||||
| - Do not block the metric SDK when OTLP metric exports are blocked in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#3925, #4395) | ||||
| - Do not append `_total` if the counter already has that suffix for the Prometheus exproter in `go.opentelemetry.io/otel/exporter/prometheus`. (#4373) | ||||
| - Fix resource detection data race in `go.opentelemetry.io/otel/sdk/resource`. (#4409) | ||||
| - Use the first-seen instrument name during instrument name conflicts in `go.opentelemetry.io/otel/sdk/metric`. (#4428) | ||||
| 
 | ||||
| ### Deprecated | ||||
| 
 | ||||
| - The `go.opentelemetry.io/otel/exporters/jaeger` package is deprecated. | ||||
|   OpenTelemetry dropped support for Jaeger exporter in July 2023. | ||||
|   Use `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` | ||||
|   or `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` instead. (#4423) | ||||
| - The `go.opentelemetry.io/otel/example/jaeger` package is deprecated. (#4423) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal` package is deprecated. (#4420) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/oconf` package is deprecated. (#4420) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otest` package is deprecated. (#4420) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/transform` package is deprecated. (#4420) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/internal` package is deprecated. (#4421) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/internal/envconfig` package is deprecated. (#4421) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/internal/retry` package is deprecated. (#4421) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal` package is deprecated. (#4425) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/envconfig` package is deprecated. (#4425) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig` package is deprecated. (#4425) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlptracetest` package is deprecated. (#4425) | ||||
| - The `go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/retry` package is deprecated. (#4425) | ||||
| - The `go.opentelemetry.io/otel/sdk/metric/aggregation` package is deprecated. | ||||
|   Use the aggregation types added to `go.opentelemetry.io/otel/sdk/metric` instead. (#4435) | ||||
| 
 | ||||
| ## [1.16.0/0.39.0] 2023-05-18 | ||||
| 
 | ||||
| This release contains the first stable release of the OpenTelemetry Go [metric API]. | ||||
|  | @ -20,10 +113,14 @@ See our [versioning policy](VERSIONING.md) for more information about these stab | |||
|   The package contains semantic conventions from the `v1.19.0` version of the OpenTelemetry specification. (#3848) | ||||
| - The `go.opentelemetry.io/otel/semconv/v1.20.0` package. | ||||
|   The package contains semantic conventions from the `v1.20.0` version of the OpenTelemetry specification. (#4078) | ||||
| - The Exponential Histogram data types in `go.opentelemetry.io/otel/sdk/metric/metricdata`. (#4165) | ||||
| - OTLP metrics exporter now supports the Exponential Histogram Data Type. (#4222) | ||||
| - Fix serialization of `time.Time` zero values in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` packages. (#4271) | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| - Use `strings.Cut()` instead of `string.SplitN()` for better readability and memory use. (#4049) | ||||
| - `MeterProvider` returns noop meters once it has been shutdown. (#4154) | ||||
| 
 | ||||
| ### Removed | ||||
| 
 | ||||
|  | @ -188,6 +285,8 @@ This release drops the compatibility guarantee of [Go 1.18]. | |||
| 
 | ||||
| - Handle empty environment variable as it they were not set. (#3764) | ||||
| - Clarify the `httpconv` and `netconv` packages in `go.opentelemetry.io/otel/semconv/*` provide tracing semantic conventions. (#3823) | ||||
| - Fix race conditions in `go.opentelemetry.io/otel/exporters/metric/prometheus` that could cause a panic. (#3899) | ||||
| - Fix sending nil `scopeInfo` to metrics channel in `go.opentelemetry.io/otel/exporters/metric/prometheus` that could cause a panic in `github.com/prometheus/client_golang/prometheus`. (#3899) | ||||
| 
 | ||||
| ### Deprecated | ||||
| 
 | ||||
|  | @ -2492,7 +2591,8 @@ It contains api and sdk for trace and meter. | |||
| - CircleCI build CI manifest files. | ||||
| - CODEOWNERS file to track owners of this project. | ||||
| 
 | ||||
| [Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.16.0...HEAD | ||||
| [Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.17.0...HEAD | ||||
| [1.17.0/0.40.0/0.0.5]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.17.0 | ||||
| [1.16.0/0.39.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.16.0 | ||||
| [1.16.0-rc.1/0.39.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.16.0-rc.1 | ||||
| [1.15.1/0.38.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.15.1 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								vendor/go.opentelemetry.io/otel/CODEOWNERS
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/go.opentelemetry.io/otel/CODEOWNERS
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -14,4 +14,4 @@ | |||
| 
 | ||||
| * @MrAlias @Aneurysm9 @evantorrie @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu | ||||
| 
 | ||||
| CODEOWNERS @MrAlias @Aneurysm9 @MadVikingGod | ||||
| CODEOWNERS @MrAlias @MadVikingGod @pellared | ||||
							
								
								
									
										90
									
								
								vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										90
									
								
								vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -179,23 +179,23 @@ For a deeper discussion, see | |||
| 
 | ||||
| ## Documentation | ||||
| 
 | ||||
| Each non-example Go Module should have its own `README.md` containing: | ||||
| Each (non-internal, non-test) package must be documented using | ||||
| [Go Doc Comments](https://go.dev/doc/comment), | ||||
| preferably in a `doc.go` file. | ||||
| 
 | ||||
| - A pkg.go.dev badge which can be generated [here](https://pkg.go.dev/badge/). | ||||
| - Brief description. | ||||
| - Installation instructions (and requirements if applicable). | ||||
| - Hyperlink to an example. Depending on the component the example can be: | ||||
|   - An `example_test.go` like [here](exporters/stdout/stdouttrace/example_test.go). | ||||
|   - A sample Go application with its own `README.md`, like [here](example/zipkin). | ||||
| - Additional documentation sections such us: | ||||
|   - Configuration, | ||||
|   - Contributing, | ||||
|   - References. | ||||
| Prefer using [Examples](https://pkg.go.dev/testing#hdr-Examples) | ||||
| instead of putting code snippets in Go doc comments. | ||||
| In some cases, you can even create [Testable Examples](https://go.dev/blog/examples). | ||||
| 
 | ||||
| [Here](exporters/jaeger/README.md) is an example of a concise `README.md`. | ||||
| You can install and run a "local Go Doc site" in the following way: | ||||
| 
 | ||||
| Moreover, it should be possible to navigate to any `README.md` from the | ||||
| root `README.md`. | ||||
|   ```sh | ||||
|   go install golang.org/x/pkgsite/cmd/pkgsite@latest | ||||
|   pkgsite | ||||
|   ``` | ||||
| 
 | ||||
| [`go.opentelemetry.io/otel/metric`](https://pkg.go.dev/go.opentelemetry.io/otel/metric) | ||||
| is an example of a very well-documented package. | ||||
| 
 | ||||
| ## Style Guide | ||||
| 
 | ||||
|  | @ -475,8 +475,33 @@ documentation are allowed to be extended with additional methods. | |||
| 
 | ||||
| > Warning: methods may be added to this interface in minor releases. | ||||
| 
 | ||||
| These interfaces are defined by the OpenTelemetry specification and will be | ||||
| updated as the specification evolves. | ||||
| 
 | ||||
| Otherwise, stable interfaces MUST NOT be modified. | ||||
| 
 | ||||
| #### How to Change Specification Interfaces | ||||
| 
 | ||||
| When an API change must be made, we will update the SDK with the new method one | ||||
| release before the API change. This will allow the SDK one version before the | ||||
| API change to work seamlessly with the new API. | ||||
| 
 | ||||
| If an incompatible version of the SDK is used with the new API the application | ||||
| will fail to compile. | ||||
| 
 | ||||
| #### How Not to Change Specification Interfaces | ||||
| 
 | ||||
| We have explored using a v2 of the API to change interfaces and found that there | ||||
| was no way to introduce a v2 and have it work seamlessly with the v1 of the API. | ||||
| Problems happened with libraries that upgraded to v2 when an application did not, | ||||
| and would not produce any telemetry. | ||||
| 
 | ||||
| More detail of the approaches considered and their limitations can be found in | ||||
| the [Use a V2 API to evolve interfaces](https://github.com/open-telemetry/opentelemetry-go/issues/3920) | ||||
| issue. | ||||
| 
 | ||||
| #### How to Change Other Interfaces | ||||
| 
 | ||||
| If new functionality is needed for an interface that cannot be changed it MUST | ||||
| be added by including an additional interface. That added interface can be a | ||||
| simple interface for the specific functionality that you want to add or it can | ||||
|  | @ -531,6 +556,37 @@ functionality should be added, each one will need their own super-set | |||
| interfaces and will duplicate the pattern. For this reason, the simple targeted | ||||
| interface that defines the specific functionality should be preferred. | ||||
| 
 | ||||
| ### Testing | ||||
| 
 | ||||
| The tests should never leak goroutines. | ||||
| 
 | ||||
| Use the term `ConcurrentSafe` in the test name when it aims to verify the | ||||
| absence of race conditions. | ||||
| 
 | ||||
| ### Internal packages | ||||
| 
 | ||||
| The use of internal packages should be scoped to a single module. A sub-module | ||||
| should never import from a parent internal package. This creates a coupling | ||||
| between the two modules where a user can upgrade the parent without the child | ||||
| and if the internal package API has changed it will fail to upgrade[^3]. | ||||
| 
 | ||||
| There are two known exceptions to this rule: | ||||
| 
 | ||||
| - `go.opentelemetry.io/otel/internal/global` | ||||
|   - This package manages global state for all of opentelemetry-go. It needs to | ||||
|   be a single package in order to ensure the uniqueness of the global state. | ||||
| - `go.opentelemetry.io/otel/internal/baggage` | ||||
|   - This package provides values in a `context.Context` that need to be | ||||
|   recognized by `go.opentelemetry.io/otel/baggage` and | ||||
|   `go.opentelemetry.io/otel/bridge/opentracing` but remain private. | ||||
| 
 | ||||
| If you have duplicate code in multiple modules, make that code into a Go | ||||
| template stored in `go.opentelemetry.io/otel/internal/shared` and use [gotmpl] | ||||
| to render the templates in the desired locations. See [#4404] for an example of | ||||
| this. | ||||
| 
 | ||||
| [^3]: https://github.com/open-telemetry/opentelemetry-go/issues/3548 | ||||
| 
 | ||||
| ## Approvers and Maintainers | ||||
| 
 | ||||
| ### Approvers | ||||
|  | @ -538,14 +594,14 @@ interface that defines the specific functionality should be preferred. | |||
| - [Evan Torrie](https://github.com/evantorrie), Verizon Media | ||||
| - [Sam Xie](https://github.com/XSAM), Cisco/AppDynamics | ||||
| - [David Ashpole](https://github.com/dashpole), Google | ||||
| - [Robert Pająk](https://github.com/pellared), Splunk | ||||
| - [Chester Cheung](https://github.com/hanyuancheung), Tencent | ||||
| - [Damien Mathieu](https://github.com/dmathieu), Elastic | ||||
| - [Anthony Mirabella](https://github.com/Aneurysm9), AWS | ||||
| 
 | ||||
| ### Maintainers | ||||
| 
 | ||||
| - [Aaron Clawson](https://github.com/MadVikingGod), LightStep | ||||
| - [Anthony Mirabella](https://github.com/Aneurysm9), AWS | ||||
| - [Robert Pająk](https://github.com/pellared), Splunk | ||||
| - [Tyler Yahn](https://github.com/MrAlias), Splunk | ||||
| 
 | ||||
| ### Emeritus | ||||
|  | @ -560,3 +616,5 @@ repo](https://github.com/open-telemetry/community/blob/main/community-membership | |||
| 
 | ||||
| [Approver]: #approvers | ||||
| [Maintainer]: #maintainers | ||||
| [gotmpl]: https://pkg.go.dev/go.opentelemetry.io/build-tools/gotmpl | ||||
| [#4404]: https://github.com/open-telemetry/opentelemetry-go/pull/4404 | ||||
|  |  | |||
							
								
								
									
										60
									
								
								vendor/go.opentelemetry.io/otel/Makefile
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								vendor/go.opentelemetry.io/otel/Makefile
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -25,7 +25,7 @@ TIMEOUT = 60 | |||
| .DEFAULT_GOAL := precommit | ||||
| 
 | ||||
| .PHONY: precommit ci | ||||
| precommit: generate dependabot-generate license-check vanity-import-fix misspell go-mod-tidy golangci-lint-fix test-default | ||||
| precommit: generate dependabot-generate license-check misspell go-mod-tidy golangci-lint-fix test-default | ||||
| ci: generate dependabot-check license-check lint vanity-import-check build test-default check-clean-work-tree test-coverage | ||||
| 
 | ||||
| # Tools
 | ||||
|  | @ -71,8 +71,14 @@ $(TOOLS)/porto: PACKAGE=github.com/jcchavezs/porto/cmd/porto | |||
| GOJQ = $(TOOLS)/gojq | ||||
| $(TOOLS)/gojq: PACKAGE=github.com/itchyny/gojq/cmd/gojq | ||||
| 
 | ||||
| GOTMPL = $(TOOLS)/gotmpl | ||||
| $(GOTMPL): PACKAGE=go.opentelemetry.io/build-tools/gotmpl | ||||
| 
 | ||||
| GORELEASE = $(TOOLS)/gorelease | ||||
| $(GORELEASE): PACKAGE=golang.org/x/exp/cmd/gorelease | ||||
| 
 | ||||
| .PHONY: tools | ||||
| tools: $(CROSSLINK) $(DBOTCONF) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) | ||||
| tools: $(CROSSLINK) $(DBOTCONF) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE) | ||||
| 
 | ||||
| # Virtualized python tools via docker
 | ||||
| 
 | ||||
|  | @ -110,13 +116,24 @@ $(CODESPELL): PACKAGE=codespell | |||
| # Generate
 | ||||
| 
 | ||||
| .PHONY: generate | ||||
| generate: go-generate vanity-import-fix | ||||
| 
 | ||||
| generate: $(OTEL_GO_MOD_DIRS:%=generate/%) | ||||
| generate/%: DIR=$* | ||||
| generate/%: | $(STRINGER) $(PORTO) | ||||
| .PHONY: go-generate | ||||
| go-generate: $(OTEL_GO_MOD_DIRS:%=go-generate/%) | ||||
| go-generate/%: DIR=$* | ||||
| go-generate/%: | $(STRINGER) $(GOTMPL) | ||||
| 	@echo "$(GO) generate $(DIR)/..." \
 | ||||
| 		&& cd $(DIR) \
 | ||||
| 		&& PATH="$(TOOLS):$${PATH}" $(GO) generate ./... && $(PORTO) -w . | ||||
| 		&& PATH="$(TOOLS):$${PATH}" $(GO) generate ./... | ||||
| 
 | ||||
| .PHONY: vanity-import-fix | ||||
| vanity-import-fix: | $(PORTO) | ||||
| 	@$(PORTO) --include-internal -w . | ||||
| 
 | ||||
| # Generate go.work file for local development.
 | ||||
| .PHONY: go-work | ||||
| go-work: | $(CROSSLINK) | ||||
| 	$(CROSSLINK) work --root=$(shell pwd) | ||||
| 
 | ||||
| # Build
 | ||||
| 
 | ||||
|  | @ -203,11 +220,7 @@ lint: misspell lint-modules golangci-lint | |||
| 
 | ||||
| .PHONY: vanity-import-check | ||||
| vanity-import-check: | $(PORTO) | ||||
| 	@$(PORTO) --include-internal -l . || echo "(run: make vanity-import-fix)" | ||||
| 
 | ||||
| .PHONY: vanity-import-fix | ||||
| vanity-import-fix: | $(PORTO) | ||||
| 	@$(PORTO) --include-internal -w . | ||||
| 	@$(PORTO) --include-internal -l . || ( echo "(run: make vanity-import-fix)"; exit 1 ) | ||||
| 
 | ||||
| .PHONY: misspell | ||||
| misspell: | $(MISSPELL) | ||||
|  | @ -220,7 +233,7 @@ codespell: | $(CODESPELL) | |||
| .PHONY: license-check | ||||
| license-check: | ||||
| 	@licRes=$$(for f in $$(find . -type f \( -iname '*.go' -o -iname '*.sh' \) ! -path '**/third_party/*' ! -path './.git/*' ) ; do \
 | ||||
| 	           awk '/Copyright The OpenTelemetry Authors|generated|GENERATED/ && NR<=3 { found=1; next } END { if (!found) print FILENAME }' $$f; \
 | ||||
| 	           awk '/Copyright The OpenTelemetry Authors|generated|GENERATED/ && NR<=4 { found=1; next } END { if (!found) print FILENAME }' $$f; \
 | ||||
| 	   done); \
 | ||||
| 	   if [ -n "$${licRes}" ]; then \
 | ||||
| 	           echo "license header checking failed:"; echo "$${licRes}"; \
 | ||||
|  | @ -230,7 +243,7 @@ license-check: | |||
| DEPENDABOT_CONFIG = .github/dependabot.yml | ||||
| .PHONY: dependabot-check | ||||
| dependabot-check: | $(DBOTCONF) | ||||
| 	@$(DBOTCONF) verify $(DEPENDABOT_CONFIG) || echo "(run: make dependabot-generate)" | ||||
| 	@$(DBOTCONF) verify $(DEPENDABOT_CONFIG) || ( echo "(run: make dependabot-generate)"; exit 1 ) | ||||
| 
 | ||||
| .PHONY: dependabot-generate | ||||
| dependabot-generate: | $(DBOTCONF) | ||||
|  | @ -249,14 +262,23 @@ check-clean-work-tree: | |||
| SEMCONVPKG ?= "semconv/" | ||||
| .PHONY: semconv-generate | ||||
| semconv-generate: | $(SEMCONVGEN) $(SEMCONVKIT) | ||||
| 	[ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry specification tag"; exit 1 ) | ||||
| 	[ "$(OTEL_SPEC_REPO)" ] || ( echo "OTEL_SPEC_REPO unset: missing path to opentelemetry specification repo"; exit 1 ) | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SPEC_REPO)/semantic_conventions/." --only=span -p conventionType=trace -f trace.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SPEC_REPO)/semantic_conventions/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SPEC_REPO)/semantic_conventions/." --only=event -p conventionType=event -f event.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SPEC_REPO)/semantic_conventions/." --only=resource -p conventionType=resource -f resource.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	[ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 ) | ||||
| 	[ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 ) | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=span -p conventionType=trace -f trace.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=event -p conventionType=event -f event.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=resource -p conventionType=resource -f resource.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" | ||||
| 	$(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)" | ||||
| 
 | ||||
| .PHONY: gorelease | ||||
| gorelease: $(OTEL_GO_MOD_DIRS:%=gorelease/%) | ||||
| gorelease/%: DIR=$* | ||||
| gorelease/%:| $(GORELEASE) | ||||
| 	@echo "gorelease in $(DIR):" \
 | ||||
| 		&& cd $(DIR) \
 | ||||
| 		&& $(GORELEASE) \
 | ||||
| 		|| echo "" | ||||
| 
 | ||||
| .PHONY: prerelease | ||||
| prerelease: | $(MULTIMOD) | ||||
| 	@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 ) | ||||
|  |  | |||
							
								
								
									
										37
									
								
								vendor/go.opentelemetry.io/otel/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/go.opentelemetry.io/otel/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -11,22 +11,25 @@ It provides a set of APIs to directly measure performance and behavior of your s | |||
| 
 | ||||
| ## Project Status | ||||
| 
 | ||||
| | Signal  | Status     | Project | | ||||
| | ------- | ---------- | ------- | | ||||
| | Traces  | Stable     | N/A     | | ||||
| | Metrics | Beta       | N/A     | | ||||
| | Logs    | Frozen [1] | N/A     | | ||||
| | Signal  | Status     | Project               | | ||||
| |---------|------------|-----------------------| | ||||
| | Traces  | Stable     | N/A                   | | ||||
| | Metrics | Mixed [1]  | [Go: Metric SDK (GA)] | | ||||
| | Logs    | Frozen [2] | N/A                   | | ||||
| 
 | ||||
| - [1]: The Logs signal development is halted for this project while we develop both Traces and Metrics. | ||||
| [Go: Metric SDK (GA)]: https://github.com/orgs/open-telemetry/projects/34 | ||||
| 
 | ||||
| - [1]: [Metrics API](https://pkg.go.dev/go.opentelemetry.io/otel/metric) is Stable. [Metrics SDK](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric) is Beta. | ||||
| - [2]: The Logs signal development is halted for this project while we stabilize the Metrics SDK. | ||||
|    No Logs Pull Requests are currently being accepted. | ||||
| 
 | ||||
| Progress and status specific to this repository is tracked in our local | ||||
| Progress and status specific to this repository is tracked in our | ||||
| [project boards](https://github.com/open-telemetry/opentelemetry-go/projects) | ||||
| and | ||||
| [milestones](https://github.com/open-telemetry/opentelemetry-go/milestones). | ||||
| 
 | ||||
| Project versioning information and stability guarantees can be found in the | ||||
| [versioning documentation](./VERSIONING.md). | ||||
| [versioning documentation](VERSIONING.md). | ||||
| 
 | ||||
| ### Compatibility | ||||
| 
 | ||||
|  | @ -49,15 +52,20 @@ stop ensuring compatibility with these versions in the following manner: | |||
| Currently, this project supports the following environments. | ||||
| 
 | ||||
| | OS      | Go Version | Architecture | | ||||
| | ------- | ---------- | ------------ | | ||||
| |---------|------------|--------------| | ||||
| | Ubuntu  | 1.21       | amd64        | | ||||
| | Ubuntu  | 1.20       | amd64        | | ||||
| | Ubuntu  | 1.19       | amd64        | | ||||
| | Ubuntu  | 1.21       | 386          | | ||||
| | Ubuntu  | 1.20       | 386          | | ||||
| | Ubuntu  | 1.19       | 386          | | ||||
| | MacOS   | 1.21       | amd64        | | ||||
| | MacOS   | 1.20       | amd64        | | ||||
| | MacOS   | 1.19       | amd64        | | ||||
| | Windows | 1.21       | amd64        | | ||||
| | Windows | 1.20       | amd64        | | ||||
| | Windows | 1.19       | amd64        | | ||||
| | Windows | 1.21       | 386          | | ||||
| | Windows | 1.20       | 386          | | ||||
| | Windows | 1.19       | 386          | | ||||
| 
 | ||||
|  | @ -97,12 +105,11 @@ export pipeline to send that telemetry to an observability platform. | |||
| All officially supported exporters for the OpenTelemetry project are contained in the [exporters directory](./exporters). | ||||
| 
 | ||||
| | Exporter                              | Metrics | Traces | | ||||
| | :-----------------------------------: | :-----: | :----: | | ||||
| | [Jaeger](./exporters/jaeger/)         |         | ✓      | | ||||
| | [OTLP](./exporters/otlp/)             | ✓       | ✓      | | ||||
| | [Prometheus](./exporters/prometheus/) | ✓       |        | | ||||
| | [stdout](./exporters/stdout/)         | ✓       | ✓      | | ||||
| | [Zipkin](./exporters/zipkin/)         |         | ✓      | | ||||
| |---------------------------------------|:-------:|:------:| | ||||
| | [OTLP](./exporters/otlp/)             |    ✓    |   ✓    | | ||||
| | [Prometheus](./exporters/prometheus/) |    ✓    |        | | ||||
| | [stdout](./exporters/stdout/)         |    ✓    |   ✓    | | ||||
| | [Zipkin](./exporters/zipkin/)         |         |   ✓    | | ||||
| 
 | ||||
| ## Contributing | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										31
									
								
								vendor/go.opentelemetry.io/otel/RELEASING.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								vendor/go.opentelemetry.io/otel/RELEASING.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -2,27 +2,30 @@ | |||
| 
 | ||||
| ## Semantic Convention Generation | ||||
| 
 | ||||
| New versions of the [OpenTelemetry Specification] mean new versions of the `semconv` package need to be generated. | ||||
| New versions of the [OpenTelemetry Semantic Conventions] mean new versions of the `semconv` package need to be generated. | ||||
| The `semconv-generate` make target is used for this. | ||||
| 
 | ||||
| 1. Checkout a local copy of the [OpenTelemetry Specification] to the desired release tag. | ||||
| 1. Checkout a local copy of the [OpenTelemetry Semantic Conventions] to the desired release tag. | ||||
| 2. Pull the latest `otel/semconvgen` image: `docker pull otel/semconvgen:latest` | ||||
| 3. Run the `make semconv-generate ...` target from this repository. | ||||
| 
 | ||||
| For example, | ||||
| 
 | ||||
| ```sh | ||||
| export TAG="v1.13.0" # Change to the release version you are generating. | ||||
| export OTEL_SPEC_REPO="/absolute/path/to/opentelemetry-specification" | ||||
| export TAG="v1.21.0" # Change to the release version you are generating. | ||||
| export OTEL_SEMCONV_REPO="/absolute/path/to/opentelemetry/semantic-conventions" | ||||
| docker pull otel/semconvgen:latest | ||||
| make semconv-generate # Uses the exported TAG and OTEL_SPEC_REPO. | ||||
| make semconv-generate # Uses the exported TAG and OTEL_SEMCONV_REPO. | ||||
| ``` | ||||
| 
 | ||||
| This should create a new sub-package of [`semconv`](./semconv). | ||||
| Ensure things look correct before submitting a pull request to include the addition. | ||||
| 
 | ||||
| **Note**, the generation code was changed to generate versions >= 1.13. | ||||
| To generate versions prior to this, checkout the old release of this repository (i.e. [2fe8861](https://github.com/open-telemetry/opentelemetry-go/commit/2fe8861a24e20088c065b116089862caf9e3cd8b)). | ||||
| ## Breaking changes validation | ||||
| 
 | ||||
| You can run `make gorelease` that runs [gorelease](https://pkg.go.dev/golang.org/x/exp/cmd/gorelease) to ensure that there are no unwanted changes done in the public API. | ||||
| 
 | ||||
| You can check/report problems with `gorelease` [here](https://golang.org/issues/26420). | ||||
| 
 | ||||
| ## Pre-Release | ||||
| 
 | ||||
|  | @ -120,7 +123,17 @@ Once verified be sure to [make a release for the `contrib` repository](https://g | |||
| 
 | ||||
| ### Website Documentation | ||||
| 
 | ||||
| Update [the documentation](./website_docs) for [the OpenTelemetry website](https://opentelemetry.io/docs/go/). | ||||
| Update the [Go instrumentation documentation] in the OpenTelemetry website under [content/en/docs/instrumentation/go]. | ||||
| Importantly, bump any package versions referenced to be the latest one you just released and ensure all code examples still compile and are accurate. | ||||
| 
 | ||||
| [OpenTelemetry Specification]: https://github.com/open-telemetry/opentelemetry-specification | ||||
| [OpenTelemetry Semantic Conventions]: https://github.com/open-telemetry/semantic-conventions | ||||
| [Go instrumentation documentation]: https://opentelemetry.io/docs/instrumentation/go/ | ||||
| [content/en/docs/instrumentation/go]: https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/instrumentation/go | ||||
| 
 | ||||
| ### Demo Repository | ||||
| 
 | ||||
| Bump the dependencies in the following Go services: | ||||
| 
 | ||||
| - [`accountingservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accountingservice) | ||||
| - [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkoutservice) | ||||
| - [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/productcatalogservice) | ||||
|  |  | |||
							
								
								
									
										60
									
								
								vendor/go.opentelemetry.io/otel/attribute/filter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								vendor/go.opentelemetry.io/otel/attribute/filter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package attribute // import "go.opentelemetry.io/otel/attribute" | ||||
| 
 | ||||
| // Filter supports removing certain attributes from attribute sets. When | ||||
| // the filter returns true, the attribute will be kept in the filtered | ||||
| // attribute set. When the filter returns false, the attribute is excluded | ||||
| // from the filtered attribute set, and the attribute instead appears in | ||||
| // the removed list of excluded attributes. | ||||
| type Filter func(KeyValue) bool | ||||
| 
 | ||||
| // NewAllowKeysFilter returns a Filter that only allows attributes with one of | ||||
| // the provided keys. | ||||
| // | ||||
| // If keys is empty a deny-all filter is returned. | ||||
| func NewAllowKeysFilter(keys ...Key) Filter { | ||||
| 	if len(keys) <= 0 { | ||||
| 		return func(kv KeyValue) bool { return false } | ||||
| 	} | ||||
| 
 | ||||
| 	allowed := make(map[Key]struct{}) | ||||
| 	for _, k := range keys { | ||||
| 		allowed[k] = struct{}{} | ||||
| 	} | ||||
| 	return func(kv KeyValue) bool { | ||||
| 		_, ok := allowed[kv.Key] | ||||
| 		return ok | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewDenyKeysFilter returns a Filter that only allows attributes | ||||
| // that do not have one of the provided keys. | ||||
| // | ||||
| // If keys is empty an allow-all filter is returned. | ||||
| func NewDenyKeysFilter(keys ...Key) Filter { | ||||
| 	if len(keys) <= 0 { | ||||
| 		return func(kv KeyValue) bool { return true } | ||||
| 	} | ||||
| 
 | ||||
| 	forbid := make(map[Key]struct{}) | ||||
| 	for _, k := range keys { | ||||
| 		forbid[k] = struct{}{} | ||||
| 	} | ||||
| 	return func(kv KeyValue) bool { | ||||
| 		_, ok := forbid[kv.Key] | ||||
| 		return !ok | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/go.opentelemetry.io/otel/attribute/set.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/go.opentelemetry.io/otel/attribute/set.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -39,13 +39,6 @@ type ( | |||
| 		iface interface{} | ||||
| 	} | ||||
| 
 | ||||
| 	// Filter supports removing certain attributes from attribute sets. When | ||||
| 	// the filter returns true, the attribute will be kept in the filtered | ||||
| 	// attribute set. When the filter returns false, the attribute is excluded | ||||
| 	// from the filtered attribute set, and the attribute instead appears in | ||||
| 	// the removed list of excluded attributes. | ||||
| 	Filter func(KeyValue) bool | ||||
| 
 | ||||
| 	// Sortable implements sort.Interface, used for sorting KeyValue. This is | ||||
| 	// an exported type to support a memory optimization. A pointer to one of | ||||
| 	// these is needed for the call to sort.Stable(), which the caller may | ||||
|  |  | |||
							
								
								
									
										14
									
								
								vendor/go.opentelemetry.io/otel/baggage/baggage.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/go.opentelemetry.io/otel/baggage/baggage.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -61,11 +61,6 @@ type Property struct { | |||
| 	// hasValue indicates if a zero-value value means the property does not | ||||
| 	// have a value or if it was the zero-value. | ||||
| 	hasValue bool | ||||
| 
 | ||||
| 	// hasData indicates whether the created property contains data or not. | ||||
| 	// Properties that do not contain data are invalid with no other check | ||||
| 	// required. | ||||
| 	hasData bool | ||||
| } | ||||
| 
 | ||||
| // NewKeyProperty returns a new Property for key. | ||||
|  | @ -76,7 +71,7 @@ func NewKeyProperty(key string) (Property, error) { | |||
| 		return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) | ||||
| 	} | ||||
| 
 | ||||
| 	p := Property{key: key, hasData: true} | ||||
| 	p := Property{key: key} | ||||
| 	return p, nil | ||||
| } | ||||
| 
 | ||||
|  | @ -95,7 +90,6 @@ func NewKeyValueProperty(key, value string) (Property, error) { | |||
| 		key:      key, | ||||
| 		value:    value, | ||||
| 		hasValue: true, | ||||
| 		hasData:  true, | ||||
| 	} | ||||
| 	return p, nil | ||||
| } | ||||
|  | @ -117,7 +111,7 @@ func parseProperty(property string) (Property, error) { | |||
| 		return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidProperty, property) | ||||
| 	} | ||||
| 
 | ||||
| 	p := Property{hasData: true} | ||||
| 	var p Property | ||||
| 	if match[1] != "" { | ||||
| 		p.key = match[1] | ||||
| 	} else { | ||||
|  | @ -136,10 +130,6 @@ func (p Property) validate() error { | |||
| 		return fmt.Errorf("invalid property: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if !p.hasData { | ||||
| 		return errFunc(fmt.Errorf("%w: %q", errInvalidProperty, p)) | ||||
| 	} | ||||
| 
 | ||||
| 	if !keyRe.MatchString(p.key) { | ||||
| 		return errFunc(fmt.Errorf("%w: %q", errInvalidKey, p.key)) | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										50
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,50 +0,0 @@ | |||
| # OpenTelemetry-Go Jaeger Exporter | ||||
| 
 | ||||
| [](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger) | ||||
| 
 | ||||
| [OpenTelemetry span exporter for Jaeger](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/sdk_exporters/jaeger.md) implementation. | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| ``` | ||||
| go get -u go.opentelemetry.io/otel/exporters/jaeger | ||||
| ``` | ||||
| 
 | ||||
| ## Example | ||||
| 
 | ||||
| See [../../example/jaeger](../../example/jaeger). | ||||
| 
 | ||||
| ## Configuration | ||||
| 
 | ||||
| The exporter can be used to send spans to: | ||||
| 
 | ||||
| - Jaeger agent using `jaeger.thrift` over compact thrift protocol via | ||||
|   [`WithAgentEndpoint`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithAgentEndpoint) option. | ||||
| - Jaeger collector using `jaeger.thrift` over HTTP via | ||||
|   [`WithCollectorEndpoint`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithCollectorEndpoint) option. | ||||
| 
 | ||||
| ### Environment Variables | ||||
| 
 | ||||
| The following environment variables can be used | ||||
| (instead of options objects) to override the default configuration. | ||||
| 
 | ||||
| | Environment variable              | Option                                                                                        | Default value                       | | ||||
| | --------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------- | | ||||
| | `OTEL_EXPORTER_JAEGER_AGENT_HOST` | [`WithAgentHost`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithAgentHost) | `localhost`                         | | ||||
| | `OTEL_EXPORTER_JAEGER_AGENT_PORT` | [`WithAgentPort`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithAgentPort) | `6831`                              | | ||||
| | `OTEL_EXPORTER_JAEGER_ENDPOINT`   | [`WithEndpoint`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithEndpoint)   | `http://localhost:14268/api/traces` | | ||||
| | `OTEL_EXPORTER_JAEGER_USER`       | [`WithUsername`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithUsername)   |                                     | | ||||
| | `OTEL_EXPORTER_JAEGER_PASSWORD`   | [`WithPassword`](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithPassword)   |                                     | | ||||
| 
 | ||||
| Configuration using options have precedence over the environment variables. | ||||
| 
 | ||||
| ## Contributing | ||||
| 
 | ||||
| This exporter uses a vendored copy of the Apache Thrift library (v0.14.1) at a custom import path. | ||||
| When re-generating Thrift code in the future, please adapt import paths as necessary. | ||||
| 
 | ||||
| ## References | ||||
| 
 | ||||
| - [Jaeger](https://www.jaegertracing.io/) | ||||
| - [OpenTelemetry to Jaeger Transformation](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/sdk_exporters/jaeger.md) | ||||
| - [OpenTelemetry Environment Variable Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/sdk-environment-variables.md#jaeger-exporter) | ||||
							
								
								
									
										213
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/agent.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										213
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/agent.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,213 +0,0 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package jaeger // import "go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/go-logr/logr" | ||||
| 
 | ||||
| 	genAgent "go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent" | ||||
| 	gen "go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// udpPacketMaxLength is the max size of UDP packet we want to send, synced with jaeger-agent. | ||||
| 	udpPacketMaxLength = 65000 | ||||
| 	// emitBatchOverhead is the additional overhead bytes used for enveloping the datagram, | ||||
| 	// synced with jaeger-agent https://github.com/jaegertracing/jaeger-client-go/blob/master/transport_udp.go#L37 | ||||
| 	emitBatchOverhead = 70 | ||||
| ) | ||||
| 
 | ||||
| // agentClientUDP is a UDP client to Jaeger agent that implements gen.Agent interface. | ||||
| type agentClientUDP struct { | ||||
| 	genAgent.Agent | ||||
| 	io.Closer | ||||
| 
 | ||||
| 	connUDP        udpConn | ||||
| 	client         *genAgent.AgentClient | ||||
| 	maxPacketSize  int                   // max size of datagram in bytes | ||||
| 	thriftBuffer   *thrift.TMemoryBuffer // buffer used to calculate byte size of a span | ||||
| 	thriftProtocol thrift.TProtocol | ||||
| } | ||||
| 
 | ||||
| type udpConn interface { | ||||
| 	Write([]byte) (int, error) | ||||
| 	SetWriteBuffer(int) error | ||||
| 	Close() error | ||||
| } | ||||
| 
 | ||||
| type agentClientUDPParams struct { | ||||
| 	Host                     string | ||||
| 	Port                     string | ||||
| 	MaxPacketSize            int | ||||
| 	Logger                   logr.Logger | ||||
| 	AttemptReconnecting      bool | ||||
| 	AttemptReconnectInterval time.Duration | ||||
| } | ||||
| 
 | ||||
| // newAgentClientUDP creates a client that sends spans to Jaeger Agent over UDP. | ||||
| func newAgentClientUDP(params agentClientUDPParams) (*agentClientUDP, error) { | ||||
| 	hostPort := net.JoinHostPort(params.Host, params.Port) | ||||
| 	// validate hostport | ||||
| 	if _, _, err := net.SplitHostPort(hostPort); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if params.MaxPacketSize <= 0 || params.MaxPacketSize > udpPacketMaxLength { | ||||
| 		params.MaxPacketSize = udpPacketMaxLength | ||||
| 	} | ||||
| 
 | ||||
| 	if params.AttemptReconnecting && params.AttemptReconnectInterval <= 0 { | ||||
| 		params.AttemptReconnectInterval = time.Second * 30 | ||||
| 	} | ||||
| 
 | ||||
| 	thriftBuffer := thrift.NewTMemoryBufferLen(params.MaxPacketSize) | ||||
| 	protocolFactory := thrift.NewTCompactProtocolFactoryConf(&thrift.TConfiguration{}) | ||||
| 	thriftProtocol := protocolFactory.GetProtocol(thriftBuffer) | ||||
| 	client := genAgent.NewAgentClientFactory(thriftBuffer, protocolFactory) | ||||
| 
 | ||||
| 	var connUDP udpConn | ||||
| 	var err error | ||||
| 
 | ||||
| 	if params.AttemptReconnecting { | ||||
| 		// host is hostname, setup resolver loop in case host record changes during operation | ||||
| 		connUDP, err = newReconnectingUDPConn(hostPort, params.MaxPacketSize, params.AttemptReconnectInterval, net.ResolveUDPAddr, net.DialUDP, params.Logger) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} else { | ||||
| 		destAddr, err := net.ResolveUDPAddr("udp", hostPort) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		connUDP, err = net.DialUDP(destAddr.Network(), nil, destAddr) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := connUDP.SetWriteBuffer(params.MaxPacketSize); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &agentClientUDP{ | ||||
| 		connUDP:        connUDP, | ||||
| 		client:         client, | ||||
| 		maxPacketSize:  params.MaxPacketSize, | ||||
| 		thriftBuffer:   thriftBuffer, | ||||
| 		thriftProtocol: thriftProtocol, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // EmitBatch buffers batch to fit into UDP packets and sends the data to the agent. | ||||
| func (a *agentClientUDP) EmitBatch(ctx context.Context, batch *gen.Batch) error { | ||||
| 	var errs []error | ||||
| 	processSize, err := a.calcSizeOfSerializedThrift(ctx, batch.Process) | ||||
| 	if err != nil { | ||||
| 		// drop the batch if serialization of process fails. | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	maxPacketSize := a.maxPacketSize | ||||
| 	if maxPacketSize > udpPacketMaxLength-emitBatchOverhead { | ||||
| 		maxPacketSize = udpPacketMaxLength - emitBatchOverhead | ||||
| 	} | ||||
| 	totalSize := processSize | ||||
| 	var spans []*gen.Span | ||||
| 	for _, span := range batch.Spans { | ||||
| 		spanSize, err := a.calcSizeOfSerializedThrift(ctx, span) | ||||
| 		if err != nil { | ||||
| 			errs = append(errs, fmt.Errorf("thrift serialization failed: %v", span)) | ||||
| 			continue | ||||
| 		} | ||||
| 		if spanSize+processSize >= maxPacketSize { | ||||
| 			// drop the span that exceeds the limit. | ||||
| 			errs = append(errs, fmt.Errorf("span too large to send: %v", span)) | ||||
| 			continue | ||||
| 		} | ||||
| 		if totalSize+spanSize >= maxPacketSize { | ||||
| 			if err := a.flush(ctx, &gen.Batch{ | ||||
| 				Process: batch.Process, | ||||
| 				Spans:   spans, | ||||
| 			}); err != nil { | ||||
| 				errs = append(errs, err) | ||||
| 			} | ||||
| 			spans = spans[:0] | ||||
| 			totalSize = processSize | ||||
| 		} | ||||
| 		totalSize += spanSize | ||||
| 		spans = append(spans, span) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(spans) > 0 { | ||||
| 		if err := a.flush(ctx, &gen.Batch{ | ||||
| 			Process: batch.Process, | ||||
| 			Spans:   spans, | ||||
| 		}); err != nil { | ||||
| 			errs = append(errs, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(errs) == 1 { | ||||
| 		return errs[0] | ||||
| 	} else if len(errs) > 1 { | ||||
| 		joined := a.makeJoinedErrorString(errs) | ||||
| 		return fmt.Errorf("multiple errors during transform: %s", joined) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // makeJoinedErrorString join all the errors to one error message. | ||||
| func (a *agentClientUDP) makeJoinedErrorString(errs []error) string { | ||||
| 	var errMsgs []string | ||||
| 	for _, err := range errs { | ||||
| 		errMsgs = append(errMsgs, err.Error()) | ||||
| 	} | ||||
| 	return strings.Join(errMsgs, ", ") | ||||
| } | ||||
| 
 | ||||
| // flush will send the batch of spans to the agent. | ||||
| func (a *agentClientUDP) flush(ctx context.Context, batch *gen.Batch) error { | ||||
| 	a.thriftBuffer.Reset() | ||||
| 	if err := a.client.EmitBatch(ctx, batch); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if a.thriftBuffer.Len() > a.maxPacketSize { | ||||
| 		return fmt.Errorf("data does not fit within one UDP packet; size %d, max %d, spans %d", | ||||
| 			a.thriftBuffer.Len(), a.maxPacketSize, len(batch.Spans)) | ||||
| 	} | ||||
| 	_, err := a.connUDP.Write(a.thriftBuffer.Bytes()) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // calcSizeOfSerializedThrift calculate the serialized thrift packet size. | ||||
| func (a *agentClientUDP) calcSizeOfSerializedThrift(ctx context.Context, thriftStruct thrift.TStruct) (int, error) { | ||||
| 	a.thriftBuffer.Reset() | ||||
| 	err := thriftStruct.Write(ctx, a.thriftProtocol) | ||||
| 	return a.thriftBuffer.Len(), err | ||||
| } | ||||
| 
 | ||||
| // Close implements Close() of io.Closer and closes the underlying UDP connection. | ||||
| func (a *agentClientUDP) Close() error { | ||||
| 	return a.connUDP.Close() | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/env.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/env.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,44 +0,0 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package jaeger // import "go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| // Environment variable names. | ||||
| const ( | ||||
| 	// Hostname for the Jaeger agent, part of address where exporter sends spans | ||||
| 	// i.e.	"localhost". | ||||
| 	envAgentHost = "OTEL_EXPORTER_JAEGER_AGENT_HOST" | ||||
| 	// Port for the Jaeger agent, part of address where exporter sends spans | ||||
| 	// i.e. 6831. | ||||
| 	envAgentPort = "OTEL_EXPORTER_JAEGER_AGENT_PORT" | ||||
| 	// The HTTP endpoint for sending spans directly to a collector, | ||||
| 	// i.e. http://jaeger-collector:14268/api/traces. | ||||
| 	envEndpoint = "OTEL_EXPORTER_JAEGER_ENDPOINT" | ||||
| 	// Username to send as part of "Basic" authentication to the collector endpoint. | ||||
| 	envUser = "OTEL_EXPORTER_JAEGER_USER" | ||||
| 	// Password to send as part of "Basic" authentication to the collector endpoint. | ||||
| 	envPassword = "OTEL_EXPORTER_JAEGER_PASSWORD" | ||||
| ) | ||||
| 
 | ||||
| // envOr returns an env variable's value if it is exists or the default if not. | ||||
| func envOr(key, defaultValue string) string { | ||||
| 	if v := os.Getenv(key); v != "" { | ||||
| 		return v | ||||
| 	} | ||||
| 	return defaultValue | ||||
| } | ||||
|  | @ -1,6 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package agent | ||||
| 
 | ||||
| var GoUnusedProtection__ int; | ||||
| 
 | ||||
							
								
								
									
										27
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent/agent-consts.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent/agent-consts.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,27 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package agent | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/zipkincore" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| // (needed to ensure safety because of naive import list construction.) | ||||
| var _ = thrift.ZERO | ||||
| var _ = fmt.Printf | ||||
| var _ = context.Background | ||||
| var _ = time.Now | ||||
| var _ = bytes.Equal | ||||
| 
 | ||||
| var _ = jaeger.GoUnusedProtection__ | ||||
| var _ = zipkincore.GoUnusedProtection__ | ||||
| 
 | ||||
| func init() { | ||||
| } | ||||
							
								
								
									
										412
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent/agent.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										412
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent/agent.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,412 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package agent | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/zipkincore" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| // (needed to ensure safety because of naive import list construction.) | ||||
| var _ = thrift.ZERO | ||||
| var _ = fmt.Printf | ||||
| var _ = context.Background | ||||
| var _ = time.Now | ||||
| var _ = bytes.Equal | ||||
| 
 | ||||
| var _ = jaeger.GoUnusedProtection__ | ||||
| var _ = zipkincore.GoUnusedProtection__ | ||||
| 
 | ||||
| type Agent interface { | ||||
| 	// Parameters: | ||||
| 	//  - Spans | ||||
| 	EmitZipkinBatch(ctx context.Context, spans []*zipkincore.Span) (_err error) | ||||
| 	// Parameters: | ||||
| 	//  - Batch | ||||
| 	EmitBatch(ctx context.Context, batch *jaeger.Batch) (_err error) | ||||
| } | ||||
| 
 | ||||
| type AgentClient struct { | ||||
| 	c    thrift.TClient | ||||
| 	meta thrift.ResponseMeta | ||||
| } | ||||
| 
 | ||||
| func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient { | ||||
| 	return &AgentClient{ | ||||
| 		c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient { | ||||
| 	return &AgentClient{ | ||||
| 		c: thrift.NewTStandardClient(iprot, oprot), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewAgentClient(c thrift.TClient) *AgentClient { | ||||
| 	return &AgentClient{ | ||||
| 		c: c, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *AgentClient) Client_() thrift.TClient { | ||||
| 	return p.c | ||||
| } | ||||
| 
 | ||||
| func (p *AgentClient) LastResponseMeta_() thrift.ResponseMeta { | ||||
| 	return p.meta | ||||
| } | ||||
| 
 | ||||
| func (p *AgentClient) SetLastResponseMeta_(meta thrift.ResponseMeta) { | ||||
| 	p.meta = meta | ||||
| } | ||||
| 
 | ||||
| // Parameters: | ||||
| //  - Spans | ||||
| func (p *AgentClient) EmitZipkinBatch(ctx context.Context, spans []*zipkincore.Span) (_err error) { | ||||
| 	var _args0 AgentEmitZipkinBatchArgs | ||||
| 	_args0.Spans = spans | ||||
| 	p.SetLastResponseMeta_(thrift.ResponseMeta{}) | ||||
| 	if _, err := p.Client_().Call(ctx, "emitZipkinBatch", &_args0, nil); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Parameters: | ||||
| //  - Batch | ||||
| func (p *AgentClient) EmitBatch(ctx context.Context, batch *jaeger.Batch) (_err error) { | ||||
| 	var _args1 AgentEmitBatchArgs | ||||
| 	_args1.Batch = batch | ||||
| 	p.SetLastResponseMeta_(thrift.ResponseMeta{}) | ||||
| 	if _, err := p.Client_().Call(ctx, "emitBatch", &_args1, nil); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| type AgentProcessor struct { | ||||
| 	processorMap map[string]thrift.TProcessorFunction | ||||
| 	handler      Agent | ||||
| } | ||||
| 
 | ||||
| func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { | ||||
| 	p.processorMap[key] = processor | ||||
| } | ||||
| 
 | ||||
| func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { | ||||
| 	processor, ok = p.processorMap[key] | ||||
| 	return processor, ok | ||||
| } | ||||
| 
 | ||||
| func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { | ||||
| 	return p.processorMap | ||||
| } | ||||
| 
 | ||||
| func NewAgentProcessor(handler Agent) *AgentProcessor { | ||||
| 
 | ||||
| 	self2 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} | ||||
| 	self2.processorMap["emitZipkinBatch"] = &agentProcessorEmitZipkinBatch{handler: handler} | ||||
| 	self2.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler} | ||||
| 	return self2 | ||||
| } | ||||
| 
 | ||||
| func (p *AgentProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { | ||||
| 	name, _, seqId, err2 := iprot.ReadMessageBegin(ctx) | ||||
| 	if err2 != nil { | ||||
| 		return false, thrift.WrapTException(err2) | ||||
| 	} | ||||
| 	if processor, ok := p.GetProcessorFunction(name); ok { | ||||
| 		return processor.Process(ctx, seqId, iprot, oprot) | ||||
| 	} | ||||
| 	iprot.Skip(ctx, thrift.STRUCT) | ||||
| 	iprot.ReadMessageEnd(ctx) | ||||
| 	x3 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) | ||||
| 	oprot.WriteMessageBegin(ctx, name, thrift.EXCEPTION, seqId) | ||||
| 	x3.Write(ctx, oprot) | ||||
| 	oprot.WriteMessageEnd(ctx) | ||||
| 	oprot.Flush(ctx) | ||||
| 	return false, x3 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| type agentProcessorEmitZipkinBatch struct { | ||||
| 	handler Agent | ||||
| } | ||||
| 
 | ||||
| func (p *agentProcessorEmitZipkinBatch) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { | ||||
| 	args := AgentEmitZipkinBatchArgs{} | ||||
| 	var err2 error | ||||
| 	if err2 = args.Read(ctx, iprot); err2 != nil { | ||||
| 		iprot.ReadMessageEnd(ctx) | ||||
| 		return false, thrift.WrapTException(err2) | ||||
| 	} | ||||
| 	iprot.ReadMessageEnd(ctx) | ||||
| 
 | ||||
| 	tickerCancel := func() {} | ||||
| 	_ = tickerCancel | ||||
| 
 | ||||
| 	if err2 = p.handler.EmitZipkinBatch(ctx, args.Spans); err2 != nil { | ||||
| 		tickerCancel() | ||||
| 		return true, thrift.WrapTException(err2) | ||||
| 	} | ||||
| 	tickerCancel() | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| type agentProcessorEmitBatch struct { | ||||
| 	handler Agent | ||||
| } | ||||
| 
 | ||||
| func (p *agentProcessorEmitBatch) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { | ||||
| 	args := AgentEmitBatchArgs{} | ||||
| 	var err2 error | ||||
| 	if err2 = args.Read(ctx, iprot); err2 != nil { | ||||
| 		iprot.ReadMessageEnd(ctx) | ||||
| 		return false, thrift.WrapTException(err2) | ||||
| 	} | ||||
| 	iprot.ReadMessageEnd(ctx) | ||||
| 
 | ||||
| 	tickerCancel := func() {} | ||||
| 	_ = tickerCancel | ||||
| 
 | ||||
| 	if err2 = p.handler.EmitBatch(ctx, args.Batch); err2 != nil { | ||||
| 		tickerCancel() | ||||
| 		return true, thrift.WrapTException(err2) | ||||
| 	} | ||||
| 	tickerCancel() | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| // HELPER FUNCTIONS AND STRUCTURES | ||||
| 
 | ||||
| // Attributes: | ||||
| //  - Spans | ||||
| type AgentEmitZipkinBatchArgs struct { | ||||
| 	Spans []*zipkincore.Span `thrift:"spans,1" db:"spans" json:"spans"` | ||||
| } | ||||
| 
 | ||||
| func NewAgentEmitZipkinBatchArgs() *AgentEmitZipkinBatchArgs { | ||||
| 	return &AgentEmitZipkinBatchArgs{} | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitZipkinBatchArgs) GetSpans() []*zipkincore.Span { | ||||
| 	return p.Spans | ||||
| } | ||||
| func (p *AgentEmitZipkinBatchArgs) Read(ctx context.Context, iprot thrift.TProtocol) error { | ||||
| 	if _, err := iprot.ReadStructBegin(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) | ||||
| 	} | ||||
| 
 | ||||
| 	for { | ||||
| 		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) | ||||
| 		} | ||||
| 		if fieldTypeId == thrift.STOP { | ||||
| 			break | ||||
| 		} | ||||
| 		switch fieldId { | ||||
| 		case 1: | ||||
| 			if fieldTypeId == thrift.LIST { | ||||
| 				if err := p.ReadField1(ctx, iprot); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				if err := iprot.Skip(ctx, fieldTypeId); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			if err := iprot.Skip(ctx, fieldTypeId); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if err := iprot.ReadFieldEnd(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := iprot.ReadStructEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitZipkinBatchArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { | ||||
| 	_, size, err := iprot.ReadListBegin(ctx) | ||||
| 	if err != nil { | ||||
| 		return thrift.PrependError("error reading list begin: ", err) | ||||
| 	} | ||||
| 	tSlice := make([]*zipkincore.Span, 0, size) | ||||
| 	p.Spans = tSlice | ||||
| 	for i := 0; i < size; i++ { | ||||
| 		_elem4 := &zipkincore.Span{} | ||||
| 		if err := _elem4.Read(ctx, iprot); err != nil { | ||||
| 			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err) | ||||
| 		} | ||||
| 		p.Spans = append(p.Spans, _elem4) | ||||
| 	} | ||||
| 	if err := iprot.ReadListEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError("error reading list end: ", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitZipkinBatchArgs) Write(ctx context.Context, oprot thrift.TProtocol) error { | ||||
| 	if err := oprot.WriteStructBegin(ctx, "emitZipkinBatch_args"); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) | ||||
| 	} | ||||
| 	if p != nil { | ||||
| 		if err := p.writeField1(ctx, oprot); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := oprot.WriteFieldStop(ctx); err != nil { | ||||
| 		return thrift.PrependError("write field stop error: ", err) | ||||
| 	} | ||||
| 	if err := oprot.WriteStructEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError("write struct stop error: ", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitZipkinBatchArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { | ||||
| 	if err := oprot.WriteFieldBegin(ctx, "spans", thrift.LIST, 1); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err) | ||||
| 	} | ||||
| 	if err := oprot.WriteListBegin(ctx, thrift.STRUCT, len(p.Spans)); err != nil { | ||||
| 		return thrift.PrependError("error writing list begin: ", err) | ||||
| 	} | ||||
| 	for _, v := range p.Spans { | ||||
| 		if err := v.Write(ctx, oprot); err != nil { | ||||
| 			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err) | ||||
| 		} | ||||
| 	} | ||||
| 	if err := oprot.WriteListEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError("error writing list end: ", err) | ||||
| 	} | ||||
| 	if err := oprot.WriteFieldEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitZipkinBatchArgs) String() string { | ||||
| 	if p == nil { | ||||
| 		return "<nil>" | ||||
| 	} | ||||
| 	return fmt.Sprintf("AgentEmitZipkinBatchArgs(%+v)", *p) | ||||
| } | ||||
| 
 | ||||
| // Attributes: | ||||
| //  - Batch | ||||
| type AgentEmitBatchArgs struct { | ||||
| 	Batch *jaeger.Batch `thrift:"batch,1" db:"batch" json:"batch"` | ||||
| } | ||||
| 
 | ||||
| func NewAgentEmitBatchArgs() *AgentEmitBatchArgs { | ||||
| 	return &AgentEmitBatchArgs{} | ||||
| } | ||||
| 
 | ||||
| var AgentEmitBatchArgs_Batch_DEFAULT *jaeger.Batch | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) GetBatch() *jaeger.Batch { | ||||
| 	if !p.IsSetBatch() { | ||||
| 		return AgentEmitBatchArgs_Batch_DEFAULT | ||||
| 	} | ||||
| 	return p.Batch | ||||
| } | ||||
| func (p *AgentEmitBatchArgs) IsSetBatch() bool { | ||||
| 	return p.Batch != nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) Read(ctx context.Context, iprot thrift.TProtocol) error { | ||||
| 	if _, err := iprot.ReadStructBegin(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) | ||||
| 	} | ||||
| 
 | ||||
| 	for { | ||||
| 		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) | ||||
| 		} | ||||
| 		if fieldTypeId == thrift.STOP { | ||||
| 			break | ||||
| 		} | ||||
| 		switch fieldId { | ||||
| 		case 1: | ||||
| 			if fieldTypeId == thrift.STRUCT { | ||||
| 				if err := p.ReadField1(ctx, iprot); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				if err := iprot.Skip(ctx, fieldTypeId); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			if err := iprot.Skip(ctx, fieldTypeId); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if err := iprot.ReadFieldEnd(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := iprot.ReadStructEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { | ||||
| 	p.Batch = &jaeger.Batch{} | ||||
| 	if err := p.Batch.Read(ctx, iprot); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) Write(ctx context.Context, oprot thrift.TProtocol) error { | ||||
| 	if err := oprot.WriteStructBegin(ctx, "emitBatch_args"); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) | ||||
| 	} | ||||
| 	if p != nil { | ||||
| 		if err := p.writeField1(ctx, oprot); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := oprot.WriteFieldStop(ctx); err != nil { | ||||
| 		return thrift.PrependError("write field stop error: ", err) | ||||
| 	} | ||||
| 	if err := oprot.WriteStructEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError("write struct stop error: ", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { | ||||
| 	if err := oprot.WriteFieldBegin(ctx, "batch", thrift.STRUCT, 1); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err) | ||||
| 	} | ||||
| 	if err := p.Batch.Write(ctx, oprot); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err) | ||||
| 	} | ||||
| 	if err := oprot.WriteFieldEnd(ctx); err != nil { | ||||
| 		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *AgentEmitBatchArgs) String() string { | ||||
| 	if p == nil { | ||||
| 		return "<nil>" | ||||
| 	} | ||||
| 	return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p) | ||||
| } | ||||
|  | @ -1,6 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package jaeger | ||||
| 
 | ||||
| var GoUnusedProtection__ int; | ||||
| 
 | ||||
							
								
								
									
										22
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger/jaeger-consts.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger/jaeger-consts.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,22 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package jaeger | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| // (needed to ensure safety because of naive import list construction.) | ||||
| var _ = thrift.ZERO | ||||
| var _ = fmt.Printf | ||||
| var _ = context.Background | ||||
| var _ = time.Now | ||||
| var _ = bytes.Equal | ||||
| 
 | ||||
| func init() { | ||||
| } | ||||
							
								
								
									
										3022
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger/jaeger.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3022
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger/jaeger.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,6 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package zipkincore | ||||
| 
 | ||||
| var GoUnusedProtection__ int; | ||||
| 
 | ||||
|  | @ -1,39 +0,0 @@ | |||
| // Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. | ||||
| 
 | ||||
| package zipkincore | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| // (needed to ensure safety because of naive import list construction.) | ||||
| var _ = thrift.ZERO | ||||
| var _ = fmt.Printf | ||||
| var _ = context.Background | ||||
| var _ = time.Now | ||||
| var _ = bytes.Equal | ||||
| 
 | ||||
| const CLIENT_SEND = "cs" | ||||
| const CLIENT_RECV = "cr" | ||||
| const SERVER_SEND = "ss" | ||||
| const SERVER_RECV = "sr" | ||||
| const MESSAGE_SEND = "ms" | ||||
| const MESSAGE_RECV = "mr" | ||||
| const WIRE_SEND = "ws" | ||||
| const WIRE_RECV = "wr" | ||||
| const CLIENT_SEND_FRAGMENT = "csf" | ||||
| const CLIENT_RECV_FRAGMENT = "crf" | ||||
| const SERVER_SEND_FRAGMENT = "ssf" | ||||
| const SERVER_RECV_FRAGMENT = "srf" | ||||
| const LOCAL_COMPONENT = "lc" | ||||
| const CLIENT_ADDR = "ca" | ||||
| const SERVER_ADDR = "sa" | ||||
| const MESSAGE_ADDR = "ma" | ||||
| 
 | ||||
| func init() { | ||||
| } | ||||
							
								
								
									
										2067
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/zipkincore/zipkincore.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2067
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/zipkincore/zipkincore.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										306
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										306
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,306 +0,0 @@ | |||
| 
 | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
| 
 | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
| 
 | ||||
|    1. Definitions. | ||||
| 
 | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
| 
 | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
| 
 | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
| 
 | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
| 
 | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
| 
 | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
| 
 | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
| 
 | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
| 
 | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
| 
 | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
| 
 | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
| 
 | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
| 
 | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
| 
 | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
| 
 | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
| 
 | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
| 
 | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
| 
 | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
| 
 | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
| 
 | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
| 
 | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
| 
 | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
| 
 | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
| 
 | ||||
|    END OF TERMS AND CONDITIONS | ||||
| 
 | ||||
|    APPENDIX: How to apply the Apache License to your work. | ||||
| 
 | ||||
|       To apply the Apache License to your work, attach the following | ||||
|       boilerplate notice, with the fields enclosed by brackets "[]" | ||||
|       replaced with your own identifying information. (Don't include | ||||
|       the brackets!)  The text should be enclosed in the appropriate | ||||
|       comment syntax for the file format. We also recommend that a | ||||
|       file or class name and description of purpose be included on the | ||||
|       same "printed page" as the copyright notice for easier | ||||
|       identification within third-party archives. | ||||
| 
 | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
| 
 | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
| 
 | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| SOFTWARE DISTRIBUTED WITH THRIFT: | ||||
| 
 | ||||
| The Apache Thrift software includes a number of subcomponents with | ||||
| separate copyright notices and license terms. Your use of the source | ||||
| code for the these subcomponents is subject to the terms and | ||||
| conditions of the following licenses. | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| Portions of the following files are licensed under the MIT License: | ||||
| 
 | ||||
|   lib/erl/src/Makefile.am | ||||
| 
 | ||||
| Please see doc/otp-base-license.txt for the full terms of this license. | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| For the aclocal/ax_boost_base.m4 and contrib/fb303/aclocal/ax_boost_base.m4 components: | ||||
| 
 | ||||
| #   Copyright (c) 2007 Thomas Porschberg <thomas@randspringer.de> | ||||
| # | ||||
| #   Copying and distribution of this file, with or without | ||||
| #   modification, are permitted in any medium without royalty provided | ||||
| #   the copyright notice and this notice are preserved. | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| For the lib/nodejs/lib/thrift/json_parse.js: | ||||
| 
 | ||||
| /* | ||||
|     json_parse.js | ||||
|     2015-05-02 | ||||
|     Public Domain. | ||||
|     NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | ||||
| 
 | ||||
| */ | ||||
| (By Douglas Crockford <douglas@crockford.com>) | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| For lib/cpp/src/thrift/windows/SocketPair.cpp | ||||
| 
 | ||||
| /* socketpair.c | ||||
|  * Copyright 2007 by Nathan C. Myers <ncm@cantrip.org>; some rights reserved. | ||||
|  * This code is Free Software.  It may be copied freely, in original or | ||||
|  * modified form, subject only to the restrictions that (1) the author is | ||||
|  * relieved from all responsibilities for any use for any purpose, and (2) | ||||
|  * this copyright notice must be retained, unchanged, in its entirety.  If | ||||
|  * for any reason the author might be held responsible for any consequences | ||||
|  * of copying or use, license is withheld. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| For lib/py/compat/win32/stdint.h | ||||
| 
 | ||||
| // ISO C9x  compliant stdint.h for Microsoft Visual Studio | ||||
| // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 | ||||
| // | ||||
| //  Copyright (c) 2006-2008 Alexander Chemeris | ||||
| // | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| // modification, are permitted provided that the following conditions are met: | ||||
| // | ||||
| //   1. Redistributions of source code must retain the above copyright notice, | ||||
| //      this list of conditions and the following disclaimer. | ||||
| // | ||||
| //   2. Redistributions in binary form must reproduce the above copyright | ||||
| //      notice, this list of conditions and the following disclaimer in the | ||||
| //      documentation and/or other materials provided with the distribution. | ||||
| // | ||||
| //   3. The name of the author may be used to endorse or promote products | ||||
| //      derived from this software without specific prior written permission. | ||||
| // | ||||
| // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||||
| // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
| // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||||
| // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||
| // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||||
| // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||||
| // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
| // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
| // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
| 
 | ||||
| -------------------------------------------------- | ||||
| Codegen template in t_html_generator.h | ||||
| 
 | ||||
| * Bootstrap v2.0.3 | ||||
| * | ||||
| * Copyright 2012 Twitter, Inc | ||||
| * Licensed under the Apache License v2.0 | ||||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||||
| * | ||||
| * Designed and built with all the love in the world @twitter by @mdo and @fat. | ||||
| 
 | ||||
| --------------------------------------------------- | ||||
| For t_cl_generator.cc | ||||
| 
 | ||||
|  * Copyright (c) 2008- Patrick Collison <patrick@collison.ie> | ||||
|  * Copyright (c) 2006- Facebook | ||||
| 
 | ||||
| --------------------------------------------------- | ||||
							
								
								
									
										5
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/NOTICE
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/NOTICE
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,5 +0,0 @@ | |||
| Apache Thrift | ||||
| Copyright (C) 2006 - 2019, The Apache Software Foundation | ||||
| 
 | ||||
| This product includes software developed at | ||||
| The Apache Software Foundation (http://www.apache.org/). | ||||
|  | @ -1,180 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	UNKNOWN_APPLICATION_EXCEPTION  = 0 | ||||
| 	UNKNOWN_METHOD                 = 1 | ||||
| 	INVALID_MESSAGE_TYPE_EXCEPTION = 2 | ||||
| 	WRONG_METHOD_NAME              = 3 | ||||
| 	BAD_SEQUENCE_ID                = 4 | ||||
| 	MISSING_RESULT                 = 5 | ||||
| 	INTERNAL_ERROR                 = 6 | ||||
| 	PROTOCOL_ERROR                 = 7 | ||||
| 	INVALID_TRANSFORM              = 8 | ||||
| 	INVALID_PROTOCOL               = 9 | ||||
| 	UNSUPPORTED_CLIENT_TYPE        = 10 | ||||
| ) | ||||
| 
 | ||||
| var defaultApplicationExceptionMessage = map[int32]string{ | ||||
| 	UNKNOWN_APPLICATION_EXCEPTION:  "unknown application exception", | ||||
| 	UNKNOWN_METHOD:                 "unknown method", | ||||
| 	INVALID_MESSAGE_TYPE_EXCEPTION: "invalid message type", | ||||
| 	WRONG_METHOD_NAME:              "wrong method name", | ||||
| 	BAD_SEQUENCE_ID:                "bad sequence ID", | ||||
| 	MISSING_RESULT:                 "missing result", | ||||
| 	INTERNAL_ERROR:                 "unknown internal error", | ||||
| 	PROTOCOL_ERROR:                 "unknown protocol error", | ||||
| 	INVALID_TRANSFORM:              "Invalid transform", | ||||
| 	INVALID_PROTOCOL:               "Invalid protocol", | ||||
| 	UNSUPPORTED_CLIENT_TYPE:        "Unsupported client type", | ||||
| } | ||||
| 
 | ||||
| // Application level Thrift exception | ||||
| type TApplicationException interface { | ||||
| 	TException | ||||
| 	TypeId() int32 | ||||
| 	Read(ctx context.Context, iprot TProtocol) error | ||||
| 	Write(ctx context.Context, oprot TProtocol) error | ||||
| } | ||||
| 
 | ||||
| type tApplicationException struct { | ||||
| 	message string | ||||
| 	type_   int32 | ||||
| } | ||||
| 
 | ||||
| var _ TApplicationException = (*tApplicationException)(nil) | ||||
| 
 | ||||
| func (tApplicationException) TExceptionType() TExceptionType { | ||||
| 	return TExceptionTypeApplication | ||||
| } | ||||
| 
 | ||||
| func (e tApplicationException) Error() string { | ||||
| 	if e.message != "" { | ||||
| 		return e.message | ||||
| 	} | ||||
| 	return defaultApplicationExceptionMessage[e.type_] | ||||
| } | ||||
| 
 | ||||
| func NewTApplicationException(type_ int32, message string) TApplicationException { | ||||
| 	return &tApplicationException{message, type_} | ||||
| } | ||||
| 
 | ||||
| func (p *tApplicationException) TypeId() int32 { | ||||
| 	return p.type_ | ||||
| } | ||||
| 
 | ||||
| func (p *tApplicationException) Read(ctx context.Context, iprot TProtocol) error { | ||||
| 	// TODO: this should really be generated by the compiler | ||||
| 	_, err := iprot.ReadStructBegin(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	message := "" | ||||
| 	type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) | ||||
| 
 | ||||
| 	for { | ||||
| 		_, ttype, id, err := iprot.ReadFieldBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if ttype == STOP { | ||||
| 			break | ||||
| 		} | ||||
| 		switch id { | ||||
| 		case 1: | ||||
| 			if ttype == STRING { | ||||
| 				if message, err = iprot.ReadString(ctx); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		case 2: | ||||
| 			if ttype == I32 { | ||||
| 				if type_, err = iprot.ReadI32(ctx); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if err = iprot.ReadFieldEnd(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := iprot.ReadStructEnd(ctx); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	p.message = message | ||||
| 	p.type_ = type_ | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *tApplicationException) Write(ctx context.Context, oprot TProtocol) (err error) { | ||||
| 	err = oprot.WriteStructBegin(ctx, "TApplicationException") | ||||
| 	if len(p.Error()) > 0 { | ||||
| 		err = oprot.WriteFieldBegin(ctx, "message", STRING, 1) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		err = oprot.WriteString(ctx, p.Error()) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		err = oprot.WriteFieldEnd(ctx) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	err = oprot.WriteFieldBegin(ctx, "type", I32, 2) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	err = oprot.WriteI32(ctx, p.type_) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	err = oprot.WriteFieldEnd(ctx) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	err = oprot.WriteFieldStop(ctx) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	err = oprot.WriteStructEnd(ctx) | ||||
| 	return | ||||
| } | ||||
|  | @ -1,555 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| ) | ||||
| 
 | ||||
| type TBinaryProtocol struct { | ||||
| 	trans         TRichTransport | ||||
| 	origTransport TTransport | ||||
| 	cfg           *TConfiguration | ||||
| 	buffer        [64]byte | ||||
| } | ||||
| 
 | ||||
| type TBinaryProtocolFactory struct { | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTBinaryProtocolConf instead. | ||||
| func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { | ||||
| 	return NewTBinaryProtocolConf(t, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTBinaryProtocolConf instead. | ||||
| func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { | ||||
| 	return NewTBinaryProtocolConf(t, &TConfiguration{ | ||||
| 		TBinaryStrictRead:  &strictRead, | ||||
| 		TBinaryStrictWrite: &strictWrite, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTBinaryProtocolConf(t TTransport, conf *TConfiguration) *TBinaryProtocol { | ||||
| 	PropagateTConfiguration(t, conf) | ||||
| 	p := &TBinaryProtocol{ | ||||
| 		origTransport: t, | ||||
| 		cfg:           conf, | ||||
| 	} | ||||
| 	if et, ok := t.(TRichTransport); ok { | ||||
| 		p.trans = et | ||||
| 	} else { | ||||
| 		p.trans = NewTRichTransport(t) | ||||
| 	} | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTBinaryProtocolFactoryConf instead. | ||||
| func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { | ||||
| 	return NewTBinaryProtocolFactoryConf(&TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTBinaryProtocolFactoryConf instead. | ||||
| func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { | ||||
| 	return NewTBinaryProtocolFactoryConf(&TConfiguration{ | ||||
| 		TBinaryStrictRead:  &strictRead, | ||||
| 		TBinaryStrictWrite: &strictWrite, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTBinaryProtocolFactoryConf(conf *TConfiguration) *TBinaryProtocolFactory { | ||||
| 	return &TBinaryProtocolFactory{ | ||||
| 		cfg: conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { | ||||
| 	return NewTBinaryProtocolConf(t, p.cfg) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocolFactory) SetTConfiguration(conf *TConfiguration) { | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Writing Methods | ||||
|  */ | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { | ||||
| 	if p.cfg.GetTBinaryStrictWrite() { | ||||
| 		version := uint32(VERSION_1) | uint32(typeId) | ||||
| 		e := p.WriteI32(ctx, int32(version)) | ||||
| 		if e != nil { | ||||
| 			return e | ||||
| 		} | ||||
| 		e = p.WriteString(ctx, name) | ||||
| 		if e != nil { | ||||
| 			return e | ||||
| 		} | ||||
| 		e = p.WriteI32(ctx, seqId) | ||||
| 		return e | ||||
| 	} else { | ||||
| 		e := p.WriteString(ctx, name) | ||||
| 		if e != nil { | ||||
| 			return e | ||||
| 		} | ||||
| 		e = p.WriteByte(ctx, int8(typeId)) | ||||
| 		if e != nil { | ||||
| 			return e | ||||
| 		} | ||||
| 		e = p.WriteI32(ctx, seqId) | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteMessageEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteStructBegin(ctx context.Context, name string) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteStructEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { | ||||
| 	e := p.WriteByte(ctx, int8(typeId)) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	e = p.WriteI16(ctx, id) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteFieldEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteFieldStop(ctx context.Context) error { | ||||
| 	e := p.WriteByte(ctx, STOP) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { | ||||
| 	e := p.WriteByte(ctx, int8(keyType)) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	e = p.WriteByte(ctx, int8(valueType)) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	e = p.WriteI32(ctx, int32(size)) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteMapEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	e := p.WriteByte(ctx, int8(elemType)) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	e = p.WriteI32(ctx, int32(size)) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteListEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	e := p.WriteByte(ctx, int8(elemType)) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	e = p.WriteI32(ctx, int32(size)) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteSetEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteBool(ctx context.Context, value bool) error { | ||||
| 	if value { | ||||
| 		return p.WriteByte(ctx, 1) | ||||
| 	} | ||||
| 	return p.WriteByte(ctx, 0) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteByte(ctx context.Context, value int8) error { | ||||
| 	e := p.trans.WriteByte(byte(value)) | ||||
| 	return NewTProtocolException(e) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteI16(ctx context.Context, value int16) error { | ||||
| 	v := p.buffer[0:2] | ||||
| 	binary.BigEndian.PutUint16(v, uint16(value)) | ||||
| 	_, e := p.trans.Write(v) | ||||
| 	return NewTProtocolException(e) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteI32(ctx context.Context, value int32) error { | ||||
| 	v := p.buffer[0:4] | ||||
| 	binary.BigEndian.PutUint32(v, uint32(value)) | ||||
| 	_, e := p.trans.Write(v) | ||||
| 	return NewTProtocolException(e) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteI64(ctx context.Context, value int64) error { | ||||
| 	v := p.buffer[0:8] | ||||
| 	binary.BigEndian.PutUint64(v, uint64(value)) | ||||
| 	_, err := p.trans.Write(v) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteDouble(ctx context.Context, value float64) error { | ||||
| 	return p.WriteI64(ctx, int64(math.Float64bits(value))) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteString(ctx context.Context, value string) error { | ||||
| 	e := p.WriteI32(ctx, int32(len(value))) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	_, err := p.trans.WriteString(value) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) WriteBinary(ctx context.Context, value []byte) error { | ||||
| 	e := p.WriteI32(ctx, int32(len(value))) | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	_, err := p.trans.Write(value) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Reading methods | ||||
|  */ | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { | ||||
| 	size, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		return "", typeId, 0, NewTProtocolException(e) | ||||
| 	} | ||||
| 	if size < 0 { | ||||
| 		typeId = TMessageType(size & 0x0ff) | ||||
| 		version := int64(int64(size) & VERSION_MASK) | ||||
| 		if version != VERSION_1 { | ||||
| 			return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin")) | ||||
| 		} | ||||
| 		name, e = p.ReadString(ctx) | ||||
| 		if e != nil { | ||||
| 			return name, typeId, seqId, NewTProtocolException(e) | ||||
| 		} | ||||
| 		seqId, e = p.ReadI32(ctx) | ||||
| 		if e != nil { | ||||
| 			return name, typeId, seqId, NewTProtocolException(e) | ||||
| 		} | ||||
| 		return name, typeId, seqId, nil | ||||
| 	} | ||||
| 	if p.cfg.GetTBinaryStrictRead() { | ||||
| 		return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin")) | ||||
| 	} | ||||
| 	name, e2 := p.readStringBody(size) | ||||
| 	if e2 != nil { | ||||
| 		return name, typeId, seqId, e2 | ||||
| 	} | ||||
| 	b, e3 := p.ReadByte(ctx) | ||||
| 	if e3 != nil { | ||||
| 		return name, typeId, seqId, e3 | ||||
| 	} | ||||
| 	typeId = TMessageType(b) | ||||
| 	seqId, e4 := p.ReadI32(ctx) | ||||
| 	if e4 != nil { | ||||
| 		return name, typeId, seqId, e4 | ||||
| 	} | ||||
| 	return name, typeId, seqId, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadMessageEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadStructEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, seqId int16, err error) { | ||||
| 	t, err := p.ReadByte(ctx) | ||||
| 	typeId = TType(t) | ||||
| 	if err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	if t != STOP { | ||||
| 		seqId, err = p.ReadI16(ctx) | ||||
| 	} | ||||
| 	return name, typeId, seqId, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadFieldEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length")) | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadMapBegin(ctx context.Context) (kType, vType TType, size int, err error) { | ||||
| 	k, e := p.ReadByte(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	kType = TType(k) | ||||
| 	v, e := p.ReadByte(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	vType = TType(v) | ||||
| 	size32, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	if size32 < 0 { | ||||
| 		err = invalidDataLength | ||||
| 		return | ||||
| 	} | ||||
| 	size = int(size32) | ||||
| 	return kType, vType, size, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadMapEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	b, e := p.ReadByte(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	elemType = TType(b) | ||||
| 	size32, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	if size32 < 0 { | ||||
| 		err = invalidDataLength | ||||
| 		return | ||||
| 	} | ||||
| 	size = int(size32) | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadListEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	b, e := p.ReadByte(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	elemType = TType(b) | ||||
| 	size32, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	if size32 < 0 { | ||||
| 		err = invalidDataLength | ||||
| 		return | ||||
| 	} | ||||
| 	size = int(size32) | ||||
| 	return elemType, size, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadSetEnd(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadBool(ctx context.Context) (bool, error) { | ||||
| 	b, e := p.ReadByte(ctx) | ||||
| 	v := true | ||||
| 	if b != 1 { | ||||
| 		v = false | ||||
| 	} | ||||
| 	return v, e | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadByte(ctx context.Context) (int8, error) { | ||||
| 	v, err := p.trans.ReadByte() | ||||
| 	return int8(v), err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadI16(ctx context.Context) (value int16, err error) { | ||||
| 	buf := p.buffer[0:2] | ||||
| 	err = p.readAll(ctx, buf) | ||||
| 	value = int16(binary.BigEndian.Uint16(buf)) | ||||
| 	return value, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadI32(ctx context.Context) (value int32, err error) { | ||||
| 	buf := p.buffer[0:4] | ||||
| 	err = p.readAll(ctx, buf) | ||||
| 	value = int32(binary.BigEndian.Uint32(buf)) | ||||
| 	return value, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadI64(ctx context.Context) (value int64, err error) { | ||||
| 	buf := p.buffer[0:8] | ||||
| 	err = p.readAll(ctx, buf) | ||||
| 	value = int64(binary.BigEndian.Uint64(buf)) | ||||
| 	return value, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadDouble(ctx context.Context) (value float64, err error) { | ||||
| 	buf := p.buffer[0:8] | ||||
| 	err = p.readAll(ctx, buf) | ||||
| 	value = math.Float64frombits(binary.BigEndian.Uint64(buf)) | ||||
| 	return value, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadString(ctx context.Context) (value string, err error) { | ||||
| 	size, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		return "", e | ||||
| 	} | ||||
| 	err = checkSizeForProtocol(size, p.cfg) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if size < 0 { | ||||
| 		err = invalidDataLength | ||||
| 		return | ||||
| 	} | ||||
| 	if size == 0 { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	if size < int32(len(p.buffer)) { | ||||
| 		// Avoid allocation on small reads | ||||
| 		buf := p.buffer[:size] | ||||
| 		read, e := io.ReadFull(p.trans, buf) | ||||
| 		return string(buf[:read]), NewTProtocolException(e) | ||||
| 	} | ||||
| 
 | ||||
| 	return p.readStringBody(size) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) ReadBinary(ctx context.Context) ([]byte, error) { | ||||
| 	size, e := p.ReadI32(ctx) | ||||
| 	if e != nil { | ||||
| 		return nil, e | ||||
| 	} | ||||
| 	if err := checkSizeForProtocol(size, p.cfg); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	buf, err := safeReadBytes(size, p.trans) | ||||
| 	return buf, NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) Flush(ctx context.Context) (err error) { | ||||
| 	return NewTProtocolException(p.trans.Flush(ctx)) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) Skip(ctx context.Context, fieldType TType) (err error) { | ||||
| 	return SkipDefaultDepth(ctx, p, fieldType) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) Transport() TTransport { | ||||
| 	return p.origTransport | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) readAll(ctx context.Context, buf []byte) (err error) { | ||||
| 	var read int | ||||
| 	_, deadlineSet := ctx.Deadline() | ||||
| 	for { | ||||
| 		read, err = io.ReadFull(p.trans, buf) | ||||
| 		if deadlineSet && read == 0 && isTimeoutError(err) && ctx.Err() == nil { | ||||
| 			// This is I/O timeout without anything read, | ||||
| 			// and we still have time left, keep retrying. | ||||
| 			continue | ||||
| 		} | ||||
| 		// For anything else, don't retry | ||||
| 		break | ||||
| 	} | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) { | ||||
| 	buf, err := safeReadBytes(size, p.trans) | ||||
| 	return string(buf), NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TBinaryProtocol) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.trans, conf) | ||||
| 	PropagateTConfiguration(p.origTransport, conf) | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*TBinaryProtocolFactory)(nil) | ||||
| 	_ TConfigurationSetter = (*TBinaryProtocol)(nil) | ||||
| ) | ||||
| 
 | ||||
| // This function is shared between TBinaryProtocol and TCompactProtocol. | ||||
| // | ||||
| // It tries to read size bytes from trans, in a way that prevents large | ||||
| // allocations when size is insanely large (mostly caused by malformed message). | ||||
| func safeReadBytes(size int32, trans io.Reader) ([]byte, error) { | ||||
| 	if size < 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	_, err := io.CopyN(buf, trans, int64(size)) | ||||
| 	return buf.Bytes(), err | ||||
| } | ||||
|  | @ -1,99 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| type TBufferedTransportFactory struct { | ||||
| 	size int | ||||
| } | ||||
| 
 | ||||
| type TBufferedTransport struct { | ||||
| 	bufio.ReadWriter | ||||
| 	tp TTransport | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	return NewTBufferedTransport(trans, p.size), nil | ||||
| } | ||||
| 
 | ||||
| func NewTBufferedTransportFactory(bufferSize int) *TBufferedTransportFactory { | ||||
| 	return &TBufferedTransportFactory{size: bufferSize} | ||||
| } | ||||
| 
 | ||||
| func NewTBufferedTransport(trans TTransport, bufferSize int) *TBufferedTransport { | ||||
| 	return &TBufferedTransport{ | ||||
| 		ReadWriter: bufio.ReadWriter{ | ||||
| 			Reader: bufio.NewReaderSize(trans, bufferSize), | ||||
| 			Writer: bufio.NewWriterSize(trans, bufferSize), | ||||
| 		}, | ||||
| 		tp: trans, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) IsOpen() bool { | ||||
| 	return p.tp.IsOpen() | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) Open() (err error) { | ||||
| 	return p.tp.Open() | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) Close() (err error) { | ||||
| 	return p.tp.Close() | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) Read(b []byte) (int, error) { | ||||
| 	n, err := p.ReadWriter.Read(b) | ||||
| 	if err != nil { | ||||
| 		p.ReadWriter.Reader.Reset(p.tp) | ||||
| 	} | ||||
| 	return n, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) Write(b []byte) (int, error) { | ||||
| 	n, err := p.ReadWriter.Write(b) | ||||
| 	if err != nil { | ||||
| 		p.ReadWriter.Writer.Reset(p.tp) | ||||
| 	} | ||||
| 	return n, err | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) Flush(ctx context.Context) error { | ||||
| 	if err := p.ReadWriter.Flush(); err != nil { | ||||
| 		p.ReadWriter.Writer.Reset(p.tp) | ||||
| 		return err | ||||
| 	} | ||||
| 	return p.tp.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) { | ||||
| 	return p.tp.RemainingBytes() | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter for propagation. | ||||
| func (p *TBufferedTransport) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.tp, conf) | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TBufferedTransport)(nil) | ||||
|  | @ -1,109 +0,0 @@ | |||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| // ResponseMeta represents the metadata attached to the response. | ||||
| type ResponseMeta struct { | ||||
| 	// The headers in the response, if any. | ||||
| 	// If the underlying transport/protocol is not THeader, this will always be nil. | ||||
| 	Headers THeaderMap | ||||
| } | ||||
| 
 | ||||
| type TClient interface { | ||||
| 	Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) | ||||
| } | ||||
| 
 | ||||
| type TStandardClient struct { | ||||
| 	seqId        int32 | ||||
| 	iprot, oprot TProtocol | ||||
| } | ||||
| 
 | ||||
| // TStandardClient implements TClient, and uses the standard message format for Thrift. | ||||
| // It is not safe for concurrent use. | ||||
| func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClient { | ||||
| 	return &TStandardClient{ | ||||
| 		iprot: inputProtocol, | ||||
| 		oprot: outputProtocol, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error { | ||||
| 	// Set headers from context object on THeaderProtocol | ||||
| 	if headerProt, ok := oprot.(*THeaderProtocol); ok { | ||||
| 		headerProt.ClearWriteHeaders() | ||||
| 		for _, key := range GetWriteHeaderList(ctx) { | ||||
| 			if value, ok := GetHeader(ctx, key); ok { | ||||
| 				headerProt.SetWriteHeader(key, value) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := oprot.WriteMessageBegin(ctx, method, CALL, seqId); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := args.Write(ctx, oprot); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := oprot.WriteMessageEnd(ctx); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return oprot.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *TStandardClient) Recv(ctx context.Context, iprot TProtocol, seqId int32, method string, result TStruct) error { | ||||
| 	rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if method != rMethod { | ||||
| 		return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method)) | ||||
| 	} else if seqId != rSeqId { | ||||
| 		return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method)) | ||||
| 	} else if rTypeId == EXCEPTION { | ||||
| 		var exception tApplicationException | ||||
| 		if err := exception.Read(ctx, iprot); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		if err := iprot.ReadMessageEnd(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		return &exception | ||||
| 	} else if rTypeId != REPLY { | ||||
| 		return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method)) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := result.Read(ctx, iprot); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return iprot.ReadMessageEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { | ||||
| 	p.seqId++ | ||||
| 	seqId := p.seqId | ||||
| 
 | ||||
| 	if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil { | ||||
| 		return ResponseMeta{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	// method is oneway | ||||
| 	if result == nil { | ||||
| 		return ResponseMeta{}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	err := p.Recv(ctx, p.iprot, seqId, method, result) | ||||
| 	var headers THeaderMap | ||||
| 	if hp, ok := p.iprot.(*THeaderProtocol); ok { | ||||
| 		headers = hp.transport.readHeaders | ||||
| 	} | ||||
| 	return ResponseMeta{ | ||||
| 		Headers: headers, | ||||
| 	}, err | ||||
| } | ||||
|  | @ -1,865 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	COMPACT_PROTOCOL_ID       = 0x082 | ||||
| 	COMPACT_VERSION           = 1 | ||||
| 	COMPACT_VERSION_MASK      = 0x1f | ||||
| 	COMPACT_TYPE_MASK         = 0x0E0 | ||||
| 	COMPACT_TYPE_BITS         = 0x07 | ||||
| 	COMPACT_TYPE_SHIFT_AMOUNT = 5 | ||||
| ) | ||||
| 
 | ||||
| type tCompactType byte | ||||
| 
 | ||||
| const ( | ||||
| 	COMPACT_BOOLEAN_TRUE  = 0x01 | ||||
| 	COMPACT_BOOLEAN_FALSE = 0x02 | ||||
| 	COMPACT_BYTE          = 0x03 | ||||
| 	COMPACT_I16           = 0x04 | ||||
| 	COMPACT_I32           = 0x05 | ||||
| 	COMPACT_I64           = 0x06 | ||||
| 	COMPACT_DOUBLE        = 0x07 | ||||
| 	COMPACT_BINARY        = 0x08 | ||||
| 	COMPACT_LIST          = 0x09 | ||||
| 	COMPACT_SET           = 0x0A | ||||
| 	COMPACT_MAP           = 0x0B | ||||
| 	COMPACT_STRUCT        = 0x0C | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	ttypeToCompactType map[TType]tCompactType | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	ttypeToCompactType = map[TType]tCompactType{ | ||||
| 		STOP:   STOP, | ||||
| 		BOOL:   COMPACT_BOOLEAN_TRUE, | ||||
| 		BYTE:   COMPACT_BYTE, | ||||
| 		I16:    COMPACT_I16, | ||||
| 		I32:    COMPACT_I32, | ||||
| 		I64:    COMPACT_I64, | ||||
| 		DOUBLE: COMPACT_DOUBLE, | ||||
| 		STRING: COMPACT_BINARY, | ||||
| 		LIST:   COMPACT_LIST, | ||||
| 		SET:    COMPACT_SET, | ||||
| 		MAP:    COMPACT_MAP, | ||||
| 		STRUCT: COMPACT_STRUCT, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type TCompactProtocolFactory struct { | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTCompactProtocolFactoryConf instead. | ||||
| func NewTCompactProtocolFactory() *TCompactProtocolFactory { | ||||
| 	return NewTCompactProtocolFactoryConf(&TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTCompactProtocolFactoryConf(conf *TConfiguration) *TCompactProtocolFactory { | ||||
| 	return &TCompactProtocolFactory{ | ||||
| 		cfg: conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { | ||||
| 	return NewTCompactProtocolConf(trans, p.cfg) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocolFactory) SetTConfiguration(conf *TConfiguration) { | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| type TCompactProtocol struct { | ||||
| 	trans         TRichTransport | ||||
| 	origTransport TTransport | ||||
| 
 | ||||
| 	cfg *TConfiguration | ||||
| 
 | ||||
| 	// Used to keep track of the last field for the current and previous structs, | ||||
| 	// so we can do the delta stuff. | ||||
| 	lastField   []int | ||||
| 	lastFieldId int | ||||
| 
 | ||||
| 	// If we encounter a boolean field begin, save the TField here so it can | ||||
| 	// have the value incorporated. | ||||
| 	booleanFieldName    string | ||||
| 	booleanFieldId      int16 | ||||
| 	booleanFieldPending bool | ||||
| 
 | ||||
| 	// If we read a field header, and it's a boolean field, save the boolean | ||||
| 	// value here so that readBool can use it. | ||||
| 	boolValue          bool | ||||
| 	boolValueIsNotNull bool | ||||
| 	buffer             [64]byte | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTCompactProtocolConf instead. | ||||
| func NewTCompactProtocol(trans TTransport) *TCompactProtocol { | ||||
| 	return NewTCompactProtocolConf(trans, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTCompactProtocolConf(trans TTransport, conf *TConfiguration) *TCompactProtocol { | ||||
| 	PropagateTConfiguration(trans, conf) | ||||
| 	p := &TCompactProtocol{ | ||||
| 		origTransport: trans, | ||||
| 		cfg:           conf, | ||||
| 	} | ||||
| 	if et, ok := trans.(TRichTransport); ok { | ||||
| 		p.trans = et | ||||
| 	} else { | ||||
| 		p.trans = NewTRichTransport(trans) | ||||
| 	} | ||||
| 
 | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // Public Writing methods. | ||||
| // | ||||
| 
 | ||||
| // Write a message header to the wire. Compact Protocol messages contain the | ||||
| // protocol version so we can migrate forwards in the future if need be. | ||||
| func (p *TCompactProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { | ||||
| 	err := p.writeByteDirect(COMPACT_PROTOCOL_ID) | ||||
| 	if err != nil { | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) | ||||
| 	if err != nil { | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	_, err = p.writeVarint32(seqid) | ||||
| 	if err != nil { | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	e := p.WriteString(ctx, name) | ||||
| 	return e | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteMessageEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Write a struct begin. This doesn't actually put anything on the wire. We | ||||
| // use it as an opportunity to put special placeholder markers on the field | ||||
| // stack so we can get the field id deltas correct. | ||||
| func (p *TCompactProtocol) WriteStructBegin(ctx context.Context, name string) error { | ||||
| 	p.lastField = append(p.lastField, p.lastFieldId) | ||||
| 	p.lastFieldId = 0 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Write a struct end. This doesn't actually put anything on the wire. We use | ||||
| // this as an opportunity to pop the last field from the current struct off | ||||
| // of the field stack. | ||||
| func (p *TCompactProtocol) WriteStructEnd(ctx context.Context) error { | ||||
| 	if len(p.lastField) <= 0 { | ||||
| 		return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("WriteStructEnd called without matching WriteStructBegin call before")) | ||||
| 	} | ||||
| 	p.lastFieldId = p.lastField[len(p.lastField)-1] | ||||
| 	p.lastField = p.lastField[:len(p.lastField)-1] | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { | ||||
| 	if typeId == BOOL { | ||||
| 		// we want to possibly include the value, so we'll wait. | ||||
| 		p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true | ||||
| 		return nil | ||||
| 	} | ||||
| 	_, err := p.writeFieldBeginInternal(ctx, name, typeId, id, 0xFF) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // The workhorse of writeFieldBegin. It has the option of doing a | ||||
| // 'type override' of the type header. This is used specifically in the | ||||
| // boolean field case. | ||||
| func (p *TCompactProtocol) writeFieldBeginInternal(ctx context.Context, name string, typeId TType, id int16, typeOverride byte) (int, error) { | ||||
| 	// short lastField = lastField_.pop(); | ||||
| 
 | ||||
| 	// if there's a type override, use that. | ||||
| 	var typeToWrite byte | ||||
| 	if typeOverride == 0xFF { | ||||
| 		typeToWrite = byte(p.getCompactType(typeId)) | ||||
| 	} else { | ||||
| 		typeToWrite = typeOverride | ||||
| 	} | ||||
| 	// check if we can use delta encoding for the field id | ||||
| 	fieldId := int(id) | ||||
| 	written := 0 | ||||
| 	if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 { | ||||
| 		// write them together | ||||
| 		err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 	} else { | ||||
| 		// write them separate | ||||
| 		err := p.writeByteDirect(typeToWrite) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		err = p.WriteI16(ctx, id) | ||||
| 		written = 1 + 2 | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	p.lastFieldId = fieldId | ||||
| 	return written, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteFieldEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteFieldStop(ctx context.Context) error { | ||||
| 	err := p.writeByteDirect(STOP) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { | ||||
| 	if size == 0 { | ||||
| 		err := p.writeByteDirect(0) | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	_, err := p.writeVarint32(int32(size)) | ||||
| 	if err != nil { | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType))) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteMapEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Write a list header. | ||||
| func (p *TCompactProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	_, err := p.writeCollectionBegin(elemType, size) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteListEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Write a set header. | ||||
| func (p *TCompactProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	_, err := p.writeCollectionBegin(elemType, size) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteSetEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| func (p *TCompactProtocol) WriteBool(ctx context.Context, value bool) error { | ||||
| 	v := byte(COMPACT_BOOLEAN_FALSE) | ||||
| 	if value { | ||||
| 		v = byte(COMPACT_BOOLEAN_TRUE) | ||||
| 	} | ||||
| 	if p.booleanFieldPending { | ||||
| 		// we haven't written the field header yet | ||||
| 		_, err := p.writeFieldBeginInternal(ctx, p.booleanFieldName, BOOL, p.booleanFieldId, v) | ||||
| 		p.booleanFieldPending = false | ||||
| 		return NewTProtocolException(err) | ||||
| 	} | ||||
| 	// we're not part of a field, so just write the value. | ||||
| 	err := p.writeByteDirect(v) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write a byte. Nothing to see here! | ||||
| func (p *TCompactProtocol) WriteByte(ctx context.Context, value int8) error { | ||||
| 	err := p.writeByteDirect(byte(value)) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write an I16 as a zigzag varint. | ||||
| func (p *TCompactProtocol) WriteI16(ctx context.Context, value int16) error { | ||||
| 	_, err := p.writeVarint32(p.int32ToZigzag(int32(value))) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write an i32 as a zigzag varint. | ||||
| func (p *TCompactProtocol) WriteI32(ctx context.Context, value int32) error { | ||||
| 	_, err := p.writeVarint32(p.int32ToZigzag(value)) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write an i64 as a zigzag varint. | ||||
| func (p *TCompactProtocol) WriteI64(ctx context.Context, value int64) error { | ||||
| 	_, err := p.writeVarint64(p.int64ToZigzag(value)) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write a double to the wire as 8 bytes. | ||||
| func (p *TCompactProtocol) WriteDouble(ctx context.Context, value float64) error { | ||||
| 	buf := p.buffer[0:8] | ||||
| 	binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) | ||||
| 	_, err := p.trans.Write(buf) | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| // Write a string to the wire with a varint size preceding. | ||||
| func (p *TCompactProtocol) WriteString(ctx context.Context, value string) error { | ||||
| 	_, e := p.writeVarint32(int32(len(value))) | ||||
| 	if e != nil { | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	if len(value) > 0 { | ||||
| 	} | ||||
| 	_, e = p.trans.WriteString(value) | ||||
| 	return e | ||||
| } | ||||
| 
 | ||||
| // Write a byte array, using a varint for the size. | ||||
| func (p *TCompactProtocol) WriteBinary(ctx context.Context, bin []byte) error { | ||||
| 	_, e := p.writeVarint32(int32(len(bin))) | ||||
| 	if e != nil { | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	if len(bin) > 0 { | ||||
| 		_, e = p.trans.Write(bin) | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // Reading methods. | ||||
| // | ||||
| 
 | ||||
| // Read a message header. | ||||
| func (p *TCompactProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { | ||||
| 	var protocolId byte | ||||
| 
 | ||||
| 	_, deadlineSet := ctx.Deadline() | ||||
| 	for { | ||||
| 		protocolId, err = p.readByteDirect() | ||||
| 		if deadlineSet && isTimeoutError(err) && ctx.Err() == nil { | ||||
| 			// keep retrying I/O timeout errors since we still have | ||||
| 			// time left | ||||
| 			continue | ||||
| 		} | ||||
| 		// For anything else, don't retry | ||||
| 		break | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if protocolId != COMPACT_PROTOCOL_ID { | ||||
| 		e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId) | ||||
| 		return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e) | ||||
| 	} | ||||
| 
 | ||||
| 	versionAndType, err := p.readByteDirect() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	version := versionAndType & COMPACT_VERSION_MASK | ||||
| 	typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS) | ||||
| 	if version != COMPACT_VERSION { | ||||
| 		e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version) | ||||
| 		err = NewTProtocolExceptionWithType(BAD_VERSION, e) | ||||
| 		return | ||||
| 	} | ||||
| 	seqId, e := p.readVarint32() | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	name, err = p.ReadString(ctx) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) ReadMessageEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Read a struct begin. There's nothing on the wire for this, but it is our | ||||
| // opportunity to push a new struct begin marker onto the field stack. | ||||
| func (p *TCompactProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { | ||||
| 	p.lastField = append(p.lastField, p.lastFieldId) | ||||
| 	p.lastFieldId = 0 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Doesn't actually consume any wire data, just removes the last field for | ||||
| // this struct from the field stack. | ||||
| func (p *TCompactProtocol) ReadStructEnd(ctx context.Context) error { | ||||
| 	// consume the last field we read off the wire. | ||||
| 	if len(p.lastField) <= 0 { | ||||
| 		return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("ReadStructEnd called without matching ReadStructBegin call before")) | ||||
| 	} | ||||
| 	p.lastFieldId = p.lastField[len(p.lastField)-1] | ||||
| 	p.lastField = p.lastField[:len(p.lastField)-1] | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Read a field header off the wire. | ||||
| func (p *TCompactProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) { | ||||
| 	t, err := p.readByteDirect() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// if it's a stop, then we can return immediately, as the struct is over. | ||||
| 	if (t & 0x0f) == STOP { | ||||
| 		return "", STOP, 0, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// mask off the 4 MSB of the type header. it could contain a field id delta. | ||||
| 	modifier := int16((t & 0xf0) >> 4) | ||||
| 	if modifier == 0 { | ||||
| 		// not a delta. look ahead for the zigzag varint field id. | ||||
| 		id, err = p.ReadI16(ctx) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} else { | ||||
| 		// has a delta. add the delta to the last read field id. | ||||
| 		id = int16(p.lastFieldId) + modifier | ||||
| 	} | ||||
| 	typeId, e := p.getTType(tCompactType(t & 0x0f)) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// if this happens to be a boolean field, the value is encoded in the type | ||||
| 	if p.isBoolType(t) { | ||||
| 		// save the boolean value in a special instance variable. | ||||
| 		p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE) | ||||
| 		p.boolValueIsNotNull = true | ||||
| 	} | ||||
| 
 | ||||
| 	// push the new field onto the field stack so we can keep the deltas going. | ||||
| 	p.lastFieldId = int(id) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) ReadFieldEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Read a map header off the wire. If the size is zero, skip reading the key | ||||
| // and value type. This means that 0-length maps will yield TMaps without the | ||||
| // "correct" types. | ||||
| func (p *TCompactProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { | ||||
| 	size32, e := p.readVarint32() | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	if size32 < 0 { | ||||
| 		err = invalidDataLength | ||||
| 		return | ||||
| 	} | ||||
| 	size = int(size32) | ||||
| 
 | ||||
| 	keyAndValueType := byte(STOP) | ||||
| 	if size != 0 { | ||||
| 		keyAndValueType, err = p.readByteDirect() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4)) | ||||
| 	valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf)) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) ReadMapEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Read a list header off the wire. If the list size is 0-14, the size will | ||||
| // be packed into the element type header. If it's a longer list, the 4 MSB | ||||
| // of the element type header will be 0xF, and a varint will follow with the | ||||
| // true size. | ||||
| func (p *TCompactProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	size_and_type, err := p.readByteDirect() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	size = int((size_and_type >> 4) & 0x0f) | ||||
| 	if size == 15 { | ||||
| 		size2, e := p.readVarint32() | ||||
| 		if e != nil { | ||||
| 			err = NewTProtocolException(e) | ||||
| 			return | ||||
| 		} | ||||
| 		if size2 < 0 { | ||||
| 			err = invalidDataLength | ||||
| 			return | ||||
| 		} | ||||
| 		size = int(size2) | ||||
| 	} | ||||
| 	elemType, e := p.getTType(tCompactType(size_and_type)) | ||||
| 	if e != nil { | ||||
| 		err = NewTProtocolException(e) | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) ReadListEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Read a set header off the wire. If the set size is 0-14, the size will | ||||
| // be packed into the element type header. If it's a longer set, the 4 MSB | ||||
| // of the element type header will be 0xF, and a varint will follow with the | ||||
| // true size. | ||||
| func (p *TCompactProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	return p.ReadListBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) ReadSetEnd(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| // Read a boolean off the wire. If this is a boolean field, the value should | ||||
| // already have been read during readFieldBegin, so we'll just consume the | ||||
| // pre-stored value. Otherwise, read a byte. | ||||
| func (p *TCompactProtocol) ReadBool(ctx context.Context) (value bool, err error) { | ||||
| 	if p.boolValueIsNotNull { | ||||
| 		p.boolValueIsNotNull = false | ||||
| 		return p.boolValue, nil | ||||
| 	} | ||||
| 	v, err := p.readByteDirect() | ||||
| 	return v == COMPACT_BOOLEAN_TRUE, err | ||||
| } | ||||
| 
 | ||||
| // Read a single byte off the wire. Nothing interesting here. | ||||
| func (p *TCompactProtocol) ReadByte(ctx context.Context) (int8, error) { | ||||
| 	v, err := p.readByteDirect() | ||||
| 	if err != nil { | ||||
| 		return 0, NewTProtocolException(err) | ||||
| 	} | ||||
| 	return int8(v), err | ||||
| } | ||||
| 
 | ||||
| // Read an i16 from the wire as a zigzag varint. | ||||
| func (p *TCompactProtocol) ReadI16(ctx context.Context) (value int16, err error) { | ||||
| 	v, err := p.ReadI32(ctx) | ||||
| 	return int16(v), err | ||||
| } | ||||
| 
 | ||||
| // Read an i32 from the wire as a zigzag varint. | ||||
| func (p *TCompactProtocol) ReadI32(ctx context.Context) (value int32, err error) { | ||||
| 	v, e := p.readVarint32() | ||||
| 	if e != nil { | ||||
| 		return 0, NewTProtocolException(e) | ||||
| 	} | ||||
| 	value = p.zigzagToInt32(v) | ||||
| 	return value, nil | ||||
| } | ||||
| 
 | ||||
| // Read an i64 from the wire as a zigzag varint. | ||||
| func (p *TCompactProtocol) ReadI64(ctx context.Context) (value int64, err error) { | ||||
| 	v, e := p.readVarint64() | ||||
| 	if e != nil { | ||||
| 		return 0, NewTProtocolException(e) | ||||
| 	} | ||||
| 	value = p.zigzagToInt64(v) | ||||
| 	return value, nil | ||||
| } | ||||
| 
 | ||||
| // No magic here - just read a double off the wire. | ||||
| func (p *TCompactProtocol) ReadDouble(ctx context.Context) (value float64, err error) { | ||||
| 	longBits := p.buffer[0:8] | ||||
| 	_, e := io.ReadFull(p.trans, longBits) | ||||
| 	if e != nil { | ||||
| 		return 0.0, NewTProtocolException(e) | ||||
| 	} | ||||
| 	return math.Float64frombits(p.bytesToUint64(longBits)), nil | ||||
| } | ||||
| 
 | ||||
| // Reads a []byte (via readBinary), and then UTF-8 decodes it. | ||||
| func (p *TCompactProtocol) ReadString(ctx context.Context) (value string, err error) { | ||||
| 	length, e := p.readVarint32() | ||||
| 	if e != nil { | ||||
| 		return "", NewTProtocolException(e) | ||||
| 	} | ||||
| 	err = checkSizeForProtocol(length, p.cfg) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if length == 0 { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	if length < int32(len(p.buffer)) { | ||||
| 		// Avoid allocation on small reads | ||||
| 		buf := p.buffer[:length] | ||||
| 		read, e := io.ReadFull(p.trans, buf) | ||||
| 		return string(buf[:read]), NewTProtocolException(e) | ||||
| 	} | ||||
| 
 | ||||
| 	buf, e := safeReadBytes(length, p.trans) | ||||
| 	return string(buf), NewTProtocolException(e) | ||||
| } | ||||
| 
 | ||||
| // Read a []byte from the wire. | ||||
| func (p *TCompactProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { | ||||
| 	length, e := p.readVarint32() | ||||
| 	if e != nil { | ||||
| 		return nil, NewTProtocolException(e) | ||||
| 	} | ||||
| 	err = checkSizeForProtocol(length, p.cfg) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if length == 0 { | ||||
| 		return []byte{}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	buf, e := safeReadBytes(length, p.trans) | ||||
| 	return buf, NewTProtocolException(e) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) Flush(ctx context.Context) (err error) { | ||||
| 	return NewTProtocolException(p.trans.Flush(ctx)) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) Skip(ctx context.Context, fieldType TType) (err error) { | ||||
| 	return SkipDefaultDepth(ctx, p, fieldType) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) Transport() TTransport { | ||||
| 	return p.origTransport | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // Internal writing methods | ||||
| // | ||||
| 
 | ||||
| // Abstract method for writing the start of lists and sets. List and sets on | ||||
| // the wire differ only by the type indicator. | ||||
| func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) { | ||||
| 	if size <= 14 { | ||||
| 		return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType)))) | ||||
| 	} | ||||
| 	err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType))) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	m, err := p.writeVarint32(int32(size)) | ||||
| 	return 1 + m, err | ||||
| } | ||||
| 
 | ||||
| // Write an i32 as a varint. Results in 1-5 bytes on the wire. | ||||
| // TODO(pomack): make a permanent buffer like writeVarint64? | ||||
| func (p *TCompactProtocol) writeVarint32(n int32) (int, error) { | ||||
| 	i32buf := p.buffer[0:5] | ||||
| 	idx := 0 | ||||
| 	for { | ||||
| 		if (n & ^0x7F) == 0 { | ||||
| 			i32buf[idx] = byte(n) | ||||
| 			idx++ | ||||
| 			// p.writeByteDirect(byte(n)); | ||||
| 			break | ||||
| 			// return; | ||||
| 		} else { | ||||
| 			i32buf[idx] = byte((n & 0x7F) | 0x80) | ||||
| 			idx++ | ||||
| 			// p.writeByteDirect(byte(((n & 0x7F) | 0x80))); | ||||
| 			u := uint32(n) | ||||
| 			n = int32(u >> 7) | ||||
| 		} | ||||
| 	} | ||||
| 	return p.trans.Write(i32buf[0:idx]) | ||||
| } | ||||
| 
 | ||||
| // Write an i64 as a varint. Results in 1-10 bytes on the wire. | ||||
| func (p *TCompactProtocol) writeVarint64(n int64) (int, error) { | ||||
| 	varint64out := p.buffer[0:10] | ||||
| 	idx := 0 | ||||
| 	for { | ||||
| 		if (n & ^0x7F) == 0 { | ||||
| 			varint64out[idx] = byte(n) | ||||
| 			idx++ | ||||
| 			break | ||||
| 		} else { | ||||
| 			varint64out[idx] = byte((n & 0x7F) | 0x80) | ||||
| 			idx++ | ||||
| 			u := uint64(n) | ||||
| 			n = int64(u >> 7) | ||||
| 		} | ||||
| 	} | ||||
| 	return p.trans.Write(varint64out[0:idx]) | ||||
| } | ||||
| 
 | ||||
| // Convert l into a zigzag long. This allows negative numbers to be | ||||
| // represented compactly as a varint. | ||||
| func (p *TCompactProtocol) int64ToZigzag(l int64) int64 { | ||||
| 	return (l << 1) ^ (l >> 63) | ||||
| } | ||||
| 
 | ||||
| // Convert l into a zigzag long. This allows negative numbers to be | ||||
| // represented compactly as a varint. | ||||
| func (p *TCompactProtocol) int32ToZigzag(n int32) int32 { | ||||
| 	return (n << 1) ^ (n >> 31) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) { | ||||
| 	binary.LittleEndian.PutUint64(buf, n) | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) { | ||||
| 	binary.LittleEndian.PutUint64(buf, uint64(n)) | ||||
| } | ||||
| 
 | ||||
| // Writes a byte without any possibility of all that field header nonsense. | ||||
| // Used internally by other writing methods that know they need to write a byte. | ||||
| func (p *TCompactProtocol) writeByteDirect(b byte) error { | ||||
| 	return p.trans.WriteByte(b) | ||||
| } | ||||
| 
 | ||||
| // Writes a byte without any possibility of all that field header nonsense. | ||||
| func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) { | ||||
| 	return 1, p.writeByteDirect(byte(n)) | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // Internal reading methods | ||||
| // | ||||
| 
 | ||||
| // Read an i32 from the wire as a varint. The MSB of each byte is set | ||||
| // if there is another byte to follow. This can read up to 5 bytes. | ||||
| func (p *TCompactProtocol) readVarint32() (int32, error) { | ||||
| 	// if the wire contains the right stuff, this will just truncate the i64 we | ||||
| 	// read and get us the right sign. | ||||
| 	v, err := p.readVarint64() | ||||
| 	return int32(v), err | ||||
| } | ||||
| 
 | ||||
| // Read an i64 from the wire as a proper varint. The MSB of each byte is set | ||||
| // if there is another byte to follow. This can read up to 10 bytes. | ||||
| func (p *TCompactProtocol) readVarint64() (int64, error) { | ||||
| 	shift := uint(0) | ||||
| 	result := int64(0) | ||||
| 	for { | ||||
| 		b, err := p.readByteDirect() | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		result |= int64(b&0x7f) << shift | ||||
| 		if (b & 0x80) != 0x80 { | ||||
| 			break | ||||
| 		} | ||||
| 		shift += 7 | ||||
| 	} | ||||
| 	return result, nil | ||||
| } | ||||
| 
 | ||||
| // Read a byte, unlike ReadByte that reads Thrift-byte that is i8. | ||||
| func (p *TCompactProtocol) readByteDirect() (byte, error) { | ||||
| 	return p.trans.ReadByte() | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // encoding helpers | ||||
| // | ||||
| 
 | ||||
| // Convert from zigzag int to int. | ||||
| func (p *TCompactProtocol) zigzagToInt32(n int32) int32 { | ||||
| 	u := uint32(n) | ||||
| 	return int32(u>>1) ^ -(n & 1) | ||||
| } | ||||
| 
 | ||||
| // Convert from zigzag long to long. | ||||
| func (p *TCompactProtocol) zigzagToInt64(n int64) int64 { | ||||
| 	u := uint64(n) | ||||
| 	return int64(u>>1) ^ -(n & 1) | ||||
| } | ||||
| 
 | ||||
| // Note that it's important that the mask bytes are long literals, | ||||
| // otherwise they'll default to ints, and when you shift an int left 56 bits, | ||||
| // you just get a messed up int. | ||||
| func (p *TCompactProtocol) bytesToInt64(b []byte) int64 { | ||||
| 	return int64(binary.LittleEndian.Uint64(b)) | ||||
| } | ||||
| 
 | ||||
| // Note that it's important that the mask bytes are long literals, | ||||
| // otherwise they'll default to ints, and when you shift an int left 56 bits, | ||||
| // you just get a messed up int. | ||||
| func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 { | ||||
| 	return binary.LittleEndian.Uint64(b) | ||||
| } | ||||
| 
 | ||||
| // | ||||
| // type testing and converting | ||||
| // | ||||
| 
 | ||||
| func (p *TCompactProtocol) isBoolType(b byte) bool { | ||||
| 	return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE | ||||
| } | ||||
| 
 | ||||
| // Given a tCompactType constant, convert it to its corresponding | ||||
| // TType value. | ||||
| func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { | ||||
| 	switch byte(t) & 0x0f { | ||||
| 	case STOP: | ||||
| 		return STOP, nil | ||||
| 	case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE: | ||||
| 		return BOOL, nil | ||||
| 	case COMPACT_BYTE: | ||||
| 		return BYTE, nil | ||||
| 	case COMPACT_I16: | ||||
| 		return I16, nil | ||||
| 	case COMPACT_I32: | ||||
| 		return I32, nil | ||||
| 	case COMPACT_I64: | ||||
| 		return I64, nil | ||||
| 	case COMPACT_DOUBLE: | ||||
| 		return DOUBLE, nil | ||||
| 	case COMPACT_BINARY: | ||||
| 		return STRING, nil | ||||
| 	case COMPACT_LIST: | ||||
| 		return LIST, nil | ||||
| 	case COMPACT_SET: | ||||
| 		return SET, nil | ||||
| 	case COMPACT_MAP: | ||||
| 		return MAP, nil | ||||
| 	case COMPACT_STRUCT: | ||||
| 		return STRUCT, nil | ||||
| 	} | ||||
| 	return STOP, NewTProtocolException(fmt.Errorf("don't know what type: %v", t&0x0f)) | ||||
| } | ||||
| 
 | ||||
| // Given a TType value, find the appropriate TCompactProtocol.Types constant. | ||||
| func (p *TCompactProtocol) getCompactType(t TType) tCompactType { | ||||
| 	return ttypeToCompactType[t] | ||||
| } | ||||
| 
 | ||||
| func (p *TCompactProtocol) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.trans, conf) | ||||
| 	PropagateTConfiguration(p.origTransport, conf) | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*TCompactProtocolFactory)(nil) | ||||
| 	_ TConfigurationSetter = (*TCompactProtocol)(nil) | ||||
| ) | ||||
|  | @ -1,378 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Default TConfiguration values. | ||||
| const ( | ||||
| 	DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024 | ||||
| 	DEFAULT_MAX_FRAME_SIZE   = 16384000 | ||||
| 
 | ||||
| 	DEFAULT_TBINARY_STRICT_READ  = false | ||||
| 	DEFAULT_TBINARY_STRICT_WRITE = true | ||||
| 
 | ||||
| 	DEFAULT_CONNECT_TIMEOUT = 0 | ||||
| 	DEFAULT_SOCKET_TIMEOUT  = 0 | ||||
| ) | ||||
| 
 | ||||
| // TConfiguration defines some configurations shared between TTransport, | ||||
| // TProtocol, TTransportFactory, TProtocolFactory, and other implementations. | ||||
| // | ||||
| // When constructing TConfiguration, you only need to specify the non-default | ||||
| // fields. All zero values have sane default values. | ||||
| // | ||||
| // Not all configurations defined are applicable to all implementations. | ||||
| // Implementations are free to ignore the configurations not applicable to them. | ||||
| // | ||||
| // All functions attached to this type are nil-safe. | ||||
| // | ||||
| // See [1] for spec. | ||||
| // | ||||
| // NOTE: When using TConfiguration, fill in all the configurations you want to | ||||
| // set across the stack, not only the ones you want to set in the immediate | ||||
| // TTransport/TProtocol. | ||||
| // | ||||
| // For example, say you want to migrate this old code into using TConfiguration: | ||||
| // | ||||
| //     sccket := thrift.NewTSocketTimeout("host:port", time.Second) | ||||
| //     transFactory := thrift.NewTFramedTransportFactoryMaxLength( | ||||
| //         thrift.NewTTransportFactory(), | ||||
| //         1024 * 1024 * 256, | ||||
| //     ) | ||||
| //     protoFactory := thrift.NewTBinaryProtocolFactory(true, true) | ||||
| // | ||||
| // This is the wrong way to do it because in the end the TConfiguration used by | ||||
| // socket and transFactory will be overwritten by the one used by protoFactory | ||||
| // because of TConfiguration propagation: | ||||
| // | ||||
| //     // bad example, DO NOT USE | ||||
| //     sccket := thrift.NewTSocketConf("host:port", &thrift.TConfiguration{ | ||||
| //         ConnectTimeout: time.Second, | ||||
| //         SocketTimeout:  time.Second, | ||||
| //     }) | ||||
| //     transFactory := thrift.NewTFramedTransportFactoryConf( | ||||
| //         thrift.NewTTransportFactory(), | ||||
| //         &thrift.TConfiguration{ | ||||
| //             MaxFrameSize: 1024 * 1024 * 256, | ||||
| //         }, | ||||
| //     ) | ||||
| //     protoFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{ | ||||
| //         TBinaryStrictRead:  thrift.BoolPtr(true), | ||||
| //         TBinaryStrictWrite: thrift.BoolPtr(true), | ||||
| //     }) | ||||
| // | ||||
| // This is the correct way to do it: | ||||
| // | ||||
| //     conf := &thrift.TConfiguration{ | ||||
| //         ConnectTimeout: time.Second, | ||||
| //         SocketTimeout:  time.Second, | ||||
| // | ||||
| //         MaxFrameSize: 1024 * 1024 * 256, | ||||
| // | ||||
| //         TBinaryStrictRead:  thrift.BoolPtr(true), | ||||
| //         TBinaryStrictWrite: thrift.BoolPtr(true), | ||||
| //     } | ||||
| //     sccket := thrift.NewTSocketConf("host:port", conf) | ||||
| //     transFactory := thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), conf) | ||||
| //     protoFactory := thrift.NewTBinaryProtocolFactoryConf(conf) | ||||
| // | ||||
| // [1]: https://github.com/apache/thrift/blob/master/doc/specs/thrift-tconfiguration.md | ||||
| type TConfiguration struct { | ||||
| 	// If <= 0, DEFAULT_MAX_MESSAGE_SIZE will be used instead. | ||||
| 	MaxMessageSize int32 | ||||
| 
 | ||||
| 	// If <= 0, DEFAULT_MAX_FRAME_SIZE will be used instead. | ||||
| 	// | ||||
| 	// Also if MaxMessageSize < MaxFrameSize, | ||||
| 	// MaxMessageSize will be used instead. | ||||
| 	MaxFrameSize int32 | ||||
| 
 | ||||
| 	// Connect and socket timeouts to be used by TSocket and TSSLSocket. | ||||
| 	// | ||||
| 	// 0 means no timeout. | ||||
| 	// | ||||
| 	// If <0, DEFAULT_CONNECT_TIMEOUT and DEFAULT_SOCKET_TIMEOUT will be | ||||
| 	// used. | ||||
| 	ConnectTimeout time.Duration | ||||
| 	SocketTimeout  time.Duration | ||||
| 
 | ||||
| 	// TLS config to be used by TSSLSocket. | ||||
| 	TLSConfig *tls.Config | ||||
| 
 | ||||
| 	// Strict read/write configurations for TBinaryProtocol. | ||||
| 	// | ||||
| 	// BoolPtr helper function is available to use literal values. | ||||
| 	TBinaryStrictRead  *bool | ||||
| 	TBinaryStrictWrite *bool | ||||
| 
 | ||||
| 	// The wrapped protocol id to be used in THeader transport/protocol. | ||||
| 	// | ||||
| 	// THeaderProtocolIDPtr and THeaderProtocolIDPtrMust helper functions | ||||
| 	// are provided to help filling this value. | ||||
| 	THeaderProtocolID *THeaderProtocolID | ||||
| 
 | ||||
| 	// Used internally by deprecated constructors, to avoid overriding | ||||
| 	// underlying TTransport/TProtocol's cfg by accidental propagations. | ||||
| 	// | ||||
| 	// For external users this is always false. | ||||
| 	noPropagation bool | ||||
| } | ||||
| 
 | ||||
| // GetMaxMessageSize returns the max message size an implementation should | ||||
| // follow. | ||||
| // | ||||
| // It's nil-safe. DEFAULT_MAX_MESSAGE_SIZE will be returned if tc is nil. | ||||
| func (tc *TConfiguration) GetMaxMessageSize() int32 { | ||||
| 	if tc == nil || tc.MaxMessageSize <= 0 { | ||||
| 		return DEFAULT_MAX_MESSAGE_SIZE | ||||
| 	} | ||||
| 	return tc.MaxMessageSize | ||||
| } | ||||
| 
 | ||||
| // GetMaxFrameSize returns the max frame size an implementation should follow. | ||||
| // | ||||
| // It's nil-safe. DEFAULT_MAX_FRAME_SIZE will be returned if tc is nil. | ||||
| // | ||||
| // If the configured max message size is smaller than the configured max frame | ||||
| // size, the smaller one will be returned instead. | ||||
| func (tc *TConfiguration) GetMaxFrameSize() int32 { | ||||
| 	if tc == nil { | ||||
| 		return DEFAULT_MAX_FRAME_SIZE | ||||
| 	} | ||||
| 	maxFrameSize := tc.MaxFrameSize | ||||
| 	if maxFrameSize <= 0 { | ||||
| 		maxFrameSize = DEFAULT_MAX_FRAME_SIZE | ||||
| 	} | ||||
| 	if maxMessageSize := tc.GetMaxMessageSize(); maxMessageSize < maxFrameSize { | ||||
| 		return maxMessageSize | ||||
| 	} | ||||
| 	return maxFrameSize | ||||
| } | ||||
| 
 | ||||
| // GetConnectTimeout returns the connect timeout should be used by TSocket and | ||||
| // TSSLSocket. | ||||
| // | ||||
| // It's nil-safe. If tc is nil, DEFAULT_CONNECT_TIMEOUT will be returned instead. | ||||
| func (tc *TConfiguration) GetConnectTimeout() time.Duration { | ||||
| 	if tc == nil || tc.ConnectTimeout < 0 { | ||||
| 		return DEFAULT_CONNECT_TIMEOUT | ||||
| 	} | ||||
| 	return tc.ConnectTimeout | ||||
| } | ||||
| 
 | ||||
| // GetSocketTimeout returns the socket timeout should be used by TSocket and | ||||
| // TSSLSocket. | ||||
| // | ||||
| // It's nil-safe. If tc is nil, DEFAULT_SOCKET_TIMEOUT will be returned instead. | ||||
| func (tc *TConfiguration) GetSocketTimeout() time.Duration { | ||||
| 	if tc == nil || tc.SocketTimeout < 0 { | ||||
| 		return DEFAULT_SOCKET_TIMEOUT | ||||
| 	} | ||||
| 	return tc.SocketTimeout | ||||
| } | ||||
| 
 | ||||
| // GetTLSConfig returns the tls config should be used by TSSLSocket. | ||||
| // | ||||
| // It's nil-safe. If tc is nil, nil will be returned instead. | ||||
| func (tc *TConfiguration) GetTLSConfig() *tls.Config { | ||||
| 	if tc == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return tc.TLSConfig | ||||
| } | ||||
| 
 | ||||
| // GetTBinaryStrictRead returns the strict read configuration TBinaryProtocol | ||||
| // should follow. | ||||
| // | ||||
| // It's nil-safe. DEFAULT_TBINARY_STRICT_READ will be returned if either tc or | ||||
| // tc.TBinaryStrictRead is nil. | ||||
| func (tc *TConfiguration) GetTBinaryStrictRead() bool { | ||||
| 	if tc == nil || tc.TBinaryStrictRead == nil { | ||||
| 		return DEFAULT_TBINARY_STRICT_READ | ||||
| 	} | ||||
| 	return *tc.TBinaryStrictRead | ||||
| } | ||||
| 
 | ||||
| // GetTBinaryStrictWrite returns the strict read configuration TBinaryProtocol | ||||
| // should follow. | ||||
| // | ||||
| // It's nil-safe. DEFAULT_TBINARY_STRICT_WRITE will be returned if either tc or | ||||
| // tc.TBinaryStrictWrite is nil. | ||||
| func (tc *TConfiguration) GetTBinaryStrictWrite() bool { | ||||
| 	if tc == nil || tc.TBinaryStrictWrite == nil { | ||||
| 		return DEFAULT_TBINARY_STRICT_WRITE | ||||
| 	} | ||||
| 	return *tc.TBinaryStrictWrite | ||||
| } | ||||
| 
 | ||||
| // GetTHeaderProtocolID returns the THeaderProtocolID should be used by | ||||
| // THeaderProtocol clients (for servers, they always use the same one as the | ||||
| // client instead). | ||||
| // | ||||
| // It's nil-safe. If either tc or tc.THeaderProtocolID is nil, | ||||
| // THeaderProtocolDefault will be returned instead. | ||||
| // THeaderProtocolDefault will also be returned if configured value is invalid. | ||||
| func (tc *TConfiguration) GetTHeaderProtocolID() THeaderProtocolID { | ||||
| 	if tc == nil || tc.THeaderProtocolID == nil { | ||||
| 		return THeaderProtocolDefault | ||||
| 	} | ||||
| 	protoID := *tc.THeaderProtocolID | ||||
| 	if err := protoID.Validate(); err != nil { | ||||
| 		return THeaderProtocolDefault | ||||
| 	} | ||||
| 	return protoID | ||||
| } | ||||
| 
 | ||||
| // THeaderProtocolIDPtr validates and returns the pointer to id. | ||||
| // | ||||
| // If id is not a valid THeaderProtocolID, a pointer to THeaderProtocolDefault | ||||
| // and the validation error will be returned. | ||||
| func THeaderProtocolIDPtr(id THeaderProtocolID) (*THeaderProtocolID, error) { | ||||
| 	err := id.Validate() | ||||
| 	if err != nil { | ||||
| 		id = THeaderProtocolDefault | ||||
| 	} | ||||
| 	return &id, err | ||||
| } | ||||
| 
 | ||||
| // THeaderProtocolIDPtrMust validates and returns the pointer to id. | ||||
| // | ||||
| // It's similar to THeaderProtocolIDPtr, but it panics on validation errors | ||||
| // instead of returning them. | ||||
| func THeaderProtocolIDPtrMust(id THeaderProtocolID) *THeaderProtocolID { | ||||
| 	ptr, err := THeaderProtocolIDPtr(id) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return ptr | ||||
| } | ||||
| 
 | ||||
| // TConfigurationSetter is an optional interface TProtocol, TTransport, | ||||
| // TProtocolFactory, TTransportFactory, and other implementations can implement. | ||||
| // | ||||
| // It's intended to be called during intializations. | ||||
| // The behavior of calling SetTConfiguration on a TTransport/TProtocol in the | ||||
| // middle of a message is undefined: | ||||
| // It may or may not change the behavior of the current processing message, | ||||
| // and it may even cause the current message to fail. | ||||
| // | ||||
| // Note for implementations: SetTConfiguration might be called multiple times | ||||
| // with the same value in quick successions due to the implementation of the | ||||
| // propagation. Implementations should make SetTConfiguration as simple as | ||||
| // possible (usually just overwrite the stored configuration and propagate it to | ||||
| // the wrapped TTransports/TProtocols). | ||||
| type TConfigurationSetter interface { | ||||
| 	SetTConfiguration(*TConfiguration) | ||||
| } | ||||
| 
 | ||||
| // PropagateTConfiguration propagates cfg to impl if impl implements | ||||
| // TConfigurationSetter and cfg is non-nil, otherwise it does nothing. | ||||
| // | ||||
| // NOTE: nil cfg is not propagated. If you want to propagate a TConfiguration | ||||
| // with everything being default value, use &TConfiguration{} explicitly instead. | ||||
| func PropagateTConfiguration(impl interface{}, cfg *TConfiguration) { | ||||
| 	if cfg == nil || cfg.noPropagation { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if setter, ok := impl.(TConfigurationSetter); ok { | ||||
| 		setter.SetTConfiguration(cfg) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func checkSizeForProtocol(size int32, cfg *TConfiguration) error { | ||||
| 	if size < 0 { | ||||
| 		return NewTProtocolExceptionWithType( | ||||
| 			NEGATIVE_SIZE, | ||||
| 			fmt.Errorf("negative size: %d", size), | ||||
| 		) | ||||
| 	} | ||||
| 	if size > cfg.GetMaxMessageSize() { | ||||
| 		return NewTProtocolExceptionWithType( | ||||
| 			SIZE_LIMIT, | ||||
| 			fmt.Errorf("size exceeded max allowed: %d", size), | ||||
| 		) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| type tTransportFactoryConf struct { | ||||
| 	delegate TTransportFactory | ||||
| 	cfg      *TConfiguration | ||||
| } | ||||
| 
 | ||||
| func (f *tTransportFactoryConf) GetTransport(orig TTransport) (TTransport, error) { | ||||
| 	trans, err := f.delegate.GetTransport(orig) | ||||
| 	if err == nil { | ||||
| 		PropagateTConfiguration(orig, f.cfg) | ||||
| 		PropagateTConfiguration(trans, f.cfg) | ||||
| 	} | ||||
| 	return trans, err | ||||
| } | ||||
| 
 | ||||
| func (f *tTransportFactoryConf) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(f.delegate, f.cfg) | ||||
| 	f.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| // TTransportFactoryConf wraps a TTransportFactory to propagate | ||||
| // TConfiguration on the factory's GetTransport calls. | ||||
| func TTransportFactoryConf(delegate TTransportFactory, conf *TConfiguration) TTransportFactory { | ||||
| 	return &tTransportFactoryConf{ | ||||
| 		delegate: delegate, | ||||
| 		cfg:      conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type tProtocolFactoryConf struct { | ||||
| 	delegate TProtocolFactory | ||||
| 	cfg      *TConfiguration | ||||
| } | ||||
| 
 | ||||
| func (f *tProtocolFactoryConf) GetProtocol(trans TTransport) TProtocol { | ||||
| 	proto := f.delegate.GetProtocol(trans) | ||||
| 	PropagateTConfiguration(trans, f.cfg) | ||||
| 	PropagateTConfiguration(proto, f.cfg) | ||||
| 	return proto | ||||
| } | ||||
| 
 | ||||
| func (f *tProtocolFactoryConf) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(f.delegate, f.cfg) | ||||
| 	f.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| // TProtocolFactoryConf wraps a TProtocolFactory to propagate | ||||
| // TConfiguration on the factory's GetProtocol calls. | ||||
| func TProtocolFactoryConf(delegate TProtocolFactory, conf *TConfiguration) TProtocolFactory { | ||||
| 	return &tProtocolFactoryConf{ | ||||
| 		delegate: delegate, | ||||
| 		cfg:      conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*tTransportFactoryConf)(nil) | ||||
| 	_ TConfigurationSetter = (*tProtocolFactoryConf)(nil) | ||||
| ) | ||||
|  | @ -1,24 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| var defaultCtx = context.Background() | ||||
|  | @ -1,447 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| type TDebugProtocol struct { | ||||
| 	// Required. The actual TProtocol to do the read/write. | ||||
| 	Delegate TProtocol | ||||
| 
 | ||||
| 	// Optional. The logger and prefix to log all the args/return values | ||||
| 	// from Delegate TProtocol calls. | ||||
| 	// | ||||
| 	// If Logger is nil, StdLogger using stdlib log package with os.Stderr | ||||
| 	// will be used. If disable logging is desired, set Logger to NopLogger | ||||
| 	// explicitly instead of leaving it as nil/unset. | ||||
| 	Logger    Logger | ||||
| 	LogPrefix string | ||||
| 
 | ||||
| 	// Optional. An TProtocol to duplicate everything read/written from Delegate. | ||||
| 	// | ||||
| 	// A typical use case of this is to use TSimpleJSONProtocol wrapping | ||||
| 	// TMemoryBuffer in a middleware to json logging requests/responses. | ||||
| 	// | ||||
| 	// This feature is not available from TDebugProtocolFactory. In order to | ||||
| 	// use it you have to construct TDebugProtocol directly, or set DuplicateTo | ||||
| 	// field after getting a TDebugProtocol from the factory. | ||||
| 	DuplicateTo TProtocol | ||||
| } | ||||
| 
 | ||||
| type TDebugProtocolFactory struct { | ||||
| 	Underlying TProtocolFactory | ||||
| 	LogPrefix  string | ||||
| 	Logger     Logger | ||||
| } | ||||
| 
 | ||||
| // NewTDebugProtocolFactory creates a TDebugProtocolFactory. | ||||
| // | ||||
| // Deprecated: Please use NewTDebugProtocolFactoryWithLogger or the struct | ||||
| // itself instead. This version will use the default logger from standard | ||||
| // library. | ||||
| func NewTDebugProtocolFactory(underlying TProtocolFactory, logPrefix string) *TDebugProtocolFactory { | ||||
| 	return &TDebugProtocolFactory{ | ||||
| 		Underlying: underlying, | ||||
| 		LogPrefix:  logPrefix, | ||||
| 		Logger:     StdLogger(nil), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewTDebugProtocolFactoryWithLogger creates a TDebugProtocolFactory. | ||||
| func NewTDebugProtocolFactoryWithLogger(underlying TProtocolFactory, logPrefix string, logger Logger) *TDebugProtocolFactory { | ||||
| 	return &TDebugProtocolFactory{ | ||||
| 		Underlying: underlying, | ||||
| 		LogPrefix:  logPrefix, | ||||
| 		Logger:     logger, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TDebugProtocolFactory) GetProtocol(trans TTransport) TProtocol { | ||||
| 	return &TDebugProtocol{ | ||||
| 		Delegate:  t.Underlying.GetProtocol(trans), | ||||
| 		LogPrefix: t.LogPrefix, | ||||
| 		Logger:    fallbackLogger(t.Logger), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (tdp *TDebugProtocol) logf(format string, v ...interface{}) { | ||||
| 	fallbackLogger(tdp.Logger)(fmt.Sprintf(format, v...)) | ||||
| } | ||||
| 
 | ||||
| func (tdp *TDebugProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { | ||||
| 	err := tdp.Delegate.WriteMessageBegin(ctx, name, typeId, seqid) | ||||
| 	tdp.logf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteMessageEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteMessageEnd(ctx) | ||||
| 	tdp.logf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMessageEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteStructBegin(ctx context.Context, name string) error { | ||||
| 	err := tdp.Delegate.WriteStructBegin(ctx, name) | ||||
| 	tdp.logf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteStructBegin(ctx, name) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteStructEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteStructEnd(ctx) | ||||
| 	tdp.logf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteStructEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { | ||||
| 	err := tdp.Delegate.WriteFieldBegin(ctx, name, typeId, id) | ||||
| 	tdp.logf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteFieldEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteFieldEnd(ctx) | ||||
| 	tdp.logf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteFieldEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteFieldStop(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteFieldStop(ctx) | ||||
| 	tdp.logf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteFieldStop(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { | ||||
| 	err := tdp.Delegate.WriteMapBegin(ctx, keyType, valueType, size) | ||||
| 	tdp.logf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteMapEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteMapEnd(ctx) | ||||
| 	tdp.logf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMapEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	err := tdp.Delegate.WriteListBegin(ctx, elemType, size) | ||||
| 	tdp.logf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteListBegin(ctx, elemType, size) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteListEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteListEnd(ctx) | ||||
| 	tdp.logf("%sWriteListEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteListEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	err := tdp.Delegate.WriteSetBegin(ctx, elemType, size) | ||||
| 	tdp.logf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteSetEnd(ctx context.Context) error { | ||||
| 	err := tdp.Delegate.WriteSetEnd(ctx) | ||||
| 	tdp.logf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteSetEnd(ctx) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteBool(ctx context.Context, value bool) error { | ||||
| 	err := tdp.Delegate.WriteBool(ctx, value) | ||||
| 	tdp.logf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteBool(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteByte(ctx context.Context, value int8) error { | ||||
| 	err := tdp.Delegate.WriteByte(ctx, value) | ||||
| 	tdp.logf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteByte(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteI16(ctx context.Context, value int16) error { | ||||
| 	err := tdp.Delegate.WriteI16(ctx, value) | ||||
| 	tdp.logf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI16(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteI32(ctx context.Context, value int32) error { | ||||
| 	err := tdp.Delegate.WriteI32(ctx, value) | ||||
| 	tdp.logf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI32(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteI64(ctx context.Context, value int64) error { | ||||
| 	err := tdp.Delegate.WriteI64(ctx, value) | ||||
| 	tdp.logf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI64(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteDouble(ctx context.Context, value float64) error { | ||||
| 	err := tdp.Delegate.WriteDouble(ctx, value) | ||||
| 	tdp.logf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteDouble(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteString(ctx context.Context, value string) error { | ||||
| 	err := tdp.Delegate.WriteString(ctx, value) | ||||
| 	tdp.logf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteString(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| func (tdp *TDebugProtocol) WriteBinary(ctx context.Context, value []byte) error { | ||||
| 	err := tdp.Delegate.WriteBinary(ctx, value) | ||||
| 	tdp.logf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteBinary(ctx, value) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (tdp *TDebugProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) { | ||||
| 	name, typeId, seqid, err = tdp.Delegate.ReadMessageBegin(ctx) | ||||
| 	tdp.logf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadMessageEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadMessageEnd(ctx) | ||||
| 	tdp.logf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMessageEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { | ||||
| 	name, err = tdp.Delegate.ReadStructBegin(ctx) | ||||
| 	tdp.logf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteStructBegin(ctx, name) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadStructEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadStructEnd(ctx) | ||||
| 	tdp.logf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteStructEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) { | ||||
| 	name, typeId, id, err = tdp.Delegate.ReadFieldBegin(ctx) | ||||
| 	tdp.logf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadFieldEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadFieldEnd(ctx) | ||||
| 	tdp.logf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteFieldEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { | ||||
| 	keyType, valueType, size, err = tdp.Delegate.ReadMapBegin(ctx) | ||||
| 	tdp.logf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadMapEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadMapEnd(ctx) | ||||
| 	tdp.logf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteMapEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	elemType, size, err = tdp.Delegate.ReadListBegin(ctx) | ||||
| 	tdp.logf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteListBegin(ctx, elemType, size) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadListEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadListEnd(ctx) | ||||
| 	tdp.logf("%sReadListEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteListEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	elemType, size, err = tdp.Delegate.ReadSetBegin(ctx) | ||||
| 	tdp.logf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadSetEnd(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.ReadSetEnd(ctx) | ||||
| 	tdp.logf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteSetEnd(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadBool(ctx context.Context) (value bool, err error) { | ||||
| 	value, err = tdp.Delegate.ReadBool(ctx) | ||||
| 	tdp.logf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteBool(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadByte(ctx context.Context) (value int8, err error) { | ||||
| 	value, err = tdp.Delegate.ReadByte(ctx) | ||||
| 	tdp.logf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteByte(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadI16(ctx context.Context) (value int16, err error) { | ||||
| 	value, err = tdp.Delegate.ReadI16(ctx) | ||||
| 	tdp.logf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI16(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadI32(ctx context.Context) (value int32, err error) { | ||||
| 	value, err = tdp.Delegate.ReadI32(ctx) | ||||
| 	tdp.logf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI32(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadI64(ctx context.Context) (value int64, err error) { | ||||
| 	value, err = tdp.Delegate.ReadI64(ctx) | ||||
| 	tdp.logf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteI64(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadDouble(ctx context.Context) (value float64, err error) { | ||||
| 	value, err = tdp.Delegate.ReadDouble(ctx) | ||||
| 	tdp.logf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteDouble(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadString(ctx context.Context) (value string, err error) { | ||||
| 	value, err = tdp.Delegate.ReadString(ctx) | ||||
| 	tdp.logf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteString(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { | ||||
| 	value, err = tdp.Delegate.ReadBinary(ctx) | ||||
| 	tdp.logf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.WriteBinary(ctx, value) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) Skip(ctx context.Context, fieldType TType) (err error) { | ||||
| 	err = tdp.Delegate.Skip(ctx, fieldType) | ||||
| 	tdp.logf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.Skip(ctx, fieldType) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) { | ||||
| 	err = tdp.Delegate.Flush(ctx) | ||||
| 	tdp.logf("%sFlush() (err=%#v)", tdp.LogPrefix, err) | ||||
| 	if tdp.DuplicateTo != nil { | ||||
| 		tdp.DuplicateTo.Flush(ctx) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (tdp *TDebugProtocol) Transport() TTransport { | ||||
| 	return tdp.Delegate.Transport() | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter for propagation. | ||||
| func (tdp *TDebugProtocol) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(tdp.Delegate, conf) | ||||
| 	PropagateTConfiguration(tdp.DuplicateTo, conf) | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TDebugProtocol)(nil) | ||||
|  | @ -1,121 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| type TDeserializer struct { | ||||
| 	Transport *TMemoryBuffer | ||||
| 	Protocol  TProtocol | ||||
| } | ||||
| 
 | ||||
| func NewTDeserializer() *TDeserializer { | ||||
| 	transport := NewTMemoryBufferLen(1024) | ||||
| 	protocol := NewTBinaryProtocolTransport(transport) | ||||
| 
 | ||||
| 	return &TDeserializer{ | ||||
| 		Transport: transport, | ||||
| 		Protocol:  protocol, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TDeserializer) ReadString(ctx context.Context, msg TStruct, s string) (err error) { | ||||
| 	t.Transport.Reset() | ||||
| 
 | ||||
| 	err = nil | ||||
| 	if _, err = t.Transport.Write([]byte(s)); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err = msg.Read(ctx, t.Protocol); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (t *TDeserializer) Read(ctx context.Context, msg TStruct, b []byte) (err error) { | ||||
| 	t.Transport.Reset() | ||||
| 
 | ||||
| 	err = nil | ||||
| 	if _, err = t.Transport.Write(b); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err = msg.Read(ctx, t.Protocol); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // TDeserializerPool is the thread-safe version of TDeserializer, | ||||
| // it uses resource pool of TDeserializer under the hood. | ||||
| // | ||||
| // It must be initialized with either NewTDeserializerPool or | ||||
| // NewTDeserializerPoolSizeFactory. | ||||
| type TDeserializerPool struct { | ||||
| 	pool sync.Pool | ||||
| } | ||||
| 
 | ||||
| // NewTDeserializerPool creates a new TDeserializerPool. | ||||
| // | ||||
| // NewTDeserializer can be used as the arg here. | ||||
| func NewTDeserializerPool(f func() *TDeserializer) *TDeserializerPool { | ||||
| 	return &TDeserializerPool{ | ||||
| 		pool: sync.Pool{ | ||||
| 			New: func() interface{} { | ||||
| 				return f() | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewTDeserializerPoolSizeFactory creates a new TDeserializerPool with | ||||
| // the given size and protocol factory. | ||||
| // | ||||
| // Note that the size is not the limit. The TMemoryBuffer underneath can grow | ||||
| // larger than that. It just dictates the initial size. | ||||
| func NewTDeserializerPoolSizeFactory(size int, factory TProtocolFactory) *TDeserializerPool { | ||||
| 	return &TDeserializerPool{ | ||||
| 		pool: sync.Pool{ | ||||
| 			New: func() interface{} { | ||||
| 				transport := NewTMemoryBufferLen(size) | ||||
| 				protocol := factory.GetProtocol(transport) | ||||
| 
 | ||||
| 				return &TDeserializer{ | ||||
| 					Transport: transport, | ||||
| 					Protocol:  protocol, | ||||
| 				} | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TDeserializerPool) ReadString(ctx context.Context, msg TStruct, s string) error { | ||||
| 	d := t.pool.Get().(*TDeserializer) | ||||
| 	defer t.pool.Put(d) | ||||
| 	return d.ReadString(ctx, msg, s) | ||||
| } | ||||
| 
 | ||||
| func (t *TDeserializerPool) Read(ctx context.Context, msg TStruct, b []byte) error { | ||||
| 	d := t.pool.Get().(*TDeserializer) | ||||
| 	defer t.pool.Put(d) | ||||
| 	return d.Read(ctx, msg, b) | ||||
| } | ||||
|  | @ -1,116 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // Generic Thrift exception | ||||
| type TException interface { | ||||
| 	error | ||||
| 
 | ||||
| 	TExceptionType() TExceptionType | ||||
| } | ||||
| 
 | ||||
| // Prepends additional information to an error without losing the Thrift exception interface | ||||
| func PrependError(prepend string, err error) error { | ||||
| 	msg := prepend + err.Error() | ||||
| 
 | ||||
| 	var te TException | ||||
| 	if errors.As(err, &te) { | ||||
| 		switch te.TExceptionType() { | ||||
| 		case TExceptionTypeTransport: | ||||
| 			if t, ok := err.(TTransportException); ok { | ||||
| 				return prependTTransportException(prepend, t) | ||||
| 			} | ||||
| 		case TExceptionTypeProtocol: | ||||
| 			if t, ok := err.(TProtocolException); ok { | ||||
| 				return prependTProtocolException(prepend, t) | ||||
| 			} | ||||
| 		case TExceptionTypeApplication: | ||||
| 			var t TApplicationException | ||||
| 			if errors.As(err, &t) { | ||||
| 				return NewTApplicationException(t.TypeId(), msg) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return wrappedTException{ | ||||
| 			err:            err, | ||||
| 			msg:            msg, | ||||
| 			tExceptionType: te.TExceptionType(), | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return errors.New(msg) | ||||
| } | ||||
| 
 | ||||
| // TExceptionType is an enum type to categorize different "subclasses" of TExceptions. | ||||
| type TExceptionType byte | ||||
| 
 | ||||
| // TExceptionType values | ||||
| const ( | ||||
| 	TExceptionTypeUnknown     TExceptionType = iota | ||||
| 	TExceptionTypeCompiled                   // TExceptions defined in thrift files and generated by thrift compiler | ||||
| 	TExceptionTypeApplication                // TApplicationExceptions | ||||
| 	TExceptionTypeProtocol                   // TProtocolExceptions | ||||
| 	TExceptionTypeTransport                  // TTransportExceptions | ||||
| ) | ||||
| 
 | ||||
| // WrapTException wraps an error into TException. | ||||
| // | ||||
| // If err is nil or already TException, it's returned as-is. | ||||
| // Otherwise it will be wrapped into TException with TExceptionType() returning | ||||
| // TExceptionTypeUnknown, and Unwrap() returning the original error. | ||||
| func WrapTException(err error) TException { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if te, ok := err.(TException); ok { | ||||
| 		return te | ||||
| 	} | ||||
| 
 | ||||
| 	return wrappedTException{ | ||||
| 		err:            err, | ||||
| 		msg:            err.Error(), | ||||
| 		tExceptionType: TExceptionTypeUnknown, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type wrappedTException struct { | ||||
| 	err            error | ||||
| 	msg            string | ||||
| 	tExceptionType TExceptionType | ||||
| } | ||||
| 
 | ||||
| func (w wrappedTException) Error() string { | ||||
| 	return w.msg | ||||
| } | ||||
| 
 | ||||
| func (w wrappedTException) TExceptionType() TExceptionType { | ||||
| 	return w.tExceptionType | ||||
| } | ||||
| 
 | ||||
| func (w wrappedTException) Unwrap() error { | ||||
| 	return w.err | ||||
| } | ||||
| 
 | ||||
| var _ TException = wrappedTException{} | ||||
|  | @ -1,223 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // Deprecated: Use DEFAULT_MAX_FRAME_SIZE instead. | ||||
| const DEFAULT_MAX_LENGTH = 16384000 | ||||
| 
 | ||||
| type TFramedTransport struct { | ||||
| 	transport TTransport | ||||
| 
 | ||||
| 	cfg *TConfiguration | ||||
| 
 | ||||
| 	writeBuf bytes.Buffer | ||||
| 
 | ||||
| 	reader  *bufio.Reader | ||||
| 	readBuf bytes.Buffer | ||||
| 
 | ||||
| 	buffer [4]byte | ||||
| } | ||||
| 
 | ||||
| type tFramedTransportFactory struct { | ||||
| 	factory TTransportFactory | ||||
| 	cfg     *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTFramedTransportFactoryConf instead. | ||||
| func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory { | ||||
| 	return NewTFramedTransportFactoryConf(factory, &TConfiguration{ | ||||
| 		MaxFrameSize: DEFAULT_MAX_LENGTH, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTFramedTransportFactoryConf instead. | ||||
| func NewTFramedTransportFactoryMaxLength(factory TTransportFactory, maxLength uint32) TTransportFactory { | ||||
| 	return NewTFramedTransportFactoryConf(factory, &TConfiguration{ | ||||
| 		MaxFrameSize: int32(maxLength), | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTFramedTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory { | ||||
| 	PropagateTConfiguration(factory, conf) | ||||
| 	return &tFramedTransportFactory{ | ||||
| 		factory: factory, | ||||
| 		cfg:     conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *tFramedTransportFactory) GetTransport(base TTransport) (TTransport, error) { | ||||
| 	PropagateTConfiguration(base, p.cfg) | ||||
| 	tt, err := p.factory.GetTransport(base) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewTFramedTransportConf(tt, p.cfg), nil | ||||
| } | ||||
| 
 | ||||
| func (p *tFramedTransportFactory) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.factory, cfg) | ||||
| 	p.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTFramedTransportConf instead. | ||||
| func NewTFramedTransport(transport TTransport) *TFramedTransport { | ||||
| 	return NewTFramedTransportConf(transport, &TConfiguration{ | ||||
| 		MaxFrameSize: DEFAULT_MAX_LENGTH, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTFramedTransportConf instead. | ||||
| func NewTFramedTransportMaxLength(transport TTransport, maxLength uint32) *TFramedTransport { | ||||
| 	return NewTFramedTransportConf(transport, &TConfiguration{ | ||||
| 		MaxFrameSize: int32(maxLength), | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func NewTFramedTransportConf(transport TTransport, conf *TConfiguration) *TFramedTransport { | ||||
| 	PropagateTConfiguration(transport, conf) | ||||
| 	return &TFramedTransport{ | ||||
| 		transport: transport, | ||||
| 		reader:    bufio.NewReader(transport), | ||||
| 		cfg:       conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) Open() error { | ||||
| 	return p.transport.Open() | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) IsOpen() bool { | ||||
| 	return p.transport.IsOpen() | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) Close() error { | ||||
| 	return p.transport.Close() | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) Read(buf []byte) (read int, err error) { | ||||
| 	read, err = p.readBuf.Read(buf) | ||||
| 	if err != io.EOF { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// For bytes.Buffer.Read, EOF would only happen when read is zero, | ||||
| 	// but still, do a sanity check, | ||||
| 	// in case that behavior is changed in a future version of go stdlib. | ||||
| 	// When that happens, just return nil error, | ||||
| 	// and let the caller call Read again to read the next frame. | ||||
| 	if read > 0 { | ||||
| 		return read, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// Reaching here means that the last Read finished the last frame, | ||||
| 	// so we need to read the next frame into readBuf now. | ||||
| 	if err = p.readFrame(); err != nil { | ||||
| 		return read, err | ||||
| 	} | ||||
| 	newRead, err := p.Read(buf[read:]) | ||||
| 	return read + newRead, err | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) ReadByte() (c byte, err error) { | ||||
| 	buf := p.buffer[:1] | ||||
| 	_, err = p.Read(buf) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	c = buf[0] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) Write(buf []byte) (int, error) { | ||||
| 	n, err := p.writeBuf.Write(buf) | ||||
| 	return n, NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) WriteByte(c byte) error { | ||||
| 	return p.writeBuf.WriteByte(c) | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) WriteString(s string) (n int, err error) { | ||||
| 	return p.writeBuf.WriteString(s) | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) Flush(ctx context.Context) error { | ||||
| 	size := p.writeBuf.Len() | ||||
| 	buf := p.buffer[:4] | ||||
| 	binary.BigEndian.PutUint32(buf, uint32(size)) | ||||
| 	_, err := p.transport.Write(buf) | ||||
| 	if err != nil { | ||||
| 		p.writeBuf.Reset() | ||||
| 		return NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	if size > 0 { | ||||
| 		if _, err := io.Copy(p.transport, &p.writeBuf); err != nil { | ||||
| 			p.writeBuf.Reset() | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 	} | ||||
| 	err = p.transport.Flush(ctx) | ||||
| 	return NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) readFrame() error { | ||||
| 	buf := p.buffer[:4] | ||||
| 	if _, err := io.ReadFull(p.reader, buf); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	size := binary.BigEndian.Uint32(buf) | ||||
| 	if size < 0 || size > uint32(p.cfg.GetMaxFrameSize()) { | ||||
| 		return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, fmt.Sprintf("Incorrect frame size (%d)", size)) | ||||
| 	} | ||||
| 	_, err := io.CopyN(&p.readBuf, p.reader, int64(size)) | ||||
| 	return NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TFramedTransport) RemainingBytes() (num_bytes uint64) { | ||||
| 	return uint64(p.readBuf.Len()) | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| func (p *TFramedTransport) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.transport, cfg) | ||||
| 	p.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*tFramedTransportFactory)(nil) | ||||
| 	_ TConfigurationSetter = (*TFramedTransport)(nil) | ||||
| ) | ||||
|  | @ -1,110 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| // See https://godoc.org/context#WithValue on why do we need the unexported typedefs. | ||||
| type ( | ||||
| 	headerKey     string | ||||
| 	headerKeyList int | ||||
| ) | ||||
| 
 | ||||
| // Values for headerKeyList. | ||||
| const ( | ||||
| 	headerKeyListRead headerKeyList = iota | ||||
| 	headerKeyListWrite | ||||
| ) | ||||
| 
 | ||||
| // SetHeader sets a header in the context. | ||||
| func SetHeader(ctx context.Context, key, value string) context.Context { | ||||
| 	return context.WithValue( | ||||
| 		ctx, | ||||
| 		headerKey(key), | ||||
| 		value, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // UnsetHeader unsets a previously set header in the context. | ||||
| func UnsetHeader(ctx context.Context, key string) context.Context { | ||||
| 	return context.WithValue( | ||||
| 		ctx, | ||||
| 		headerKey(key), | ||||
| 		nil, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // GetHeader returns a value of the given header from the context. | ||||
| func GetHeader(ctx context.Context, key string) (value string, ok bool) { | ||||
| 	if v := ctx.Value(headerKey(key)); v != nil { | ||||
| 		value, ok = v.(string) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // SetReadHeaderList sets the key list of read THeaders in the context. | ||||
| func SetReadHeaderList(ctx context.Context, keys []string) context.Context { | ||||
| 	return context.WithValue( | ||||
| 		ctx, | ||||
| 		headerKeyListRead, | ||||
| 		keys, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // GetReadHeaderList returns the key list of read THeaders from the context. | ||||
| func GetReadHeaderList(ctx context.Context) []string { | ||||
| 	if v := ctx.Value(headerKeyListRead); v != nil { | ||||
| 		if value, ok := v.([]string); ok { | ||||
| 			return value | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SetWriteHeaderList sets the key list of THeaders to write in the context. | ||||
| func SetWriteHeaderList(ctx context.Context, keys []string) context.Context { | ||||
| 	return context.WithValue( | ||||
| 		ctx, | ||||
| 		headerKeyListWrite, | ||||
| 		keys, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // GetWriteHeaderList returns the key list of THeaders to write from the context. | ||||
| func GetWriteHeaderList(ctx context.Context) []string { | ||||
| 	if v := ctx.Value(headerKeyListWrite); v != nil { | ||||
| 		if value, ok := v.([]string); ok { | ||||
| 			return value | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // AddReadTHeaderToContext adds the whole THeader headers into context. | ||||
| func AddReadTHeaderToContext(ctx context.Context, headers THeaderMap) context.Context { | ||||
| 	keys := make([]string, 0, len(headers)) | ||||
| 	for key, value := range headers { | ||||
| 		ctx = SetHeader(ctx, key, value) | ||||
| 		keys = append(keys, key) | ||||
| 	} | ||||
| 	return SetReadHeaderList(ctx, keys) | ||||
| } | ||||
|  | @ -1,351 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // THeaderProtocol is a thrift protocol that implements THeader: | ||||
| // https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md | ||||
| // | ||||
| // It supports either binary or compact protocol as the wrapped protocol. | ||||
| // | ||||
| // Most of the THeader handlings are happening inside THeaderTransport. | ||||
| type THeaderProtocol struct { | ||||
| 	transport *THeaderTransport | ||||
| 
 | ||||
| 	// Will be initialized on first read/write. | ||||
| 	protocol TProtocol | ||||
| 
 | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHeaderProtocolConf instead. | ||||
| func NewTHeaderProtocol(trans TTransport) *THeaderProtocol { | ||||
| 	return newTHeaderProtocolConf(trans, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTHeaderProtocolConf creates a new THeaderProtocol from the underlying | ||||
| // transport with given TConfiguration. | ||||
| // | ||||
| // The passed in transport will be wrapped with THeaderTransport. | ||||
| // | ||||
| // Note that THeaderTransport handles frame and zlib by itself, | ||||
| // so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), | ||||
| // instead of rich transports like TZlibTransport or TFramedTransport. | ||||
| func NewTHeaderProtocolConf(trans TTransport, conf *TConfiguration) *THeaderProtocol { | ||||
| 	return newTHeaderProtocolConf(trans, conf) | ||||
| } | ||||
| 
 | ||||
| func newTHeaderProtocolConf(trans TTransport, cfg *TConfiguration) *THeaderProtocol { | ||||
| 	t := NewTHeaderTransportConf(trans, cfg) | ||||
| 	p, _ := t.cfg.GetTHeaderProtocolID().GetProtocol(t) | ||||
| 	PropagateTConfiguration(p, cfg) | ||||
| 	return &THeaderProtocol{ | ||||
| 		transport: t, | ||||
| 		protocol:  p, | ||||
| 		cfg:       cfg, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type tHeaderProtocolFactory struct { | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| func (f tHeaderProtocolFactory) GetProtocol(trans TTransport) TProtocol { | ||||
| 	return newTHeaderProtocolConf(trans, f.cfg) | ||||
| } | ||||
| 
 | ||||
| func (f *tHeaderProtocolFactory) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	f.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHeaderProtocolFactoryConf instead. | ||||
| func NewTHeaderProtocolFactory() TProtocolFactory { | ||||
| 	return NewTHeaderProtocolFactoryConf(&TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTHeaderProtocolFactoryConf creates a factory for THeader with given | ||||
| // TConfiguration. | ||||
| func NewTHeaderProtocolFactoryConf(conf *TConfiguration) TProtocolFactory { | ||||
| 	return tHeaderProtocolFactory{ | ||||
| 		cfg: conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Transport returns the underlying transport. | ||||
| // | ||||
| // It's guaranteed to be of type *THeaderTransport. | ||||
| func (p *THeaderProtocol) Transport() TTransport { | ||||
| 	return p.transport | ||||
| } | ||||
| 
 | ||||
| // GetReadHeaders returns the THeaderMap read from transport. | ||||
| func (p *THeaderProtocol) GetReadHeaders() THeaderMap { | ||||
| 	return p.transport.GetReadHeaders() | ||||
| } | ||||
| 
 | ||||
| // SetWriteHeader sets a header for write. | ||||
| func (p *THeaderProtocol) SetWriteHeader(key, value string) { | ||||
| 	p.transport.SetWriteHeader(key, value) | ||||
| } | ||||
| 
 | ||||
| // ClearWriteHeaders clears all write headers previously set. | ||||
| func (p *THeaderProtocol) ClearWriteHeaders() { | ||||
| 	p.transport.ClearWriteHeaders() | ||||
| } | ||||
| 
 | ||||
| // AddTransform add a transform for writing. | ||||
| func (p *THeaderProtocol) AddTransform(transform THeaderTransformID) error { | ||||
| 	return p.transport.AddTransform(transform) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) Flush(ctx context.Context) error { | ||||
| 	return p.transport.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteMessageBegin(ctx context.Context, name string, typeID TMessageType, seqID int32) error { | ||||
| 	newProto, err := p.transport.Protocol().GetProtocol(p.transport) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	PropagateTConfiguration(newProto, p.cfg) | ||||
| 	p.protocol = newProto | ||||
| 	p.transport.SequenceID = seqID | ||||
| 	return p.protocol.WriteMessageBegin(ctx, name, typeID, seqID) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteMessageEnd(ctx context.Context) error { | ||||
| 	if err := p.protocol.WriteMessageEnd(ctx); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return p.transport.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteStructBegin(ctx context.Context, name string) error { | ||||
| 	return p.protocol.WriteStructBegin(ctx, name) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteStructEnd(ctx context.Context) error { | ||||
| 	return p.protocol.WriteStructEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteFieldBegin(ctx context.Context, name string, typeID TType, id int16) error { | ||||
| 	return p.protocol.WriteFieldBegin(ctx, name, typeID, id) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteFieldEnd(ctx context.Context) error { | ||||
| 	return p.protocol.WriteFieldEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteFieldStop(ctx context.Context) error { | ||||
| 	return p.protocol.WriteFieldStop(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { | ||||
| 	return p.protocol.WriteMapBegin(ctx, keyType, valueType, size) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteMapEnd(ctx context.Context) error { | ||||
| 	return p.protocol.WriteMapEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	return p.protocol.WriteListBegin(ctx, elemType, size) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteListEnd(ctx context.Context) error { | ||||
| 	return p.protocol.WriteListEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	return p.protocol.WriteSetBegin(ctx, elemType, size) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteSetEnd(ctx context.Context) error { | ||||
| 	return p.protocol.WriteSetEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteBool(ctx context.Context, value bool) error { | ||||
| 	return p.protocol.WriteBool(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteByte(ctx context.Context, value int8) error { | ||||
| 	return p.protocol.WriteByte(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteI16(ctx context.Context, value int16) error { | ||||
| 	return p.protocol.WriteI16(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteI32(ctx context.Context, value int32) error { | ||||
| 	return p.protocol.WriteI32(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteI64(ctx context.Context, value int64) error { | ||||
| 	return p.protocol.WriteI64(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteDouble(ctx context.Context, value float64) error { | ||||
| 	return p.protocol.WriteDouble(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteString(ctx context.Context, value string) error { | ||||
| 	return p.protocol.WriteString(ctx, value) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) WriteBinary(ctx context.Context, value []byte) error { | ||||
| 	return p.protocol.WriteBinary(ctx, value) | ||||
| } | ||||
| 
 | ||||
| // ReadFrame calls underlying THeaderTransport's ReadFrame function. | ||||
| func (p *THeaderProtocol) ReadFrame(ctx context.Context) error { | ||||
| 	return p.transport.ReadFrame(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadMessageBegin(ctx context.Context) (name string, typeID TMessageType, seqID int32, err error) { | ||||
| 	if err = p.transport.ReadFrame(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	var newProto TProtocol | ||||
| 	newProto, err = p.transport.Protocol().GetProtocol(p.transport) | ||||
| 	if err != nil { | ||||
| 		var tAppExc TApplicationException | ||||
| 		if !errors.As(err, &tAppExc) { | ||||
| 			return | ||||
| 		} | ||||
| 		if e := p.protocol.WriteMessageBegin(ctx, "", EXCEPTION, seqID); e != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if e := tAppExc.Write(ctx, p.protocol); e != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if e := p.protocol.WriteMessageEnd(ctx); e != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if e := p.transport.Flush(ctx); e != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	PropagateTConfiguration(newProto, p.cfg) | ||||
| 	p.protocol = newProto | ||||
| 
 | ||||
| 	return p.protocol.ReadMessageBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadMessageEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadMessageEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { | ||||
| 	return p.protocol.ReadStructBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadStructEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadStructEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadFieldBegin(ctx context.Context) (name string, typeID TType, id int16, err error) { | ||||
| 	return p.protocol.ReadFieldBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadFieldEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadFieldEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { | ||||
| 	return p.protocol.ReadMapBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadMapEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadMapEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	return p.protocol.ReadListBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadListEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadListEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { | ||||
| 	return p.protocol.ReadSetBegin(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadSetEnd(ctx context.Context) error { | ||||
| 	return p.protocol.ReadSetEnd(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadBool(ctx context.Context) (value bool, err error) { | ||||
| 	return p.protocol.ReadBool(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadByte(ctx context.Context) (value int8, err error) { | ||||
| 	return p.protocol.ReadByte(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadI16(ctx context.Context) (value int16, err error) { | ||||
| 	return p.protocol.ReadI16(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadI32(ctx context.Context) (value int32, err error) { | ||||
| 	return p.protocol.ReadI32(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadI64(ctx context.Context) (value int64, err error) { | ||||
| 	return p.protocol.ReadI64(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadDouble(ctx context.Context) (value float64, err error) { | ||||
| 	return p.protocol.ReadDouble(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadString(ctx context.Context) (value string, err error) { | ||||
| 	return p.protocol.ReadString(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { | ||||
| 	return p.protocol.ReadBinary(ctx) | ||||
| } | ||||
| 
 | ||||
| func (p *THeaderProtocol) Skip(ctx context.Context, fieldType TType) error { | ||||
| 	return p.protocol.Skip(ctx, fieldType) | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| func (p *THeaderProtocol) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.transport, cfg) | ||||
| 	PropagateTConfiguration(p.protocol, cfg) | ||||
| 	p.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*tHeaderProtocolFactory)(nil) | ||||
| 	_ TConfigurationSetter = (*THeaderProtocol)(nil) | ||||
| ) | ||||
|  | @ -1,809 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"compress/zlib" | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // Size in bytes for 32-bit ints. | ||||
| const size32 = 4 | ||||
| 
 | ||||
| type headerMeta struct { | ||||
| 	MagicFlags   uint32 | ||||
| 	SequenceID   int32 | ||||
| 	HeaderLength uint16 | ||||
| } | ||||
| 
 | ||||
| const headerMetaSize = 10 | ||||
| 
 | ||||
| type clientType int | ||||
| 
 | ||||
| const ( | ||||
| 	clientUnknown clientType = iota | ||||
| 	clientHeaders | ||||
| 	clientFramedBinary | ||||
| 	clientUnframedBinary | ||||
| 	clientFramedCompact | ||||
| 	clientUnframedCompact | ||||
| ) | ||||
| 
 | ||||
| // Constants defined in THeader format: | ||||
| // https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md | ||||
| const ( | ||||
| 	THeaderHeaderMagic  uint32 = 0x0fff0000 | ||||
| 	THeaderHeaderMask   uint32 = 0xffff0000 | ||||
| 	THeaderFlagsMask    uint32 = 0x0000ffff | ||||
| 	THeaderMaxFrameSize uint32 = 0x3fffffff | ||||
| ) | ||||
| 
 | ||||
| // THeaderMap is the type of the header map in THeader transport. | ||||
| type THeaderMap map[string]string | ||||
| 
 | ||||
| // THeaderProtocolID is the wrapped protocol id used in THeader. | ||||
| type THeaderProtocolID int32 | ||||
| 
 | ||||
| // Supported THeaderProtocolID values. | ||||
| const ( | ||||
| 	THeaderProtocolBinary  THeaderProtocolID = 0x00 | ||||
| 	THeaderProtocolCompact THeaderProtocolID = 0x02 | ||||
| 	THeaderProtocolDefault                   = THeaderProtocolBinary | ||||
| ) | ||||
| 
 | ||||
| // Declared globally to avoid repetitive allocations, not really used. | ||||
| var globalMemoryBuffer = NewTMemoryBuffer() | ||||
| 
 | ||||
| // Validate checks whether the THeaderProtocolID is a valid/supported one. | ||||
| func (id THeaderProtocolID) Validate() error { | ||||
| 	_, err := id.GetProtocol(globalMemoryBuffer) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // GetProtocol gets the corresponding TProtocol from the wrapped protocol id. | ||||
| func (id THeaderProtocolID) GetProtocol(trans TTransport) (TProtocol, error) { | ||||
| 	switch id { | ||||
| 	default: | ||||
| 		return nil, NewTApplicationException( | ||||
| 			INVALID_PROTOCOL, | ||||
| 			fmt.Sprintf("THeader protocol id %d not supported", id), | ||||
| 		) | ||||
| 	case THeaderProtocolBinary: | ||||
| 		return NewTBinaryProtocolTransport(trans), nil | ||||
| 	case THeaderProtocolCompact: | ||||
| 		return NewTCompactProtocol(trans), nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // THeaderTransformID defines the numeric id of the transform used. | ||||
| type THeaderTransformID int32 | ||||
| 
 | ||||
| // THeaderTransformID values. | ||||
| // | ||||
| // Values not defined here are not currently supported, namely HMAC and Snappy. | ||||
| const ( | ||||
| 	TransformNone THeaderTransformID = iota // 0, no special handling | ||||
| 	TransformZlib                           // 1, zlib | ||||
| ) | ||||
| 
 | ||||
| var supportedTransformIDs = map[THeaderTransformID]bool{ | ||||
| 	TransformNone: true, | ||||
| 	TransformZlib: true, | ||||
| } | ||||
| 
 | ||||
| // TransformReader is an io.ReadCloser that handles transforms reading. | ||||
| type TransformReader struct { | ||||
| 	io.Reader | ||||
| 
 | ||||
| 	closers []io.Closer | ||||
| } | ||||
| 
 | ||||
| var _ io.ReadCloser = (*TransformReader)(nil) | ||||
| 
 | ||||
| // NewTransformReaderWithCapacity initializes a TransformReader with expected | ||||
| // closers capacity. | ||||
| // | ||||
| // If you don't know the closers capacity beforehand, just use | ||||
| // | ||||
| //     &TransformReader{Reader: baseReader} | ||||
| // | ||||
| // instead would be sufficient. | ||||
| func NewTransformReaderWithCapacity(baseReader io.Reader, capacity int) *TransformReader { | ||||
| 	return &TransformReader{ | ||||
| 		Reader:  baseReader, | ||||
| 		closers: make([]io.Closer, 0, capacity), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Close calls the underlying closers in appropriate order, | ||||
| // stops at and returns the first error encountered. | ||||
| func (tr *TransformReader) Close() error { | ||||
| 	// Call closers in reversed order | ||||
| 	for i := len(tr.closers) - 1; i >= 0; i-- { | ||||
| 		if err := tr.closers[i].Close(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // AddTransform adds a transform. | ||||
| func (tr *TransformReader) AddTransform(id THeaderTransformID) error { | ||||
| 	switch id { | ||||
| 	default: | ||||
| 		return NewTApplicationException( | ||||
| 			INVALID_TRANSFORM, | ||||
| 			fmt.Sprintf("THeaderTransformID %d not supported", id), | ||||
| 		) | ||||
| 	case TransformNone: | ||||
| 		// no-op | ||||
| 	case TransformZlib: | ||||
| 		readCloser, err := zlib.NewReader(tr.Reader) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		tr.Reader = readCloser | ||||
| 		tr.closers = append(tr.closers, readCloser) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // TransformWriter is an io.WriteCloser that handles transforms writing. | ||||
| type TransformWriter struct { | ||||
| 	io.Writer | ||||
| 
 | ||||
| 	closers []io.Closer | ||||
| } | ||||
| 
 | ||||
| var _ io.WriteCloser = (*TransformWriter)(nil) | ||||
| 
 | ||||
| // NewTransformWriter creates a new TransformWriter with base writer and transforms. | ||||
| func NewTransformWriter(baseWriter io.Writer, transforms []THeaderTransformID) (io.WriteCloser, error) { | ||||
| 	writer := &TransformWriter{ | ||||
| 		Writer:  baseWriter, | ||||
| 		closers: make([]io.Closer, 0, len(transforms)), | ||||
| 	} | ||||
| 	for _, id := range transforms { | ||||
| 		if err := writer.AddTransform(id); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return writer, nil | ||||
| } | ||||
| 
 | ||||
| // Close calls the underlying closers in appropriate order, | ||||
| // stops at and returns the first error encountered. | ||||
| func (tw *TransformWriter) Close() error { | ||||
| 	// Call closers in reversed order | ||||
| 	for i := len(tw.closers) - 1; i >= 0; i-- { | ||||
| 		if err := tw.closers[i].Close(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // AddTransform adds a transform. | ||||
| func (tw *TransformWriter) AddTransform(id THeaderTransformID) error { | ||||
| 	switch id { | ||||
| 	default: | ||||
| 		return NewTApplicationException( | ||||
| 			INVALID_TRANSFORM, | ||||
| 			fmt.Sprintf("THeaderTransformID %d not supported", id), | ||||
| 		) | ||||
| 	case TransformNone: | ||||
| 		// no-op | ||||
| 	case TransformZlib: | ||||
| 		writeCloser := zlib.NewWriter(tw.Writer) | ||||
| 		tw.Writer = writeCloser | ||||
| 		tw.closers = append(tw.closers, writeCloser) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // THeaderInfoType is the type id of the info headers. | ||||
| type THeaderInfoType int32 | ||||
| 
 | ||||
| // Supported THeaderInfoType values. | ||||
| const ( | ||||
| 	_            THeaderInfoType = iota // Skip 0 | ||||
| 	InfoKeyValue                        // 1 | ||||
| 	// Rest of the info types are not supported. | ||||
| ) | ||||
| 
 | ||||
| // THeaderTransport is a Transport mode that implements THeader. | ||||
| // | ||||
| // Note that THeaderTransport handles frame and zlib by itself, | ||||
| // so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), | ||||
| // instead of rich transports like TZlibTransport or TFramedTransport. | ||||
| type THeaderTransport struct { | ||||
| 	SequenceID int32 | ||||
| 	Flags      uint32 | ||||
| 
 | ||||
| 	transport TTransport | ||||
| 
 | ||||
| 	// THeaderMap for read and write | ||||
| 	readHeaders  THeaderMap | ||||
| 	writeHeaders THeaderMap | ||||
| 
 | ||||
| 	// Reading related variables. | ||||
| 	reader *bufio.Reader | ||||
| 	// When frame is detected, we read the frame fully into frameBuffer. | ||||
| 	frameBuffer bytes.Buffer | ||||
| 	// When it's non-nil, Read should read from frameReader instead of | ||||
| 	// reader, and EOF error indicates end of frame instead of end of all | ||||
| 	// transport. | ||||
| 	frameReader io.ReadCloser | ||||
| 
 | ||||
| 	// Writing related variables | ||||
| 	writeBuffer     bytes.Buffer | ||||
| 	writeTransforms []THeaderTransformID | ||||
| 
 | ||||
| 	clientType clientType | ||||
| 	protocolID THeaderProtocolID | ||||
| 	cfg        *TConfiguration | ||||
| 
 | ||||
| 	// buffer is used in the following scenarios to avoid repetitive | ||||
| 	// allocations, while 4 is big enough for all those scenarios: | ||||
| 	// | ||||
| 	// * header padding (max size 4) | ||||
| 	// * write the frame size (size 4) | ||||
| 	buffer [4]byte | ||||
| } | ||||
| 
 | ||||
| var _ TTransport = (*THeaderTransport)(nil) | ||||
| 
 | ||||
| // Deprecated: Use NewTHeaderTransportConf instead. | ||||
| func NewTHeaderTransport(trans TTransport) *THeaderTransport { | ||||
| 	return NewTHeaderTransportConf(trans, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTHeaderTransportConf creates THeaderTransport from the | ||||
| // underlying transport, with given TConfiguration attached. | ||||
| // | ||||
| // If trans is already a *THeaderTransport, it will be returned as is, | ||||
| // but with TConfiguration overridden by the value passed in. | ||||
| // | ||||
| // The protocol ID in TConfiguration is only useful for client transports. | ||||
| // For servers, | ||||
| // the protocol ID will be overridden again to the one set by the client, | ||||
| // to ensure that servers always speak the same dialect as the client. | ||||
| func NewTHeaderTransportConf(trans TTransport, conf *TConfiguration) *THeaderTransport { | ||||
| 	if ht, ok := trans.(*THeaderTransport); ok { | ||||
| 		ht.SetTConfiguration(conf) | ||||
| 		return ht | ||||
| 	} | ||||
| 	PropagateTConfiguration(trans, conf) | ||||
| 	return &THeaderTransport{ | ||||
| 		transport:    trans, | ||||
| 		reader:       bufio.NewReader(trans), | ||||
| 		writeHeaders: make(THeaderMap), | ||||
| 		protocolID:   conf.GetTHeaderProtocolID(), | ||||
| 		cfg:          conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Open calls the underlying transport's Open function. | ||||
| func (t *THeaderTransport) Open() error { | ||||
| 	return t.transport.Open() | ||||
| } | ||||
| 
 | ||||
| // IsOpen calls the underlying transport's IsOpen function. | ||||
| func (t *THeaderTransport) IsOpen() bool { | ||||
| 	return t.transport.IsOpen() | ||||
| } | ||||
| 
 | ||||
| // ReadFrame tries to read the frame header, guess the client type, and handle | ||||
| // unframed clients. | ||||
| func (t *THeaderTransport) ReadFrame(ctx context.Context) error { | ||||
| 	if !t.needReadFrame() { | ||||
| 		// No need to read frame, skipping. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// Peek and handle the first 32 bits. | ||||
| 	// They could either be the length field of a framed message, | ||||
| 	// or the first bytes of an unframed message. | ||||
| 	var buf []byte | ||||
| 	var err error | ||||
| 	// This is also usually the first read from a connection, | ||||
| 	// so handle retries around socket timeouts. | ||||
| 	_, deadlineSet := ctx.Deadline() | ||||
| 	for { | ||||
| 		buf, err = t.reader.Peek(size32) | ||||
| 		if deadlineSet && isTimeoutError(err) && ctx.Err() == nil { | ||||
| 			// This is I/O timeout and we still have time, | ||||
| 			// continue trying | ||||
| 			continue | ||||
| 		} | ||||
| 		// For anything else, do not retry | ||||
| 		break | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	frameSize := binary.BigEndian.Uint32(buf) | ||||
| 	if frameSize&VERSION_MASK == VERSION_1 { | ||||
| 		t.clientType = clientUnframedBinary | ||||
| 		return nil | ||||
| 	} | ||||
| 	if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { | ||||
| 		t.clientType = clientUnframedCompact | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// At this point it should be a framed message, | ||||
| 	// sanity check on frameSize then discard the peeked part. | ||||
| 	if frameSize > THeaderMaxFrameSize || frameSize > uint32(t.cfg.GetMaxFrameSize()) { | ||||
| 		return NewTProtocolExceptionWithType( | ||||
| 			SIZE_LIMIT, | ||||
| 			errors.New("frame too large"), | ||||
| 		) | ||||
| 	} | ||||
| 	t.reader.Discard(size32) | ||||
| 
 | ||||
| 	// Read the frame fully into frameBuffer. | ||||
| 	_, err = io.CopyN(&t.frameBuffer, t.reader, int64(frameSize)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	t.frameReader = io.NopCloser(&t.frameBuffer) | ||||
| 
 | ||||
| 	// Peek and handle the next 32 bits. | ||||
| 	buf = t.frameBuffer.Bytes()[:size32] | ||||
| 	version := binary.BigEndian.Uint32(buf) | ||||
| 	if version&THeaderHeaderMask == THeaderHeaderMagic { | ||||
| 		t.clientType = clientHeaders | ||||
| 		return t.parseHeaders(ctx, frameSize) | ||||
| 	} | ||||
| 	if version&VERSION_MASK == VERSION_1 { | ||||
| 		t.clientType = clientFramedBinary | ||||
| 		return nil | ||||
| 	} | ||||
| 	if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { | ||||
| 		t.clientType = clientFramedCompact | ||||
| 		return nil | ||||
| 	} | ||||
| 	if err := t.endOfFrame(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return NewTProtocolExceptionWithType( | ||||
| 		NOT_IMPLEMENTED, | ||||
| 		errors.New("unsupported client transport type"), | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // endOfFrame does end of frame handling. | ||||
| // | ||||
| // It closes frameReader, and also resets frame related states. | ||||
| func (t *THeaderTransport) endOfFrame() error { | ||||
| 	defer func() { | ||||
| 		t.frameBuffer.Reset() | ||||
| 		t.frameReader = nil | ||||
| 	}() | ||||
| 	return t.frameReader.Close() | ||||
| } | ||||
| 
 | ||||
| func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) error { | ||||
| 	if t.clientType != clientHeaders { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	var err error | ||||
| 	var meta headerMeta | ||||
| 	if err = binary.Read(&t.frameBuffer, binary.BigEndian, &meta); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	frameSize -= headerMetaSize | ||||
| 	t.Flags = meta.MagicFlags & THeaderFlagsMask | ||||
| 	t.SequenceID = meta.SequenceID | ||||
| 	headerLength := int64(meta.HeaderLength) * 4 | ||||
| 	if int64(frameSize) < headerLength { | ||||
| 		return NewTProtocolExceptionWithType( | ||||
| 			SIZE_LIMIT, | ||||
| 			errors.New("header size is larger than the whole frame"), | ||||
| 		) | ||||
| 	} | ||||
| 	headerBuf := NewTMemoryBuffer() | ||||
| 	_, err = io.CopyN(headerBuf, &t.frameBuffer, headerLength) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	hp := NewTCompactProtocol(headerBuf) | ||||
| 	hp.SetTConfiguration(t.cfg) | ||||
| 
 | ||||
| 	// At this point the header is already read into headerBuf, | ||||
| 	// and t.frameBuffer starts from the actual payload. | ||||
| 	protoID, err := hp.readVarint32() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	t.protocolID = THeaderProtocolID(protoID) | ||||
| 
 | ||||
| 	var transformCount int32 | ||||
| 	transformCount, err = hp.readVarint32() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if transformCount > 0 { | ||||
| 		reader := NewTransformReaderWithCapacity( | ||||
| 			&t.frameBuffer, | ||||
| 			int(transformCount), | ||||
| 		) | ||||
| 		t.frameReader = reader | ||||
| 		transformIDs := make([]THeaderTransformID, transformCount) | ||||
| 		for i := 0; i < int(transformCount); i++ { | ||||
| 			id, err := hp.readVarint32() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			transformIDs[i] = THeaderTransformID(id) | ||||
| 		} | ||||
| 		// The transform IDs on the wire was added based on the order of | ||||
| 		// writing, so on the reading side we need to reverse the order. | ||||
| 		for i := transformCount - 1; i >= 0; i-- { | ||||
| 			id := transformIDs[i] | ||||
| 			if err := reader.AddTransform(id); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// The info part does not use the transforms yet, so it's | ||||
| 	// important to continue using headerBuf. | ||||
| 	headers := make(THeaderMap) | ||||
| 	for { | ||||
| 		infoType, err := hp.readVarint32() | ||||
| 		if errors.Is(err, io.EOF) { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if THeaderInfoType(infoType) == InfoKeyValue { | ||||
| 			count, err := hp.readVarint32() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			for i := 0; i < int(count); i++ { | ||||
| 				key, err := hp.ReadString(ctx) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				value, err := hp.ReadString(ctx) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				headers[key] = value | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Skip reading info section on the first | ||||
| 			// unsupported info type. | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	t.readHeaders = headers | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (t *THeaderTransport) needReadFrame() bool { | ||||
| 	if t.clientType == clientUnknown { | ||||
| 		// This is a new connection that's never read before. | ||||
| 		return true | ||||
| 	} | ||||
| 	if t.isFramed() && t.frameReader == nil { | ||||
| 		// We just finished the last frame. | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (t *THeaderTransport) Read(p []byte) (read int, err error) { | ||||
| 	// Here using context.Background instead of a context passed in is safe. | ||||
| 	// First is that there's no way to pass context into this function. | ||||
| 	// Then, 99% of the case when calling this Read frame is already read | ||||
| 	// into frameReader. ReadFrame here is more of preventing bugs that | ||||
| 	// didn't call ReadFrame before calling Read. | ||||
| 	err = t.ReadFrame(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if t.frameReader != nil { | ||||
| 		read, err = t.frameReader.Read(p) | ||||
| 		if err == nil && t.frameBuffer.Len() <= 0 { | ||||
| 			// the last Read finished the frame, do endOfFrame | ||||
| 			// handling here. | ||||
| 			err = t.endOfFrame() | ||||
| 		} else if err == io.EOF { | ||||
| 			err = t.endOfFrame() | ||||
| 			if err != nil { | ||||
| 				return | ||||
| 			} | ||||
| 			if read == 0 { | ||||
| 				// Try to read the next frame when we hit EOF | ||||
| 				// (end of frame) immediately. | ||||
| 				// When we got here, it means the last read | ||||
| 				// finished the previous frame, but didn't | ||||
| 				// do endOfFrame handling yet. | ||||
| 				// We have to read the next frame here, | ||||
| 				// as otherwise we would return 0 and nil, | ||||
| 				// which is a case not handled well by most | ||||
| 				// protocol implementations. | ||||
| 				return t.Read(p) | ||||
| 			} | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	return t.reader.Read(p) | ||||
| } | ||||
| 
 | ||||
| // Write writes data to the write buffer. | ||||
| // | ||||
| // You need to call Flush to actually write them to the transport. | ||||
| func (t *THeaderTransport) Write(p []byte) (int, error) { | ||||
| 	return t.writeBuffer.Write(p) | ||||
| } | ||||
| 
 | ||||
| // Flush writes the appropriate header and the write buffer to the underlying transport. | ||||
| func (t *THeaderTransport) Flush(ctx context.Context) error { | ||||
| 	if t.writeBuffer.Len() == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	defer t.writeBuffer.Reset() | ||||
| 
 | ||||
| 	switch t.clientType { | ||||
| 	default: | ||||
| 		fallthrough | ||||
| 	case clientUnknown: | ||||
| 		t.clientType = clientHeaders | ||||
| 		fallthrough | ||||
| 	case clientHeaders: | ||||
| 		headers := NewTMemoryBuffer() | ||||
| 		hp := NewTCompactProtocol(headers) | ||||
| 		hp.SetTConfiguration(t.cfg) | ||||
| 		if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		for _, transform := range t.writeTransforms { | ||||
| 			if _, err := hp.writeVarint32(int32(transform)); err != nil { | ||||
| 				return NewTTransportExceptionFromError(err) | ||||
| 			} | ||||
| 		} | ||||
| 		if len(t.writeHeaders) > 0 { | ||||
| 			if _, err := hp.writeVarint32(int32(InfoKeyValue)); err != nil { | ||||
| 				return NewTTransportExceptionFromError(err) | ||||
| 			} | ||||
| 			if _, err := hp.writeVarint32(int32(len(t.writeHeaders))); err != nil { | ||||
| 				return NewTTransportExceptionFromError(err) | ||||
| 			} | ||||
| 			for key, value := range t.writeHeaders { | ||||
| 				if err := hp.WriteString(ctx, key); err != nil { | ||||
| 					return NewTTransportExceptionFromError(err) | ||||
| 				} | ||||
| 				if err := hp.WriteString(ctx, value); err != nil { | ||||
| 					return NewTTransportExceptionFromError(err) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		padding := 4 - headers.Len()%4 | ||||
| 		if padding < 4 { | ||||
| 			buf := t.buffer[:padding] | ||||
| 			for i := range buf { | ||||
| 				buf[i] = 0 | ||||
| 			} | ||||
| 			if _, err := headers.Write(buf); err != nil { | ||||
| 				return NewTTransportExceptionFromError(err) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		var payload bytes.Buffer | ||||
| 		meta := headerMeta{ | ||||
| 			MagicFlags:   THeaderHeaderMagic + t.Flags&THeaderFlagsMask, | ||||
| 			SequenceID:   t.SequenceID, | ||||
| 			HeaderLength: uint16(headers.Len() / 4), | ||||
| 		} | ||||
| 		if err := binary.Write(&payload, binary.BigEndian, meta); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		if _, err := io.Copy(&payload, headers); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 
 | ||||
| 		writer, err := NewTransformWriter(&payload, t.writeTransforms) | ||||
| 		if err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		if _, err := io.Copy(writer, &t.writeBuffer); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		if err := writer.Close(); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 
 | ||||
| 		// First write frame length | ||||
| 		buf := t.buffer[:size32] | ||||
| 		binary.BigEndian.PutUint32(buf, uint32(payload.Len())) | ||||
| 		if _, err := t.transport.Write(buf); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		// Then write the payload | ||||
| 		if _, err := io.Copy(t.transport, &payload); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 
 | ||||
| 	case clientFramedBinary, clientFramedCompact: | ||||
| 		buf := t.buffer[:size32] | ||||
| 		binary.BigEndian.PutUint32(buf, uint32(t.writeBuffer.Len())) | ||||
| 		if _, err := t.transport.Write(buf); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		fallthrough | ||||
| 	case clientUnframedBinary, clientUnframedCompact: | ||||
| 		if _, err := io.Copy(t.transport, &t.writeBuffer); err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	select { | ||||
| 	default: | ||||
| 	case <-ctx.Done(): | ||||
| 		return NewTTransportExceptionFromError(ctx.Err()) | ||||
| 	} | ||||
| 
 | ||||
| 	return t.transport.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| // Close closes the transport, along with its underlying transport. | ||||
| func (t *THeaderTransport) Close() error { | ||||
| 	if err := t.Flush(context.Background()); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return t.transport.Close() | ||||
| } | ||||
| 
 | ||||
| // RemainingBytes calls underlying transport's RemainingBytes. | ||||
| // | ||||
| // Even in framed cases, because of all the possible compression transforms | ||||
| // involved, the remaining frame size is likely to be different from the actual | ||||
| // remaining readable bytes, so we don't bother to keep tracking the remaining | ||||
| // frame size by ourselves and just use the underlying transport's | ||||
| // RemainingBytes directly. | ||||
| func (t *THeaderTransport) RemainingBytes() uint64 { | ||||
| 	return t.transport.RemainingBytes() | ||||
| } | ||||
| 
 | ||||
| // GetReadHeaders returns the THeaderMap read from transport. | ||||
| func (t *THeaderTransport) GetReadHeaders() THeaderMap { | ||||
| 	return t.readHeaders | ||||
| } | ||||
| 
 | ||||
| // SetWriteHeader sets a header for write. | ||||
| func (t *THeaderTransport) SetWriteHeader(key, value string) { | ||||
| 	t.writeHeaders[key] = value | ||||
| } | ||||
| 
 | ||||
| // ClearWriteHeaders clears all write headers previously set. | ||||
| func (t *THeaderTransport) ClearWriteHeaders() { | ||||
| 	t.writeHeaders = make(THeaderMap) | ||||
| } | ||||
| 
 | ||||
| // AddTransform add a transform for writing. | ||||
| func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error { | ||||
| 	if !supportedTransformIDs[transform] { | ||||
| 		return NewTProtocolExceptionWithType( | ||||
| 			NOT_IMPLEMENTED, | ||||
| 			fmt.Errorf("THeaderTransformID %d not supported", transform), | ||||
| 		) | ||||
| 	} | ||||
| 	t.writeTransforms = append(t.writeTransforms, transform) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Protocol returns the wrapped protocol id used in this THeaderTransport. | ||||
| func (t *THeaderTransport) Protocol() THeaderProtocolID { | ||||
| 	switch t.clientType { | ||||
| 	default: | ||||
| 		return t.protocolID | ||||
| 	case clientFramedBinary, clientUnframedBinary: | ||||
| 		return THeaderProtocolBinary | ||||
| 	case clientFramedCompact, clientUnframedCompact: | ||||
| 		return THeaderProtocolCompact | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *THeaderTransport) isFramed() bool { | ||||
| 	switch t.clientType { | ||||
| 	default: | ||||
| 		return false | ||||
| 	case clientHeaders, clientFramedBinary, clientFramedCompact: | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| func (t *THeaderTransport) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(t.transport, cfg) | ||||
| 	t.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| // THeaderTransportFactory is a TTransportFactory implementation to create | ||||
| // THeaderTransport. | ||||
| // | ||||
| // It also implements TConfigurationSetter. | ||||
| type THeaderTransportFactory struct { | ||||
| 	// The underlying factory, could be nil. | ||||
| 	Factory TTransportFactory | ||||
| 
 | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHeaderTransportFactoryConf instead. | ||||
| func NewTHeaderTransportFactory(factory TTransportFactory) TTransportFactory { | ||||
| 	return NewTHeaderTransportFactoryConf(factory, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTHeaderTransportFactoryConf creates a new *THeaderTransportFactory with | ||||
| // the given *TConfiguration. | ||||
| func NewTHeaderTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory { | ||||
| 	return &THeaderTransportFactory{ | ||||
| 		Factory: factory, | ||||
| 
 | ||||
| 		cfg: conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GetTransport implements TTransportFactory. | ||||
| func (f *THeaderTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	if f.Factory != nil { | ||||
| 		t, err := f.Factory.GetTransport(trans) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return NewTHeaderTransportConf(t, f.cfg), nil | ||||
| 	} | ||||
| 	return NewTHeaderTransportConf(trans, f.cfg), nil | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| func (f *THeaderTransportFactory) SetTConfiguration(cfg *TConfiguration) { | ||||
| 	PropagateTConfiguration(f.Factory, f.cfg) | ||||
| 	f.cfg = cfg | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ TConfigurationSetter = (*THeaderTransportFactory)(nil) | ||||
| 	_ TConfigurationSetter = (*THeaderTransport)(nil) | ||||
| ) | ||||
|  | @ -1,257 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // Default to using the shared http client. Library users are | ||||
| // free to change this global client or specify one through | ||||
| // THttpClientOptions. | ||||
| var DefaultHttpClient *http.Client = http.DefaultClient | ||||
| 
 | ||||
| type THttpClient struct { | ||||
| 	client             *http.Client | ||||
| 	response           *http.Response | ||||
| 	url                *url.URL | ||||
| 	requestBuffer      *bytes.Buffer | ||||
| 	header             http.Header | ||||
| 	nsecConnectTimeout int64 | ||||
| 	nsecReadTimeout    int64 | ||||
| } | ||||
| 
 | ||||
| type THttpClientTransportFactory struct { | ||||
| 	options THttpClientOptions | ||||
| 	url     string | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClientTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	if trans != nil { | ||||
| 		t, ok := trans.(*THttpClient) | ||||
| 		if ok && t.url != nil { | ||||
| 			return NewTHttpClientWithOptions(t.url.String(), p.options) | ||||
| 		} | ||||
| 	} | ||||
| 	return NewTHttpClientWithOptions(p.url, p.options) | ||||
| } | ||||
| 
 | ||||
| type THttpClientOptions struct { | ||||
| 	// If nil, DefaultHttpClient is used | ||||
| 	Client *http.Client | ||||
| } | ||||
| 
 | ||||
| func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { | ||||
| 	return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) | ||||
| } | ||||
| 
 | ||||
| func NewTHttpClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { | ||||
| 	return &THttpClientTransportFactory{url: url, options: options} | ||||
| } | ||||
| 
 | ||||
| func NewTHttpClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { | ||||
| 	parsedURL, err := url.Parse(urlstr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	buf := make([]byte, 0, 1024) | ||||
| 	client := options.Client | ||||
| 	if client == nil { | ||||
| 		client = DefaultHttpClient | ||||
| 	} | ||||
| 	httpHeader := map[string][]string{"Content-Type": {"application/x-thrift"}} | ||||
| 	return &THttpClient{client: client, url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: httpHeader}, nil | ||||
| } | ||||
| 
 | ||||
| func NewTHttpClient(urlstr string) (TTransport, error) { | ||||
| 	return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) | ||||
| } | ||||
| 
 | ||||
| // Set the HTTP Header for this specific Thrift Transport | ||||
| // It is important that you first assert the TTransport as a THttpClient type | ||||
| // like so: | ||||
| // | ||||
| // httpTrans := trans.(THttpClient) | ||||
| // httpTrans.SetHeader("User-Agent","Thrift Client 1.0") | ||||
| func (p *THttpClient) SetHeader(key string, value string) { | ||||
| 	p.header.Add(key, value) | ||||
| } | ||||
| 
 | ||||
| // Get the HTTP Header represented by the supplied Header Key for this specific Thrift Transport | ||||
| // It is important that you first assert the TTransport as a THttpClient type | ||||
| // like so: | ||||
| // | ||||
| // httpTrans := trans.(THttpClient) | ||||
| // hdrValue := httpTrans.GetHeader("User-Agent") | ||||
| func (p *THttpClient) GetHeader(key string) string { | ||||
| 	return p.header.Get(key) | ||||
| } | ||||
| 
 | ||||
| // Deletes the HTTP Header given a Header Key for this specific Thrift Transport | ||||
| // It is important that you first assert the TTransport as a THttpClient type | ||||
| // like so: | ||||
| // | ||||
| // httpTrans := trans.(THttpClient) | ||||
| // httpTrans.DelHeader("User-Agent") | ||||
| func (p *THttpClient) DelHeader(key string) { | ||||
| 	p.header.Del(key) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) Open() error { | ||||
| 	// do nothing | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) IsOpen() bool { | ||||
| 	return p.response != nil || p.requestBuffer != nil | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) closeResponse() error { | ||||
| 	var err error | ||||
| 	if p.response != nil && p.response.Body != nil { | ||||
| 		// The docs specify that if keepalive is enabled and the response body is not | ||||
| 		// read to completion the connection will never be returned to the pool and | ||||
| 		// reused. Errors are being ignored here because if the connection is invalid | ||||
| 		// and this fails for some reason, the Close() method will do any remaining | ||||
| 		// cleanup. | ||||
| 		io.Copy(io.Discard, p.response.Body) | ||||
| 
 | ||||
| 		err = p.response.Body.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	p.response = nil | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) Close() error { | ||||
| 	if p.requestBuffer != nil { | ||||
| 		p.requestBuffer.Reset() | ||||
| 		p.requestBuffer = nil | ||||
| 	} | ||||
| 	return p.closeResponse() | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) Read(buf []byte) (int, error) { | ||||
| 	if p.response == nil { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") | ||||
| 	} | ||||
| 	n, err := p.response.Body.Read(buf) | ||||
| 	if n > 0 && (err == nil || errors.Is(err, io.EOF)) { | ||||
| 		return n, nil | ||||
| 	} | ||||
| 	return n, NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) ReadByte() (c byte, err error) { | ||||
| 	if p.response == nil { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") | ||||
| 	} | ||||
| 	return readByte(p.response.Body) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) Write(buf []byte) (int, error) { | ||||
| 	if p.requestBuffer == nil { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") | ||||
| 	} | ||||
| 	return p.requestBuffer.Write(buf) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) WriteByte(c byte) error { | ||||
| 	if p.requestBuffer == nil { | ||||
| 		return NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") | ||||
| 	} | ||||
| 	return p.requestBuffer.WriteByte(c) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) WriteString(s string) (n int, err error) { | ||||
| 	if p.requestBuffer == nil { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") | ||||
| 	} | ||||
| 	return p.requestBuffer.WriteString(s) | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) Flush(ctx context.Context) error { | ||||
| 	// Close any previous response body to avoid leaking connections. | ||||
| 	p.closeResponse() | ||||
| 
 | ||||
| 	// Give up the ownership of the current request buffer to http request, | ||||
| 	// and create a new buffer for the next request. | ||||
| 	buf := p.requestBuffer | ||||
| 	p.requestBuffer = new(bytes.Buffer) | ||||
| 	req, err := http.NewRequest("POST", p.url.String(), buf) | ||||
| 	if err != nil { | ||||
| 		return NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	req.Header = p.header | ||||
| 	if ctx != nil { | ||||
| 		req = req.WithContext(ctx) | ||||
| 	} | ||||
| 	response, err := p.client.Do(req) | ||||
| 	if err != nil { | ||||
| 		return NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	if response.StatusCode != http.StatusOK { | ||||
| 		// Close the response to avoid leaking file descriptors. closeResponse does | ||||
| 		// more than just call Close(), so temporarily assign it and reuse the logic. | ||||
| 		p.response = response | ||||
| 		p.closeResponse() | ||||
| 
 | ||||
| 		// TODO(pomack) log bad response | ||||
| 		return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode)) | ||||
| 	} | ||||
| 	p.response = response | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *THttpClient) RemainingBytes() (num_bytes uint64) { | ||||
| 	len := p.response.ContentLength | ||||
| 	if len >= 0 { | ||||
| 		return uint64(len) | ||||
| 	} | ||||
| 
 | ||||
| 	const maxSize = ^uint64(0) | ||||
| 	return maxSize // the truth is, we just don't know unless framed is used | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHttpClientTransportFactory instead. | ||||
| func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { | ||||
| 	return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHttpClientTransportFactoryWithOptions instead. | ||||
| func NewTHttpPostClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { | ||||
| 	return NewTHttpClientTransportFactoryWithOptions(url, options) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHttpClientWithOptions instead. | ||||
| func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { | ||||
| 	return NewTHttpClientWithOptions(urlstr, options) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTHttpClient instead. | ||||
| func NewTHttpPostClient(urlstr string) (TTransport, error) { | ||||
| 	return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) | ||||
| } | ||||
|  | @ -1,74 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"compress/gzip" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| // NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function | ||||
| func NewThriftHandlerFunc(processor TProcessor, | ||||
| 	inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { | ||||
| 
 | ||||
| 	return gz(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		w.Header().Add("Content-Type", "application/x-thrift") | ||||
| 
 | ||||
| 		transport := NewStreamTransport(r.Body, w) | ||||
| 		processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // gz transparently compresses the HTTP response if the client supports it. | ||||
| func gz(handler http.HandlerFunc) http.HandlerFunc { | ||||
| 	sp := &sync.Pool{ | ||||
| 		New: func() interface{} { | ||||
| 			return gzip.NewWriter(nil) | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	return func(w http.ResponseWriter, r *http.Request) { | ||||
| 		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { | ||||
| 			handler(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		w.Header().Set("Content-Encoding", "gzip") | ||||
| 		gz := sp.Get().(*gzip.Writer) | ||||
| 		gz.Reset(w) | ||||
| 		defer func() { | ||||
| 			_ = gz.Close() | ||||
| 			sp.Put(gz) | ||||
| 		}() | ||||
| 		gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w} | ||||
| 		handler(gzw, r) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type gzipResponseWriter struct { | ||||
| 	io.Writer | ||||
| 	http.ResponseWriter | ||||
| } | ||||
| 
 | ||||
| func (w gzipResponseWriter) Write(b []byte) (int, error) { | ||||
| 	return w.Writer.Write(b) | ||||
| } | ||||
|  | @ -1,222 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"context" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // StreamTransport is a Transport made of an io.Reader and/or an io.Writer | ||||
| type StreamTransport struct { | ||||
| 	io.Reader | ||||
| 	io.Writer | ||||
| 	isReadWriter bool | ||||
| 	closed       bool | ||||
| } | ||||
| 
 | ||||
| type StreamTransportFactory struct { | ||||
| 	Reader       io.Reader | ||||
| 	Writer       io.Writer | ||||
| 	isReadWriter bool | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	if trans != nil { | ||||
| 		t, ok := trans.(*StreamTransport) | ||||
| 		if ok { | ||||
| 			if t.isReadWriter { | ||||
| 				return NewStreamTransportRW(t.Reader.(io.ReadWriter)), nil | ||||
| 			} | ||||
| 			if t.Reader != nil && t.Writer != nil { | ||||
| 				return NewStreamTransport(t.Reader, t.Writer), nil | ||||
| 			} | ||||
| 			if t.Reader != nil && t.Writer == nil { | ||||
| 				return NewStreamTransportR(t.Reader), nil | ||||
| 			} | ||||
| 			if t.Reader == nil && t.Writer != nil { | ||||
| 				return NewStreamTransportW(t.Writer), nil | ||||
| 			} | ||||
| 			return &StreamTransport{}, nil | ||||
| 		} | ||||
| 	} | ||||
| 	if p.isReadWriter { | ||||
| 		return NewStreamTransportRW(p.Reader.(io.ReadWriter)), nil | ||||
| 	} | ||||
| 	if p.Reader != nil && p.Writer != nil { | ||||
| 		return NewStreamTransport(p.Reader, p.Writer), nil | ||||
| 	} | ||||
| 	if p.Reader != nil && p.Writer == nil { | ||||
| 		return NewStreamTransportR(p.Reader), nil | ||||
| 	} | ||||
| 	if p.Reader == nil && p.Writer != nil { | ||||
| 		return NewStreamTransportW(p.Writer), nil | ||||
| 	} | ||||
| 	return &StreamTransport{}, nil | ||||
| } | ||||
| 
 | ||||
| func NewStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *StreamTransportFactory { | ||||
| 	return &StreamTransportFactory{Reader: reader, Writer: writer, isReadWriter: isReadWriter} | ||||
| } | ||||
| 
 | ||||
| func NewStreamTransport(r io.Reader, w io.Writer) *StreamTransport { | ||||
| 	return &StreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)} | ||||
| } | ||||
| 
 | ||||
| func NewStreamTransportR(r io.Reader) *StreamTransport { | ||||
| 	return &StreamTransport{Reader: bufio.NewReader(r)} | ||||
| } | ||||
| 
 | ||||
| func NewStreamTransportW(w io.Writer) *StreamTransport { | ||||
| 	return &StreamTransport{Writer: bufio.NewWriter(w)} | ||||
| } | ||||
| 
 | ||||
| func NewStreamTransportRW(rw io.ReadWriter) *StreamTransport { | ||||
| 	bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)) | ||||
| 	return &StreamTransport{Reader: bufrw, Writer: bufrw, isReadWriter: true} | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) IsOpen() bool { | ||||
| 	return !p.closed | ||||
| } | ||||
| 
 | ||||
| // implicitly opened on creation, can't be reopened once closed | ||||
| func (p *StreamTransport) Open() error { | ||||
| 	if !p.closed { | ||||
| 		return NewTTransportException(ALREADY_OPEN, "StreamTransport already open.") | ||||
| 	} else { | ||||
| 		return NewTTransportException(NOT_OPEN, "cannot reopen StreamTransport.") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Closes both the input and output streams. | ||||
| func (p *StreamTransport) Close() error { | ||||
| 	if p.closed { | ||||
| 		return NewTTransportException(NOT_OPEN, "StreamTransport already closed.") | ||||
| 	} | ||||
| 	p.closed = true | ||||
| 	closedReader := false | ||||
| 	if p.Reader != nil { | ||||
| 		c, ok := p.Reader.(io.Closer) | ||||
| 		if ok { | ||||
| 			e := c.Close() | ||||
| 			closedReader = true | ||||
| 			if e != nil { | ||||
| 				return e | ||||
| 			} | ||||
| 		} | ||||
| 		p.Reader = nil | ||||
| 	} | ||||
| 	if p.Writer != nil && (!closedReader || !p.isReadWriter) { | ||||
| 		c, ok := p.Writer.(io.Closer) | ||||
| 		if ok { | ||||
| 			e := c.Close() | ||||
| 			if e != nil { | ||||
| 				return e | ||||
| 			} | ||||
| 		} | ||||
| 		p.Writer = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Flushes the underlying output stream if not null. | ||||
| func (p *StreamTransport) Flush(ctx context.Context) error { | ||||
| 	if p.Writer == nil { | ||||
| 		return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") | ||||
| 	} | ||||
| 	f, ok := p.Writer.(Flusher) | ||||
| 	if ok { | ||||
| 		err := f.Flush() | ||||
| 		if err != nil { | ||||
| 			return NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) Read(c []byte) (n int, err error) { | ||||
| 	n, err = p.Reader.Read(c) | ||||
| 	if err != nil { | ||||
| 		err = NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) ReadByte() (c byte, err error) { | ||||
| 	f, ok := p.Reader.(io.ByteReader) | ||||
| 	if ok { | ||||
| 		c, err = f.ReadByte() | ||||
| 	} else { | ||||
| 		c, err = readByte(p.Reader) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		err = NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) Write(c []byte) (n int, err error) { | ||||
| 	n, err = p.Writer.Write(c) | ||||
| 	if err != nil { | ||||
| 		err = NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) WriteByte(c byte) (err error) { | ||||
| 	f, ok := p.Writer.(io.ByteWriter) | ||||
| 	if ok { | ||||
| 		err = f.WriteByte(c) | ||||
| 	} else { | ||||
| 		err = writeByte(p.Writer, c) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		err = NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) WriteString(s string) (n int, err error) { | ||||
| 	f, ok := p.Writer.(stringWriter) | ||||
| 	if ok { | ||||
| 		n, err = f.WriteString(s) | ||||
| 	} else { | ||||
| 		n, err = p.Writer.Write([]byte(s)) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		err = NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *StreamTransport) RemainingBytes() (num_bytes uint64) { | ||||
| 	const maxSize = ^uint64(0) | ||||
| 	return maxSize // the truth is, we just don't know unless framed is used | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter for propagation. | ||||
| func (p *StreamTransport) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(p.Reader, conf) | ||||
| 	PropagateTConfiguration(p.Writer, conf) | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*StreamTransport)(nil) | ||||
|  | @ -1,591 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	THRIFT_JSON_PROTOCOL_VERSION = 1 | ||||
| ) | ||||
| 
 | ||||
| // for references to _ParseContext see tsimplejson_protocol.go | ||||
| 
 | ||||
| // JSON protocol implementation for thrift. | ||||
| // Utilizes Simple JSON protocol | ||||
| // | ||||
| type TJSONProtocol struct { | ||||
| 	*TSimpleJSONProtocol | ||||
| } | ||||
| 
 | ||||
| // Constructor | ||||
| func NewTJSONProtocol(t TTransport) *TJSONProtocol { | ||||
| 	v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} | ||||
| 	v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL) | ||||
| 	v.dumpContext.push(_CONTEXT_IN_TOPLEVEL) | ||||
| 	return v | ||||
| } | ||||
| 
 | ||||
| // Factory | ||||
| type TJSONProtocolFactory struct{} | ||||
| 
 | ||||
| func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { | ||||
| 	return NewTJSONProtocol(trans) | ||||
| } | ||||
| 
 | ||||
| func NewTJSONProtocolFactory() *TJSONProtocolFactory { | ||||
| 	return &TJSONProtocolFactory{} | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { | ||||
| 	p.resetContextStack() // THRIFT-3735 | ||||
| 	if e := p.OutputListBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.WriteI32(ctx, THRIFT_JSON_PROTOCOL_VERSION); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.WriteString(ctx, name); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.WriteByte(ctx, int8(typeId)); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.WriteI32(ctx, seqId); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteMessageEnd(ctx context.Context) error { | ||||
| 	return p.OutputListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteStructBegin(ctx context.Context, name string) error { | ||||
| 	if e := p.OutputObjectBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteStructEnd(ctx context.Context) error { | ||||
| 	return p.OutputObjectEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { | ||||
| 	if e := p.WriteI16(ctx, id); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.OutputObjectBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	s, e1 := p.TypeIdToString(typeId) | ||||
| 	if e1 != nil { | ||||
| 		return e1 | ||||
| 	} | ||||
| 	if e := p.WriteString(ctx, s); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteFieldEnd(ctx context.Context) error { | ||||
| 	return p.OutputObjectEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { | ||||
| 	if e := p.OutputListBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	s, e1 := p.TypeIdToString(keyType) | ||||
| 	if e1 != nil { | ||||
| 		return e1 | ||||
| 	} | ||||
| 	if e := p.WriteString(ctx, s); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	s, e1 = p.TypeIdToString(valueType) | ||||
| 	if e1 != nil { | ||||
| 		return e1 | ||||
| 	} | ||||
| 	if e := p.WriteString(ctx, s); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.WriteI64(ctx, int64(size)); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return p.OutputObjectBegin() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteMapEnd(ctx context.Context) error { | ||||
| 	if e := p.OutputObjectEnd(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return p.OutputListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	return p.OutputElemListBegin(elemType, size) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteListEnd(ctx context.Context) error { | ||||
| 	return p.OutputListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { | ||||
| 	return p.OutputElemListBegin(elemType, size) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteSetEnd(ctx context.Context) error { | ||||
| 	return p.OutputListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteBool(ctx context.Context, b bool) error { | ||||
| 	if b { | ||||
| 		return p.WriteI32(ctx, 1) | ||||
| 	} | ||||
| 	return p.WriteI32(ctx, 0) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteByte(ctx context.Context, b int8) error { | ||||
| 	return p.WriteI32(ctx, int32(b)) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteI16(ctx context.Context, v int16) error { | ||||
| 	return p.WriteI32(ctx, int32(v)) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteI32(ctx context.Context, v int32) error { | ||||
| 	return p.OutputI64(int64(v)) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteI64(ctx context.Context, v int64) error { | ||||
| 	return p.OutputI64(int64(v)) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteDouble(ctx context.Context, v float64) error { | ||||
| 	return p.OutputF64(v) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteString(ctx context.Context, v string) error { | ||||
| 	return p.OutputString(v) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) WriteBinary(ctx context.Context, v []byte) error { | ||||
| 	// JSON library only takes in a string, | ||||
| 	// not an arbitrary byte array, to ensure bytes are transmitted | ||||
| 	// efficiently we must convert this into a valid JSON string | ||||
| 	// therefore we use base64 encoding to avoid excessive escaping/quoting | ||||
| 	if e := p.OutputPreValue(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if _, e := p.write(JSON_QUOTE_BYTES); e != nil { | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	writer := base64.NewEncoder(base64.StdEncoding, p.writer) | ||||
| 	if _, e := writer.Write(v); e != nil { | ||||
| 		p.writer.Reset(p.trans) // THRIFT-3735 | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	if e := writer.Close(); e != nil { | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	if _, e := p.write(JSON_QUOTE_BYTES); e != nil { | ||||
| 		return NewTProtocolException(e) | ||||
| 	} | ||||
| 	return p.OutputPostValue() | ||||
| } | ||||
| 
 | ||||
| // Reading methods. | ||||
| func (p *TJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { | ||||
| 	p.resetContextStack() // THRIFT-3735 | ||||
| 	if isNull, err := p.ParseListBegin(); isNull || err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	version, err := p.ReadI32(ctx) | ||||
| 	if err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	if version != THRIFT_JSON_PROTOCOL_VERSION { | ||||
| 		e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION) | ||||
| 		return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| 
 | ||||
| 	} | ||||
| 	if name, err = p.ReadString(ctx); err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	bTypeId, err := p.ReadByte(ctx) | ||||
| 	typeId = TMessageType(bTypeId) | ||||
| 	if err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	if seqId, err = p.ReadI32(ctx); err != nil { | ||||
| 		return name, typeId, seqId, err | ||||
| 	} | ||||
| 	return name, typeId, seqId, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadMessageEnd(ctx context.Context) error { | ||||
| 	err := p.ParseListEnd() | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { | ||||
| 	_, err = p.ParseObjectStart() | ||||
| 	return "", err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadStructEnd(ctx context.Context) error { | ||||
| 	return p.ParseObjectEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) { | ||||
| 	b, _ := p.reader.Peek(1) | ||||
| 	if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { | ||||
| 		return "", STOP, -1, nil | ||||
| 	} | ||||
| 	fieldId, err := p.ReadI16(ctx) | ||||
| 	if err != nil { | ||||
| 		return "", STOP, fieldId, err | ||||
| 	} | ||||
| 	if _, err = p.ParseObjectStart(); err != nil { | ||||
| 		return "", STOP, fieldId, err | ||||
| 	} | ||||
| 	sType, err := p.ReadString(ctx) | ||||
| 	if err != nil { | ||||
| 		return "", STOP, fieldId, err | ||||
| 	} | ||||
| 	fType, err := p.StringToTypeId(sType) | ||||
| 	return "", fType, fieldId, err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadFieldEnd(ctx context.Context) error { | ||||
| 	return p.ParseObjectEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) { | ||||
| 	if isNull, e := p.ParseListBegin(); isNull || e != nil { | ||||
| 		return VOID, VOID, 0, e | ||||
| 	} | ||||
| 
 | ||||
| 	// read keyType | ||||
| 	sKeyType, e := p.ReadString(ctx) | ||||
| 	if e != nil { | ||||
| 		return keyType, valueType, size, e | ||||
| 	} | ||||
| 	keyType, e = p.StringToTypeId(sKeyType) | ||||
| 	if e != nil { | ||||
| 		return keyType, valueType, size, e | ||||
| 	} | ||||
| 
 | ||||
| 	// read valueType | ||||
| 	sValueType, e := p.ReadString(ctx) | ||||
| 	if e != nil { | ||||
| 		return keyType, valueType, size, e | ||||
| 	} | ||||
| 	valueType, e = p.StringToTypeId(sValueType) | ||||
| 	if e != nil { | ||||
| 		return keyType, valueType, size, e | ||||
| 	} | ||||
| 
 | ||||
| 	// read size | ||||
| 	iSize, e := p.ReadI64(ctx) | ||||
| 	if e != nil { | ||||
| 		return keyType, valueType, size, e | ||||
| 	} | ||||
| 	size = int(iSize) | ||||
| 
 | ||||
| 	_, e = p.ParseObjectStart() | ||||
| 	return keyType, valueType, size, e | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadMapEnd(ctx context.Context) error { | ||||
| 	e := p.ParseObjectEnd() | ||||
| 	if e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return p.ParseListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) { | ||||
| 	return p.ParseElemListBegin() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadListEnd(ctx context.Context) error { | ||||
| 	return p.ParseListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) { | ||||
| 	return p.ParseElemListBegin() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadSetEnd(ctx context.Context) error { | ||||
| 	return p.ParseListEnd() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadBool(ctx context.Context) (bool, error) { | ||||
| 	value, err := p.ReadI32(ctx) | ||||
| 	return (value != 0), err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadByte(ctx context.Context) (int8, error) { | ||||
| 	v, err := p.ReadI64(ctx) | ||||
| 	return int8(v), err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadI16(ctx context.Context) (int16, error) { | ||||
| 	v, err := p.ReadI64(ctx) | ||||
| 	return int16(v), err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadI32(ctx context.Context) (int32, error) { | ||||
| 	v, err := p.ReadI64(ctx) | ||||
| 	return int32(v), err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadI64(ctx context.Context) (int64, error) { | ||||
| 	v, _, err := p.ParseI64() | ||||
| 	return v, err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadDouble(ctx context.Context) (float64, error) { | ||||
| 	v, _, err := p.ParseF64() | ||||
| 	return v, err | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadString(ctx context.Context) (string, error) { | ||||
| 	var v string | ||||
| 	if err := p.ParsePreValue(); err != nil { | ||||
| 		return v, err | ||||
| 	} | ||||
| 	f, _ := p.reader.Peek(1) | ||||
| 	if len(f) > 0 && f[0] == JSON_QUOTE { | ||||
| 		p.reader.ReadByte() | ||||
| 		value, err := p.ParseStringBody() | ||||
| 		v = value | ||||
| 		if err != nil { | ||||
| 			return v, err | ||||
| 		} | ||||
| 	} else if len(f) > 0 && f[0] == JSON_NULL[0] { | ||||
| 		b := make([]byte, len(JSON_NULL)) | ||||
| 		_, err := p.reader.Read(b) | ||||
| 		if err != nil { | ||||
| 			return v, NewTProtocolException(err) | ||||
| 		} | ||||
| 		if string(b) != string(JSON_NULL) { | ||||
| 			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) | ||||
| 			return v, NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| 		} | ||||
| 	} else { | ||||
| 		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) | ||||
| 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| 	} | ||||
| 	return v, p.ParsePostValue() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) { | ||||
| 	var v []byte | ||||
| 	if err := p.ParsePreValue(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	f, _ := p.reader.Peek(1) | ||||
| 	if len(f) > 0 && f[0] == JSON_QUOTE { | ||||
| 		p.reader.ReadByte() | ||||
| 		value, err := p.ParseBase64EncodedBody() | ||||
| 		v = value | ||||
| 		if err != nil { | ||||
| 			return v, err | ||||
| 		} | ||||
| 	} else if len(f) > 0 && f[0] == JSON_NULL[0] { | ||||
| 		b := make([]byte, len(JSON_NULL)) | ||||
| 		_, err := p.reader.Read(b) | ||||
| 		if err != nil { | ||||
| 			return v, NewTProtocolException(err) | ||||
| 		} | ||||
| 		if string(b) != string(JSON_NULL) { | ||||
| 			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) | ||||
| 			return v, NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| 		} | ||||
| 	} else { | ||||
| 		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) | ||||
| 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| 	} | ||||
| 
 | ||||
| 	return v, p.ParsePostValue() | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) Flush(ctx context.Context) (err error) { | ||||
| 	err = p.writer.Flush() | ||||
| 	if err == nil { | ||||
| 		err = p.trans.Flush(ctx) | ||||
| 	} | ||||
| 	return NewTProtocolException(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) { | ||||
| 	return SkipDefaultDepth(ctx, p, fieldType) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) Transport() TTransport { | ||||
| 	return p.trans | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error { | ||||
| 	if e := p.OutputListBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	s, e1 := p.TypeIdToString(elemType) | ||||
| 	if e1 != nil { | ||||
| 		return e1 | ||||
| 	} | ||||
| 	if e := p.OutputString(s); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.OutputI64(int64(size)); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { | ||||
| 	if isNull, e := p.ParseListBegin(); isNull || e != nil { | ||||
| 		return VOID, 0, e | ||||
| 	} | ||||
| 	// We don't really use the ctx in ReadString implementation, | ||||
| 	// so this is safe for now. | ||||
| 	// We might want to add context to ParseElemListBegin if we start to use | ||||
| 	// ctx in ReadString implementation in the future. | ||||
| 	sElemType, err := p.ReadString(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return VOID, size, err | ||||
| 	} | ||||
| 	elemType, err = p.StringToTypeId(sElemType) | ||||
| 	if err != nil { | ||||
| 		return elemType, size, err | ||||
| 	} | ||||
| 	nSize, _, err2 := p.ParseI64() | ||||
| 	size = int(nSize) | ||||
| 	return elemType, size, err2 | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) { | ||||
| 	if isNull, e := p.ParseListBegin(); isNull || e != nil { | ||||
| 		return VOID, 0, e | ||||
| 	} | ||||
| 	// We don't really use the ctx in ReadString implementation, | ||||
| 	// so this is safe for now. | ||||
| 	// We might want to add context to ParseElemListBegin if we start to use | ||||
| 	// ctx in ReadString implementation in the future. | ||||
| 	sElemType, err := p.ReadString(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return VOID, size, err | ||||
| 	} | ||||
| 	elemType, err = p.StringToTypeId(sElemType) | ||||
| 	if err != nil { | ||||
| 		return elemType, size, err | ||||
| 	} | ||||
| 	nSize, _, err2 := p.ParseI64() | ||||
| 	size = int(nSize) | ||||
| 	return elemType, size, err2 | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error { | ||||
| 	if e := p.OutputListBegin(); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	s, e1 := p.TypeIdToString(elemType) | ||||
| 	if e1 != nil { | ||||
| 		return e1 | ||||
| 	} | ||||
| 	if e := p.OutputString(s); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	if e := p.OutputI64(int64(size)); e != nil { | ||||
| 		return e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) { | ||||
| 	switch byte(fieldType) { | ||||
| 	case BOOL: | ||||
| 		return "tf", nil | ||||
| 	case BYTE: | ||||
| 		return "i8", nil | ||||
| 	case I16: | ||||
| 		return "i16", nil | ||||
| 	case I32: | ||||
| 		return "i32", nil | ||||
| 	case I64: | ||||
| 		return "i64", nil | ||||
| 	case DOUBLE: | ||||
| 		return "dbl", nil | ||||
| 	case STRING: | ||||
| 		return "str", nil | ||||
| 	case STRUCT: | ||||
| 		return "rec", nil | ||||
| 	case MAP: | ||||
| 		return "map", nil | ||||
| 	case SET: | ||||
| 		return "set", nil | ||||
| 	case LIST: | ||||
| 		return "lst", nil | ||||
| 	} | ||||
| 
 | ||||
| 	e := fmt.Errorf("Unknown fieldType: %d", int(fieldType)) | ||||
| 	return "", NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| } | ||||
| 
 | ||||
| func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) { | ||||
| 	switch fieldType { | ||||
| 	case "tf": | ||||
| 		return TType(BOOL), nil | ||||
| 	case "i8": | ||||
| 		return TType(BYTE), nil | ||||
| 	case "i16": | ||||
| 		return TType(I16), nil | ||||
| 	case "i32": | ||||
| 		return TType(I32), nil | ||||
| 	case "i64": | ||||
| 		return TType(I64), nil | ||||
| 	case "dbl": | ||||
| 		return TType(DOUBLE), nil | ||||
| 	case "str": | ||||
| 		return TType(STRING), nil | ||||
| 	case "rec": | ||||
| 		return TType(STRUCT), nil | ||||
| 	case "map": | ||||
| 		return TType(MAP), nil | ||||
| 	case "set": | ||||
| 		return TType(SET), nil | ||||
| 	case "lst": | ||||
| 		return TType(LIST), nil | ||||
| 	} | ||||
| 
 | ||||
| 	e := fmt.Errorf("Unknown type identifier: %s", fieldType) | ||||
| 	return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e) | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TJSONProtocol)(nil) | ||||
|  | @ -1,69 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| // Logger is a simple wrapper of a logging function. | ||||
| // | ||||
| // In reality the users might actually use different logging libraries, and they | ||||
| // are not always compatible with each other. | ||||
| // | ||||
| // Logger is meant to be a simple common ground that it's easy to wrap whatever | ||||
| // logging library they use into. | ||||
| // | ||||
| // See https://issues.apache.org/jira/browse/THRIFT-4985 for the design | ||||
| // discussion behind it. | ||||
| type Logger func(msg string) | ||||
| 
 | ||||
| // NopLogger is a Logger implementation that does nothing. | ||||
| func NopLogger(msg string) {} | ||||
| 
 | ||||
| // StdLogger wraps stdlib log package into a Logger. | ||||
| // | ||||
| // If logger passed in is nil, it will fallback to use stderr and default flags. | ||||
| func StdLogger(logger *log.Logger) Logger { | ||||
| 	if logger == nil { | ||||
| 		logger = log.New(os.Stderr, "", log.LstdFlags) | ||||
| 	} | ||||
| 	return func(msg string) { | ||||
| 		logger.Print(msg) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // TestLogger is a Logger implementation can be used in test codes. | ||||
| // | ||||
| // It fails the test when being called. | ||||
| func TestLogger(tb testing.TB) Logger { | ||||
| 	return func(msg string) { | ||||
| 		tb.Errorf("logger called with msg: %q", msg) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func fallbackLogger(logger Logger) Logger { | ||||
| 	if logger == nil { | ||||
| 		return StdLogger(nil) | ||||
| 	} | ||||
| 	return logger | ||||
| } | ||||
|  | @ -1,80 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| // Memory buffer-based implementation of the TTransport interface. | ||||
| type TMemoryBuffer struct { | ||||
| 	*bytes.Buffer | ||||
| 	size int | ||||
| } | ||||
| 
 | ||||
| type TMemoryBufferTransportFactory struct { | ||||
| 	size int | ||||
| } | ||||
| 
 | ||||
| func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	if trans != nil { | ||||
| 		t, ok := trans.(*TMemoryBuffer) | ||||
| 		if ok && t.size > 0 { | ||||
| 			return NewTMemoryBufferLen(t.size), nil | ||||
| 		} | ||||
| 	} | ||||
| 	return NewTMemoryBufferLen(p.size), nil | ||||
| } | ||||
| 
 | ||||
| func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { | ||||
| 	return &TMemoryBufferTransportFactory{size: size} | ||||
| } | ||||
| 
 | ||||
| func NewTMemoryBuffer() *TMemoryBuffer { | ||||
| 	return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0} | ||||
| } | ||||
| 
 | ||||
| func NewTMemoryBufferLen(size int) *TMemoryBuffer { | ||||
| 	buf := make([]byte, 0, size) | ||||
| 	return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size} | ||||
| } | ||||
| 
 | ||||
| func (p *TMemoryBuffer) IsOpen() bool { | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (p *TMemoryBuffer) Open() error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TMemoryBuffer) Close() error { | ||||
| 	p.Buffer.Reset() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Flushing a memory buffer is a no-op | ||||
| func (p *TMemoryBuffer) Flush(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TMemoryBuffer) RemainingBytes() (num_bytes uint64) { | ||||
| 	return uint64(p.Buffer.Len()) | ||||
| } | ||||
|  | @ -1,31 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| // Message type constants in the Thrift protocol. | ||||
| type TMessageType int32 | ||||
| 
 | ||||
| const ( | ||||
| 	INVALID_TMESSAGE_TYPE TMessageType = 0 | ||||
| 	CALL                  TMessageType = 1 | ||||
| 	REPLY                 TMessageType = 2 | ||||
| 	EXCEPTION             TMessageType = 3 | ||||
| 	ONEWAY                TMessageType = 4 | ||||
| ) | ||||
|  | @ -1,109 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| // ProcessorMiddleware is a function that can be passed to WrapProcessor to wrap the | ||||
| // TProcessorFunctions for that TProcessor. | ||||
| // | ||||
| // Middlewares are passed in the name of the function as set in the processor | ||||
| // map of the TProcessor. | ||||
| type ProcessorMiddleware func(name string, next TProcessorFunction) TProcessorFunction | ||||
| 
 | ||||
| // WrapProcessor takes an existing TProcessor and wraps each of its inner | ||||
| // TProcessorFunctions with the middlewares passed in and returns it. | ||||
| // | ||||
| // Middlewares will be called in the order that they are defined: | ||||
| // | ||||
| //		1. Middlewares[0] | ||||
| //		2. Middlewares[1] | ||||
| //		... | ||||
| //		N. Middlewares[n] | ||||
| func WrapProcessor(processor TProcessor, middlewares ...ProcessorMiddleware) TProcessor { | ||||
| 	for name, processorFunc := range processor.ProcessorMap() { | ||||
| 		wrapped := processorFunc | ||||
| 		// Add middlewares in reverse so the first in the list is the outermost. | ||||
| 		for i := len(middlewares) - 1; i >= 0; i-- { | ||||
| 			wrapped = middlewares[i](name, wrapped) | ||||
| 		} | ||||
| 		processor.AddToProcessorMap(name, wrapped) | ||||
| 	} | ||||
| 	return processor | ||||
| } | ||||
| 
 | ||||
| // WrappedTProcessorFunction is a convenience struct that implements the | ||||
| // TProcessorFunction interface that can be used when implementing custom | ||||
| // Middleware. | ||||
| type WrappedTProcessorFunction struct { | ||||
| 	// Wrapped is called by WrappedTProcessorFunction.Process and should be a | ||||
| 	// "wrapped" call to a base TProcessorFunc.Process call. | ||||
| 	Wrapped func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) | ||||
| } | ||||
| 
 | ||||
| // Process implements the TProcessorFunction interface using p.Wrapped. | ||||
| func (p WrappedTProcessorFunction) Process(ctx context.Context, seqID int32, in, out TProtocol) (bool, TException) { | ||||
| 	return p.Wrapped(ctx, seqID, in, out) | ||||
| } | ||||
| 
 | ||||
| // verify that WrappedTProcessorFunction implements TProcessorFunction | ||||
| var ( | ||||
| 	_ TProcessorFunction = WrappedTProcessorFunction{} | ||||
| 	_ TProcessorFunction = (*WrappedTProcessorFunction)(nil) | ||||
| ) | ||||
| 
 | ||||
| // ClientMiddleware can be passed to WrapClient in order to wrap TClient calls | ||||
| // with custom middleware. | ||||
| type ClientMiddleware func(TClient) TClient | ||||
| 
 | ||||
| // WrappedTClient is a convenience struct that implements the TClient interface | ||||
| // using inner Wrapped function. | ||||
| // | ||||
| // This is provided to aid in developing ClientMiddleware. | ||||
| type WrappedTClient struct { | ||||
| 	Wrapped func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) | ||||
| } | ||||
| 
 | ||||
| // Call implements the TClient interface by calling and returning c.Wrapped. | ||||
| func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { | ||||
| 	return c.Wrapped(ctx, method, args, result) | ||||
| } | ||||
| 
 | ||||
| // verify that WrappedTClient implements TClient | ||||
| var ( | ||||
| 	_ TClient = WrappedTClient{} | ||||
| 	_ TClient = (*WrappedTClient)(nil) | ||||
| ) | ||||
| 
 | ||||
| // WrapClient wraps the given TClient in the given middlewares. | ||||
| // | ||||
| // Middlewares will be called in the order that they are defined: | ||||
| // | ||||
| //		1. Middlewares[0] | ||||
| //		2. Middlewares[1] | ||||
| //		... | ||||
| //		N. Middlewares[n] | ||||
| func WrapClient(client TClient, middlewares ...ClientMiddleware) TClient { | ||||
| 	// Add middlewares in reverse so the first in the list is the outermost. | ||||
| 	for i := len(middlewares) - 1; i >= 0; i-- { | ||||
| 		client = middlewares[i](client) | ||||
| 	} | ||||
| 	return client | ||||
| } | ||||
|  | @ -1,235 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| /* | ||||
| TMultiplexedProtocol is a protocol-independent concrete decorator | ||||
| that allows a Thrift client to communicate with a multiplexing Thrift server, | ||||
| by prepending the service name to the function name during function calls. | ||||
| 
 | ||||
| NOTE: THIS IS NOT USED BY SERVERS.  On the server, use TMultiplexedProcessor to handle request | ||||
| from a multiplexing client. | ||||
| 
 | ||||
| This example uses a single socket transport to invoke two services: | ||||
| 
 | ||||
| socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) | ||||
| transport := thrift.NewTFramedTransport(socket) | ||||
| protocol := thrift.NewTBinaryProtocolTransport(transport) | ||||
| 
 | ||||
| mp := thrift.NewTMultiplexedProtocol(protocol, "Calculator") | ||||
| service := Calculator.NewCalculatorClient(mp) | ||||
| 
 | ||||
| mp2 := thrift.NewTMultiplexedProtocol(protocol, "WeatherReport") | ||||
| service2 := WeatherReport.NewWeatherReportClient(mp2) | ||||
| 
 | ||||
| err := transport.Open() | ||||
| if err != nil { | ||||
| 	t.Fatal("Unable to open client socket", err) | ||||
| } | ||||
| 
 | ||||
| fmt.Println(service.Add(2,2)) | ||||
| fmt.Println(service2.GetTemperature()) | ||||
| */ | ||||
| 
 | ||||
| type TMultiplexedProtocol struct { | ||||
| 	TProtocol | ||||
| 	serviceName string | ||||
| } | ||||
| 
 | ||||
| const MULTIPLEXED_SEPARATOR = ":" | ||||
| 
 | ||||
| func NewTMultiplexedProtocol(protocol TProtocol, serviceName string) *TMultiplexedProtocol { | ||||
| 	return &TMultiplexedProtocol{ | ||||
| 		TProtocol:   protocol, | ||||
| 		serviceName: serviceName, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TMultiplexedProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { | ||||
| 	if typeId == CALL || typeId == ONEWAY { | ||||
| 		return t.TProtocol.WriteMessageBegin(ctx, t.serviceName+MULTIPLEXED_SEPARATOR+name, typeId, seqid) | ||||
| 	} else { | ||||
| 		return t.TProtocol.WriteMessageBegin(ctx, name, typeId, seqid) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| TMultiplexedProcessor is a TProcessor allowing | ||||
| a single TServer to provide multiple services. | ||||
| 
 | ||||
| To do so, you instantiate the processor and then register additional | ||||
| processors with it, as shown in the following example: | ||||
| 
 | ||||
| var processor = thrift.NewTMultiplexedProcessor() | ||||
| 
 | ||||
| firstProcessor := | ||||
| processor.RegisterProcessor("FirstService", firstProcessor) | ||||
| 
 | ||||
| processor.registerProcessor( | ||||
|   "Calculator", | ||||
|   Calculator.NewCalculatorProcessor(&CalculatorHandler{}), | ||||
| ) | ||||
| 
 | ||||
| processor.registerProcessor( | ||||
|   "WeatherReport", | ||||
|   WeatherReport.NewWeatherReportProcessor(&WeatherReportHandler{}), | ||||
| ) | ||||
| 
 | ||||
| serverTransport, err := thrift.NewTServerSocketTimeout(addr, TIMEOUT) | ||||
| if err != nil { | ||||
|   t.Fatal("Unable to create server socket", err) | ||||
| } | ||||
| server := thrift.NewTSimpleServer2(processor, serverTransport) | ||||
| server.Serve(); | ||||
| */ | ||||
| 
 | ||||
| type TMultiplexedProcessor struct { | ||||
| 	serviceProcessorMap map[string]TProcessor | ||||
| 	DefaultProcessor    TProcessor | ||||
| } | ||||
| 
 | ||||
| func NewTMultiplexedProcessor() *TMultiplexedProcessor { | ||||
| 	return &TMultiplexedProcessor{ | ||||
| 		serviceProcessorMap: make(map[string]TProcessor), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ProcessorMap returns a mapping of "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}" | ||||
| // to TProcessorFunction for any registered processors.  If there is also a | ||||
| // DefaultProcessor, the keys for the methods on that processor will simply be | ||||
| // "{FunctionName}".  If the TMultiplexedProcessor has both a DefaultProcessor and | ||||
| // other registered processors, then the keys will be a mix of both formats. | ||||
| // | ||||
| // The implementation differs with other TProcessors in that the map returned is | ||||
| // a new map, while most TProcessors just return their internal mapping directly. | ||||
| // This means that edits to the map returned by this implementation of ProcessorMap | ||||
| // will not affect the underlying mapping within the TMultiplexedProcessor. | ||||
| func (t *TMultiplexedProcessor) ProcessorMap() map[string]TProcessorFunction { | ||||
| 	processorFuncMap := make(map[string]TProcessorFunction) | ||||
| 	for name, processor := range t.serviceProcessorMap { | ||||
| 		for method, processorFunc := range processor.ProcessorMap() { | ||||
| 			processorFuncName := name + MULTIPLEXED_SEPARATOR + method | ||||
| 			processorFuncMap[processorFuncName] = processorFunc | ||||
| 		} | ||||
| 	} | ||||
| 	if t.DefaultProcessor != nil { | ||||
| 		for method, processorFunc := range t.DefaultProcessor.ProcessorMap() { | ||||
| 			processorFuncMap[method] = processorFunc | ||||
| 		} | ||||
| 	} | ||||
| 	return processorFuncMap | ||||
| } | ||||
| 
 | ||||
| // AddToProcessorMap updates the underlying TProcessor ProccessorMaps depending on | ||||
| // the format of "name". | ||||
| // | ||||
| // If "name" is in the format "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}", | ||||
| // then it sets the given TProcessorFunction on the inner TProcessor with the | ||||
| // ProcessorName component using the FunctionName component. | ||||
| // | ||||
| // If "name" is just in the format "{FunctionName}", that is to say there is no | ||||
| // MULTIPLEXED_SEPARATOR, and the TMultiplexedProcessor has a DefaultProcessor | ||||
| // configured, then it will set the given TProcessorFunction on the DefaultProcessor | ||||
| // using the given name. | ||||
| // | ||||
| // If there is not a TProcessor available for the given name, then this function | ||||
| // does nothing.  This can happen when there is no TProcessor registered for | ||||
| // the given ProcessorName or if all that is given is the FunctionName and there | ||||
| // is no DefaultProcessor set. | ||||
| func (t *TMultiplexedProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) { | ||||
| 	processorName, funcName, found := strings.Cut(name, MULTIPLEXED_SEPARATOR) | ||||
| 	if !found { | ||||
| 		if t.DefaultProcessor != nil { | ||||
| 			t.DefaultProcessor.AddToProcessorMap(processorName, processorFunc) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	if processor, ok := t.serviceProcessorMap[processorName]; ok { | ||||
| 		processor.AddToProcessorMap(funcName, processorFunc) | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // verify that TMultiplexedProcessor implements TProcessor | ||||
| var _ TProcessor = (*TMultiplexedProcessor)(nil) | ||||
| 
 | ||||
| func (t *TMultiplexedProcessor) RegisterDefault(processor TProcessor) { | ||||
| 	t.DefaultProcessor = processor | ||||
| } | ||||
| 
 | ||||
| func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProcessor) { | ||||
| 	if t.serviceProcessorMap == nil { | ||||
| 		t.serviceProcessorMap = make(map[string]TProcessor) | ||||
| 	} | ||||
| 	t.serviceProcessorMap[name] = processor | ||||
| } | ||||
| 
 | ||||
| func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { | ||||
| 	name, typeId, seqid, err := in.ReadMessageBegin(ctx) | ||||
| 	if err != nil { | ||||
| 		return false, NewTProtocolException(err) | ||||
| 	} | ||||
| 	if typeId != CALL && typeId != ONEWAY { | ||||
| 		return false, NewTProtocolException(fmt.Errorf("Unexpected message type %v", typeId)) | ||||
| 	} | ||||
| 	// extract the service name | ||||
| 	processorName, funcName, found := strings.Cut(name, MULTIPLEXED_SEPARATOR) | ||||
| 	if !found { | ||||
| 		if t.DefaultProcessor != nil { | ||||
| 			smb := NewStoredMessageProtocol(in, name, typeId, seqid) | ||||
| 			return t.DefaultProcessor.Process(ctx, smb, out) | ||||
| 		} | ||||
| 		return false, NewTProtocolException(fmt.Errorf( | ||||
| 			"Service name not found in message name: %s.  Did you forget to use a TMultiplexProtocol in your client?", | ||||
| 			name, | ||||
| 		)) | ||||
| 	} | ||||
| 	actualProcessor, ok := t.serviceProcessorMap[processorName] | ||||
| 	if !ok { | ||||
| 		return false, NewTProtocolException(fmt.Errorf( | ||||
| 			"Service name not found: %s.  Did you forget to call registerProcessor()?", | ||||
| 			processorName, | ||||
| 		)) | ||||
| 	} | ||||
| 	smb := NewStoredMessageProtocol(in, funcName, typeId, seqid) | ||||
| 	return actualProcessor.Process(ctx, smb, out) | ||||
| } | ||||
| 
 | ||||
| // Protocol that use stored message for ReadMessageBegin | ||||
| type storedMessageProtocol struct { | ||||
| 	TProtocol | ||||
| 	name   string | ||||
| 	typeId TMessageType | ||||
| 	seqid  int32 | ||||
| } | ||||
| 
 | ||||
| func NewStoredMessageProtocol(protocol TProtocol, name string, typeId TMessageType, seqid int32) *storedMessageProtocol { | ||||
| 	return &storedMessageProtocol{protocol, name, typeId, seqid} | ||||
| } | ||||
| 
 | ||||
| func (s *storedMessageProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) { | ||||
| 	return s.name, s.typeId, s.seqid, nil | ||||
| } | ||||
|  | @ -1,164 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"math" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| type Numeric interface { | ||||
| 	Int64() int64 | ||||
| 	Int32() int32 | ||||
| 	Int16() int16 | ||||
| 	Byte() byte | ||||
| 	Int() int | ||||
| 	Float64() float64 | ||||
| 	Float32() float32 | ||||
| 	String() string | ||||
| 	isNull() bool | ||||
| } | ||||
| 
 | ||||
| type numeric struct { | ||||
| 	iValue int64 | ||||
| 	dValue float64 | ||||
| 	sValue string | ||||
| 	isNil  bool | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	INFINITY          Numeric | ||||
| 	NEGATIVE_INFINITY Numeric | ||||
| 	NAN               Numeric | ||||
| 	ZERO              Numeric | ||||
| 	NUMERIC_NULL      Numeric | ||||
| ) | ||||
| 
 | ||||
| func NewNumericFromDouble(dValue float64) Numeric { | ||||
| 	if math.IsInf(dValue, 1) { | ||||
| 		return INFINITY | ||||
| 	} | ||||
| 	if math.IsInf(dValue, -1) { | ||||
| 		return NEGATIVE_INFINITY | ||||
| 	} | ||||
| 	if math.IsNaN(dValue) { | ||||
| 		return NAN | ||||
| 	} | ||||
| 	iValue := int64(dValue) | ||||
| 	sValue := strconv.FormatFloat(dValue, 'g', 10, 64) | ||||
| 	isNil := false | ||||
| 	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} | ||||
| } | ||||
| 
 | ||||
| func NewNumericFromI64(iValue int64) Numeric { | ||||
| 	dValue := float64(iValue) | ||||
| 	sValue := strconv.FormatInt(iValue, 10) | ||||
| 	isNil := false | ||||
| 	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} | ||||
| } | ||||
| 
 | ||||
| func NewNumericFromI32(iValue int32) Numeric { | ||||
| 	dValue := float64(iValue) | ||||
| 	sValue := strconv.FormatInt(int64(iValue), 10) | ||||
| 	isNil := false | ||||
| 	return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} | ||||
| } | ||||
| 
 | ||||
| func NewNumericFromString(sValue string) Numeric { | ||||
| 	if sValue == INFINITY.String() { | ||||
| 		return INFINITY | ||||
| 	} | ||||
| 	if sValue == NEGATIVE_INFINITY.String() { | ||||
| 		return NEGATIVE_INFINITY | ||||
| 	} | ||||
| 	if sValue == NAN.String() { | ||||
| 		return NAN | ||||
| 	} | ||||
| 	iValue, _ := strconv.ParseInt(sValue, 10, 64) | ||||
| 	dValue, _ := strconv.ParseFloat(sValue, 64) | ||||
| 	isNil := len(sValue) == 0 | ||||
| 	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} | ||||
| } | ||||
| 
 | ||||
| func NewNumericFromJSONString(sValue string, isNull bool) Numeric { | ||||
| 	if isNull { | ||||
| 		return NewNullNumeric() | ||||
| 	} | ||||
| 	if sValue == JSON_INFINITY { | ||||
| 		return INFINITY | ||||
| 	} | ||||
| 	if sValue == JSON_NEGATIVE_INFINITY { | ||||
| 		return NEGATIVE_INFINITY | ||||
| 	} | ||||
| 	if sValue == JSON_NAN { | ||||
| 		return NAN | ||||
| 	} | ||||
| 	iValue, _ := strconv.ParseInt(sValue, 10, 64) | ||||
| 	dValue, _ := strconv.ParseFloat(sValue, 64) | ||||
| 	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull} | ||||
| } | ||||
| 
 | ||||
| func NewNullNumeric() Numeric { | ||||
| 	return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true} | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Int64() int64 { | ||||
| 	return p.iValue | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Int32() int32 { | ||||
| 	return int32(p.iValue) | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Int16() int16 { | ||||
| 	return int16(p.iValue) | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Byte() byte { | ||||
| 	return byte(p.iValue) | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Int() int { | ||||
| 	return int(p.iValue) | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Float64() float64 { | ||||
| 	return p.dValue | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) Float32() float32 { | ||||
| 	return float32(p.dValue) | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) String() string { | ||||
| 	return p.sValue | ||||
| } | ||||
| 
 | ||||
| func (p *numeric) isNull() bool { | ||||
| 	return p.isNil | ||||
| } | ||||
| 
 | ||||
| func init() { | ||||
| 	INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false} | ||||
| 	NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false} | ||||
| 	NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false} | ||||
| 	ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false} | ||||
| 	NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true} | ||||
| } | ||||
|  | @ -1,52 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // This file is home to helpers that convert from various base types to | ||||
| // respective pointer types. This is necessary because Go does not permit | ||||
| // references to constants, nor can a pointer type to base type be allocated | ||||
| // and initialized in a single expression. | ||||
| // | ||||
| // E.g., this is not allowed: | ||||
| // | ||||
| //    var ip *int = &5 | ||||
| // | ||||
| // But this *is* allowed: | ||||
| // | ||||
| //    func IntPtr(i int) *int { return &i } | ||||
| //    var ip *int = IntPtr(5) | ||||
| // | ||||
| // Since pointers to base types are commonplace as [optional] fields in | ||||
| // exported thrift structs, we factor such helpers here. | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
| func Float32Ptr(v float32) *float32 { return &v } | ||||
| func Float64Ptr(v float64) *float64 { return &v } | ||||
| func IntPtr(v int) *int             { return &v } | ||||
| func Int8Ptr(v int8) *int8          { return &v } | ||||
| func Int16Ptr(v int16) *int16       { return &v } | ||||
| func Int32Ptr(v int32) *int32       { return &v } | ||||
| func Int64Ptr(v int64) *int64       { return &v } | ||||
| func StringPtr(v string) *string    { return &v } | ||||
| func Uint32Ptr(v uint32) *uint32    { return &v } | ||||
| func Uint64Ptr(v uint64) *uint64    { return &v } | ||||
| func BoolPtr(v bool) *bool          { return &v } | ||||
| func ByteSlicePtr(v []byte) *[]byte { return &v } | ||||
|  | @ -1,80 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import "context" | ||||
| 
 | ||||
| // A processor is a generic object which operates upon an input stream and | ||||
| // writes to some output stream. | ||||
| type TProcessor interface { | ||||
| 	Process(ctx context.Context, in, out TProtocol) (bool, TException) | ||||
| 
 | ||||
| 	// ProcessorMap returns a map of thrift method names to TProcessorFunctions. | ||||
| 	ProcessorMap() map[string]TProcessorFunction | ||||
| 
 | ||||
| 	// AddToProcessorMap adds the given TProcessorFunction to the internal | ||||
| 	// processor map at the given key. | ||||
| 	// | ||||
| 	// If one is already set at the given key, it will be replaced with the new | ||||
| 	// TProcessorFunction. | ||||
| 	AddToProcessorMap(string, TProcessorFunction) | ||||
| } | ||||
| 
 | ||||
| type TProcessorFunction interface { | ||||
| 	Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) | ||||
| } | ||||
| 
 | ||||
| // The default processor factory just returns a singleton | ||||
| // instance. | ||||
| type TProcessorFactory interface { | ||||
| 	GetProcessor(trans TTransport) TProcessor | ||||
| } | ||||
| 
 | ||||
| type tProcessorFactory struct { | ||||
| 	processor TProcessor | ||||
| } | ||||
| 
 | ||||
| func NewTProcessorFactory(p TProcessor) TProcessorFactory { | ||||
| 	return &tProcessorFactory{processor: p} | ||||
| } | ||||
| 
 | ||||
| func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor { | ||||
| 	return p.processor | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * The default processor factory just returns a singleton | ||||
|  * instance. | ||||
|  */ | ||||
| type TProcessorFunctionFactory interface { | ||||
| 	GetProcessorFunction(trans TTransport) TProcessorFunction | ||||
| } | ||||
| 
 | ||||
| type tProcessorFunctionFactory struct { | ||||
| 	processor TProcessorFunction | ||||
| } | ||||
| 
 | ||||
| func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory { | ||||
| 	return &tProcessorFunctionFactory{processor: p} | ||||
| } | ||||
| 
 | ||||
| func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction { | ||||
| 	return p.processor | ||||
| } | ||||
|  | @ -1,177 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	VERSION_MASK = 0xffff0000 | ||||
| 	VERSION_1    = 0x80010000 | ||||
| ) | ||||
| 
 | ||||
| type TProtocol interface { | ||||
| 	WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error | ||||
| 	WriteMessageEnd(ctx context.Context) error | ||||
| 	WriteStructBegin(ctx context.Context, name string) error | ||||
| 	WriteStructEnd(ctx context.Context) error | ||||
| 	WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error | ||||
| 	WriteFieldEnd(ctx context.Context) error | ||||
| 	WriteFieldStop(ctx context.Context) error | ||||
| 	WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error | ||||
| 	WriteMapEnd(ctx context.Context) error | ||||
| 	WriteListBegin(ctx context.Context, elemType TType, size int) error | ||||
| 	WriteListEnd(ctx context.Context) error | ||||
| 	WriteSetBegin(ctx context.Context, elemType TType, size int) error | ||||
| 	WriteSetEnd(ctx context.Context) error | ||||
| 	WriteBool(ctx context.Context, value bool) error | ||||
| 	WriteByte(ctx context.Context, value int8) error | ||||
| 	WriteI16(ctx context.Context, value int16) error | ||||
| 	WriteI32(ctx context.Context, value int32) error | ||||
| 	WriteI64(ctx context.Context, value int64) error | ||||
| 	WriteDouble(ctx context.Context, value float64) error | ||||
| 	WriteString(ctx context.Context, value string) error | ||||
| 	WriteBinary(ctx context.Context, value []byte) error | ||||
| 
 | ||||
| 	ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) | ||||
| 	ReadMessageEnd(ctx context.Context) error | ||||
| 	ReadStructBegin(ctx context.Context) (name string, err error) | ||||
| 	ReadStructEnd(ctx context.Context) error | ||||
| 	ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) | ||||
| 	ReadFieldEnd(ctx context.Context) error | ||||
| 	ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) | ||||
| 	ReadMapEnd(ctx context.Context) error | ||||
| 	ReadListBegin(ctx context.Context) (elemType TType, size int, err error) | ||||
| 	ReadListEnd(ctx context.Context) error | ||||
| 	ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) | ||||
| 	ReadSetEnd(ctx context.Context) error | ||||
| 	ReadBool(ctx context.Context) (value bool, err error) | ||||
| 	ReadByte(ctx context.Context) (value int8, err error) | ||||
| 	ReadI16(ctx context.Context) (value int16, err error) | ||||
| 	ReadI32(ctx context.Context) (value int32, err error) | ||||
| 	ReadI64(ctx context.Context) (value int64, err error) | ||||
| 	ReadDouble(ctx context.Context) (value float64, err error) | ||||
| 	ReadString(ctx context.Context) (value string, err error) | ||||
| 	ReadBinary(ctx context.Context) (value []byte, err error) | ||||
| 
 | ||||
| 	Skip(ctx context.Context, fieldType TType) (err error) | ||||
| 	Flush(ctx context.Context) (err error) | ||||
| 
 | ||||
| 	Transport() TTransport | ||||
| } | ||||
| 
 | ||||
| // The maximum recursive depth the skip() function will traverse | ||||
| const DEFAULT_RECURSION_DEPTH = 64 | ||||
| 
 | ||||
| // Skips over the next data element from the provided input TProtocol object. | ||||
| func SkipDefaultDepth(ctx context.Context, prot TProtocol, typeId TType) (err error) { | ||||
| 	return Skip(ctx, prot, typeId, DEFAULT_RECURSION_DEPTH) | ||||
| } | ||||
| 
 | ||||
| // Skips over the next data element from the provided input TProtocol object. | ||||
| func Skip(ctx context.Context, self TProtocol, fieldType TType, maxDepth int) (err error) { | ||||
| 
 | ||||
| 	if maxDepth <= 0 { | ||||
| 		return NewTProtocolExceptionWithType(DEPTH_LIMIT, errors.New("Depth limit exceeded")) | ||||
| 	} | ||||
| 
 | ||||
| 	switch fieldType { | ||||
| 	case BOOL: | ||||
| 		_, err = self.ReadBool(ctx) | ||||
| 		return | ||||
| 	case BYTE: | ||||
| 		_, err = self.ReadByte(ctx) | ||||
| 		return | ||||
| 	case I16: | ||||
| 		_, err = self.ReadI16(ctx) | ||||
| 		return | ||||
| 	case I32: | ||||
| 		_, err = self.ReadI32(ctx) | ||||
| 		return | ||||
| 	case I64: | ||||
| 		_, err = self.ReadI64(ctx) | ||||
| 		return | ||||
| 	case DOUBLE: | ||||
| 		_, err = self.ReadDouble(ctx) | ||||
| 		return | ||||
| 	case STRING: | ||||
| 		_, err = self.ReadString(ctx) | ||||
| 		return | ||||
| 	case STRUCT: | ||||
| 		if _, err = self.ReadStructBegin(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for { | ||||
| 			_, typeId, _, _ := self.ReadFieldBegin(ctx) | ||||
| 			if typeId == STOP { | ||||
| 				break | ||||
| 			} | ||||
| 			err := Skip(ctx, self, typeId, maxDepth-1) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			self.ReadFieldEnd(ctx) | ||||
| 		} | ||||
| 		return self.ReadStructEnd(ctx) | ||||
| 	case MAP: | ||||
| 		keyType, valueType, size, err := self.ReadMapBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for i := 0; i < size; i++ { | ||||
| 			err := Skip(ctx, self, keyType, maxDepth-1) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			self.Skip(ctx, valueType) | ||||
| 		} | ||||
| 		return self.ReadMapEnd(ctx) | ||||
| 	case SET: | ||||
| 		elemType, size, err := self.ReadSetBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for i := 0; i < size; i++ { | ||||
| 			err := Skip(ctx, self, elemType, maxDepth-1) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return self.ReadSetEnd(ctx) | ||||
| 	case LIST: | ||||
| 		elemType, size, err := self.ReadListBegin(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for i := 0; i < size; i++ { | ||||
| 			err := Skip(ctx, self, elemType, maxDepth-1) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return self.ReadListEnd(ctx) | ||||
| 	default: | ||||
| 		return NewTProtocolExceptionWithType(INVALID_DATA, errors.New(fmt.Sprintf("Unknown data type %d", fieldType))) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,104 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // Thrift Protocol exception | ||||
| type TProtocolException interface { | ||||
| 	TException | ||||
| 	TypeId() int | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	UNKNOWN_PROTOCOL_EXCEPTION = 0 | ||||
| 	INVALID_DATA               = 1 | ||||
| 	NEGATIVE_SIZE              = 2 | ||||
| 	SIZE_LIMIT                 = 3 | ||||
| 	BAD_VERSION                = 4 | ||||
| 	NOT_IMPLEMENTED            = 5 | ||||
| 	DEPTH_LIMIT                = 6 | ||||
| ) | ||||
| 
 | ||||
| type tProtocolException struct { | ||||
| 	typeId int | ||||
| 	err    error | ||||
| 	msg    string | ||||
| } | ||||
| 
 | ||||
| var _ TProtocolException = (*tProtocolException)(nil) | ||||
| 
 | ||||
| func (tProtocolException) TExceptionType() TExceptionType { | ||||
| 	return TExceptionTypeProtocol | ||||
| } | ||||
| 
 | ||||
| func (p *tProtocolException) TypeId() int { | ||||
| 	return p.typeId | ||||
| } | ||||
| 
 | ||||
| func (p *tProtocolException) String() string { | ||||
| 	return p.msg | ||||
| } | ||||
| 
 | ||||
| func (p *tProtocolException) Error() string { | ||||
| 	return p.msg | ||||
| } | ||||
| 
 | ||||
| func (p *tProtocolException) Unwrap() error { | ||||
| 	return p.err | ||||
| } | ||||
| 
 | ||||
| func NewTProtocolException(err error) TProtocolException { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if e, ok := err.(TProtocolException); ok { | ||||
| 		return e | ||||
| 	} | ||||
| 
 | ||||
| 	if errors.As(err, new(base64.CorruptInputError)) { | ||||
| 		return NewTProtocolExceptionWithType(INVALID_DATA, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return NewTProtocolExceptionWithType(UNKNOWN_PROTOCOL_EXCEPTION, err) | ||||
| } | ||||
| 
 | ||||
| func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &tProtocolException{ | ||||
| 		typeId: errType, | ||||
| 		err:    err, | ||||
| 		msg:    err.Error(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func prependTProtocolException(prepend string, err TProtocolException) TProtocolException { | ||||
| 	return &tProtocolException{ | ||||
| 		typeId: err.TypeId(), | ||||
| 		err:    err, | ||||
| 		msg:    prepend + err.Error(), | ||||
| 	} | ||||
| } | ||||
|  | @ -1,25 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| // Factory interface for constructing protocol instances. | ||||
| type TProtocolFactory interface { | ||||
| 	GetProtocol(trans TTransport) TProtocol | ||||
| } | ||||
|  | @ -1,94 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| // See https://godoc.org/context#WithValue on why do we need the unexported typedefs. | ||||
| type responseHelperKey struct{} | ||||
| 
 | ||||
| // TResponseHelper defines a object with a set of helper functions that can be | ||||
| // retrieved from the context object passed into server handler functions. | ||||
| // | ||||
| // Use GetResponseHelper to retrieve the injected TResponseHelper implementation | ||||
| // from the context object. | ||||
| // | ||||
| // The zero value of TResponseHelper is valid with all helper functions being | ||||
| // no-op. | ||||
| type TResponseHelper struct { | ||||
| 	// THeader related functions | ||||
| 	*THeaderResponseHelper | ||||
| } | ||||
| 
 | ||||
| // THeaderResponseHelper defines THeader related TResponseHelper functions. | ||||
| // | ||||
| // The zero value of *THeaderResponseHelper is valid with all helper functions | ||||
| // being no-op. | ||||
| type THeaderResponseHelper struct { | ||||
| 	proto *THeaderProtocol | ||||
| } | ||||
| 
 | ||||
| // NewTHeaderResponseHelper creates a new THeaderResponseHelper from the | ||||
| // underlying TProtocol. | ||||
| func NewTHeaderResponseHelper(proto TProtocol) *THeaderResponseHelper { | ||||
| 	if hp, ok := proto.(*THeaderProtocol); ok { | ||||
| 		return &THeaderResponseHelper{ | ||||
| 			proto: hp, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SetHeader sets a response header. | ||||
| // | ||||
| // It's no-op if the underlying protocol/transport does not support THeader. | ||||
| func (h *THeaderResponseHelper) SetHeader(key, value string) { | ||||
| 	if h != nil && h.proto != nil { | ||||
| 		h.proto.SetWriteHeader(key, value) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ClearHeaders clears all the response headers previously set. | ||||
| // | ||||
| // It's no-op if the underlying protocol/transport does not support THeader. | ||||
| func (h *THeaderResponseHelper) ClearHeaders() { | ||||
| 	if h != nil && h.proto != nil { | ||||
| 		h.proto.ClearWriteHeaders() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GetResponseHelper retrieves the TResponseHelper implementation injected into | ||||
| // the context object. | ||||
| // | ||||
| // If no helper was found in the context object, a nop helper with ok == false | ||||
| // will be returned. | ||||
| func GetResponseHelper(ctx context.Context) (helper TResponseHelper, ok bool) { | ||||
| 	if v := ctx.Value(responseHelperKey{}); v != nil { | ||||
| 		helper, ok = v.(TResponseHelper) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // SetResponseHelper injects TResponseHelper into the context object. | ||||
| func SetResponseHelper(ctx context.Context, helper TResponseHelper) context.Context { | ||||
| 	return context.WithValue(ctx, responseHelperKey{}, helper) | ||||
| } | ||||
|  | @ -1,71 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| type RichTransport struct { | ||||
| 	TTransport | ||||
| } | ||||
| 
 | ||||
| // Wraps Transport to provide TRichTransport interface | ||||
| func NewTRichTransport(trans TTransport) *RichTransport { | ||||
| 	return &RichTransport{trans} | ||||
| } | ||||
| 
 | ||||
| func (r *RichTransport) ReadByte() (c byte, err error) { | ||||
| 	return readByte(r.TTransport) | ||||
| } | ||||
| 
 | ||||
| func (r *RichTransport) WriteByte(c byte) error { | ||||
| 	return writeByte(r.TTransport, c) | ||||
| } | ||||
| 
 | ||||
| func (r *RichTransport) WriteString(s string) (n int, err error) { | ||||
| 	return r.Write([]byte(s)) | ||||
| } | ||||
| 
 | ||||
| func (r *RichTransport) RemainingBytes() (num_bytes uint64) { | ||||
| 	return r.TTransport.RemainingBytes() | ||||
| } | ||||
| 
 | ||||
| func readByte(r io.Reader) (c byte, err error) { | ||||
| 	v := [1]byte{0} | ||||
| 	n, err := r.Read(v[0:1]) | ||||
| 	if n > 0 && (err == nil || errors.Is(err, io.EOF)) { | ||||
| 		return v[0], nil | ||||
| 	} | ||||
| 	if n > 0 && err != nil { | ||||
| 		return v[0], err | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return v[0], nil | ||||
| } | ||||
| 
 | ||||
| func writeByte(w io.Writer, c byte) error { | ||||
| 	v := [1]byte{c} | ||||
| 	_, err := w.Write(v[0:1]) | ||||
| 	return err | ||||
| } | ||||
|  | @ -1,136 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| type TSerializer struct { | ||||
| 	Transport *TMemoryBuffer | ||||
| 	Protocol  TProtocol | ||||
| } | ||||
| 
 | ||||
| type TStruct interface { | ||||
| 	Write(ctx context.Context, p TProtocol) error | ||||
| 	Read(ctx context.Context, p TProtocol) error | ||||
| } | ||||
| 
 | ||||
| func NewTSerializer() *TSerializer { | ||||
| 	transport := NewTMemoryBufferLen(1024) | ||||
| 	protocol := NewTBinaryProtocolTransport(transport) | ||||
| 
 | ||||
| 	return &TSerializer{ | ||||
| 		Transport: transport, | ||||
| 		Protocol:  protocol, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TSerializer) WriteString(ctx context.Context, msg TStruct) (s string, err error) { | ||||
| 	t.Transport.Reset() | ||||
| 
 | ||||
| 	if err = msg.Write(ctx, t.Protocol); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err = t.Protocol.Flush(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err = t.Transport.Flush(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	return t.Transport.String(), nil | ||||
| } | ||||
| 
 | ||||
| func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err error) { | ||||
| 	t.Transport.Reset() | ||||
| 
 | ||||
| 	if err = msg.Write(ctx, t.Protocol); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err = t.Protocol.Flush(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err = t.Transport.Flush(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	b = append(b, t.Transport.Bytes()...) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // TSerializerPool is the thread-safe version of TSerializer, it uses resource | ||||
| // pool of TSerializer under the hood. | ||||
| // | ||||
| // It must be initialized with either NewTSerializerPool or | ||||
| // NewTSerializerPoolSizeFactory. | ||||
| type TSerializerPool struct { | ||||
| 	pool sync.Pool | ||||
| } | ||||
| 
 | ||||
| // NewTSerializerPool creates a new TSerializerPool. | ||||
| // | ||||
| // NewTSerializer can be used as the arg here. | ||||
| func NewTSerializerPool(f func() *TSerializer) *TSerializerPool { | ||||
| 	return &TSerializerPool{ | ||||
| 		pool: sync.Pool{ | ||||
| 			New: func() interface{} { | ||||
| 				return f() | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewTSerializerPoolSizeFactory creates a new TSerializerPool with the given | ||||
| // size and protocol factory. | ||||
| // | ||||
| // Note that the size is not the limit. The TMemoryBuffer underneath can grow | ||||
| // larger than that. It just dictates the initial size. | ||||
| func NewTSerializerPoolSizeFactory(size int, factory TProtocolFactory) *TSerializerPool { | ||||
| 	return &TSerializerPool{ | ||||
| 		pool: sync.Pool{ | ||||
| 			New: func() interface{} { | ||||
| 				transport := NewTMemoryBufferLen(size) | ||||
| 				protocol := factory.GetProtocol(transport) | ||||
| 
 | ||||
| 				return &TSerializer{ | ||||
| 					Transport: transport, | ||||
| 					Protocol:  protocol, | ||||
| 				} | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *TSerializerPool) WriteString(ctx context.Context, msg TStruct) (string, error) { | ||||
| 	s := t.pool.Get().(*TSerializer) | ||||
| 	defer t.pool.Put(s) | ||||
| 	return s.WriteString(ctx, msg) | ||||
| } | ||||
| 
 | ||||
| func (t *TSerializerPool) Write(ctx context.Context, msg TStruct) ([]byte, error) { | ||||
| 	s := t.pool.Get().(*TSerializer) | ||||
| 	defer t.pool.Put(s) | ||||
| 	return s.Write(ctx, msg) | ||||
| } | ||||
|  | @ -1,35 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| type TServer interface { | ||||
| 	ProcessorFactory() TProcessorFactory | ||||
| 	ServerTransport() TServerTransport | ||||
| 	InputTransportFactory() TTransportFactory | ||||
| 	OutputTransportFactory() TTransportFactory | ||||
| 	InputProtocolFactory() TProtocolFactory | ||||
| 	OutputProtocolFactory() TProtocolFactory | ||||
| 
 | ||||
| 	// Starts the server | ||||
| 	Serve() error | ||||
| 	// Stops the server. This is optional on a per-implementation basis. Not | ||||
| 	// all servers are required to be cleanly stoppable. | ||||
| 	Stop() error | ||||
| } | ||||
|  | @ -1,137 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type TServerSocket struct { | ||||
| 	listener      net.Listener | ||||
| 	addr          net.Addr | ||||
| 	clientTimeout time.Duration | ||||
| 
 | ||||
| 	// Protects the interrupted value to make it thread safe. | ||||
| 	mu          sync.RWMutex | ||||
| 	interrupted bool | ||||
| } | ||||
| 
 | ||||
| func NewTServerSocket(listenAddr string) (*TServerSocket, error) { | ||||
| 	return NewTServerSocketTimeout(listenAddr, 0) | ||||
| } | ||||
| 
 | ||||
| func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) { | ||||
| 	addr, err := net.ResolveTCPAddr("tcp", listenAddr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil | ||||
| } | ||||
| 
 | ||||
| // Creates a TServerSocket from a net.Addr | ||||
| func NewTServerSocketFromAddrTimeout(addr net.Addr, clientTimeout time.Duration) *TServerSocket { | ||||
| 	return &TServerSocket{addr: addr, clientTimeout: clientTimeout} | ||||
| } | ||||
| 
 | ||||
| func (p *TServerSocket) Listen() error { | ||||
| 	p.mu.Lock() | ||||
| 	defer p.mu.Unlock() | ||||
| 	if p.IsListening() { | ||||
| 		return nil | ||||
| 	} | ||||
| 	l, err := net.Listen(p.addr.Network(), p.addr.String()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.listener = l | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TServerSocket) Accept() (TTransport, error) { | ||||
| 	p.mu.RLock() | ||||
| 	interrupted := p.interrupted | ||||
| 	p.mu.RUnlock() | ||||
| 
 | ||||
| 	if interrupted { | ||||
| 		return nil, errTransportInterrupted | ||||
| 	} | ||||
| 
 | ||||
| 	p.mu.Lock() | ||||
| 	listener := p.listener | ||||
| 	p.mu.Unlock() | ||||
| 	if listener == nil { | ||||
| 		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") | ||||
| 	} | ||||
| 
 | ||||
| 	conn, err := listener.Accept() | ||||
| 	if err != nil { | ||||
| 		return nil, NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil | ||||
| } | ||||
| 
 | ||||
| // Checks whether the socket is listening. | ||||
| func (p *TServerSocket) IsListening() bool { | ||||
| 	return p.listener != nil | ||||
| } | ||||
| 
 | ||||
| // Connects the socket, creating a new socket object if necessary. | ||||
| func (p *TServerSocket) Open() error { | ||||
| 	p.mu.Lock() | ||||
| 	defer p.mu.Unlock() | ||||
| 	if p.IsListening() { | ||||
| 		return NewTTransportException(ALREADY_OPEN, "Server socket already open") | ||||
| 	} | ||||
| 	if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil { | ||||
| 		return err | ||||
| 	} else { | ||||
| 		p.listener = l | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TServerSocket) Addr() net.Addr { | ||||
| 	if p.listener != nil { | ||||
| 		return p.listener.Addr() | ||||
| 	} | ||||
| 	return p.addr | ||||
| } | ||||
| 
 | ||||
| func (p *TServerSocket) Close() error { | ||||
| 	var err error | ||||
| 	p.mu.Lock() | ||||
| 	if p.IsListening() { | ||||
| 		err = p.listener.Close() | ||||
| 		p.listener = nil | ||||
| 	} | ||||
| 	p.mu.Unlock() | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *TServerSocket) Interrupt() error { | ||||
| 	p.mu.Lock() | ||||
| 	p.interrupted = true | ||||
| 	p.mu.Unlock() | ||||
| 	p.Close() | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,34 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| // Server transport. Object which provides client transports. | ||||
| type TServerTransport interface { | ||||
| 	Listen() error | ||||
| 	Accept() (TTransport, error) | ||||
| 	Close() error | ||||
| 
 | ||||
| 	// Optional method implementation. This signals to the server transport | ||||
| 	// that it should break out of any accept() or listen() that it is currently | ||||
| 	// blocked on. This method, if implemented, MUST be thread safe, as it may | ||||
| 	// be called from a different thread context than the other TServerTransport | ||||
| 	// methods. | ||||
| 	Interrupt() error | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,332 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // ErrAbandonRequest is a special error server handler implementations can | ||||
| // return to indicate that the request has been abandoned. | ||||
| // | ||||
| // TSimpleServer will check for this error, and close the client connection | ||||
| // instead of writing the response/error back to the client. | ||||
| // | ||||
| // It shall only be used when the server handler implementation know that the | ||||
| // client already abandoned the request (by checking that the passed in context | ||||
| // is already canceled, for example). | ||||
| var ErrAbandonRequest = errors.New("request abandoned") | ||||
| 
 | ||||
| // ServerConnectivityCheckInterval defines the ticker interval used by | ||||
| // connectivity check in thrift compiled TProcessorFunc implementations. | ||||
| // | ||||
| // It's defined as a variable instead of constant, so that thrift server | ||||
| // implementations can change its value to control the behavior. | ||||
| // | ||||
| // If it's changed to <=0, the feature will be disabled. | ||||
| var ServerConnectivityCheckInterval = time.Millisecond * 5 | ||||
| 
 | ||||
| /* | ||||
|  * This is not a typical TSimpleServer as it is not blocked after accept a socket. | ||||
|  * It is more like a TThreadedServer that can handle different connections in different goroutines. | ||||
|  * This will work if golang user implements a conn-pool like thing in client side. | ||||
|  */ | ||||
| type TSimpleServer struct { | ||||
| 	closed int32 | ||||
| 	wg     sync.WaitGroup | ||||
| 	mu     sync.Mutex | ||||
| 
 | ||||
| 	processorFactory       TProcessorFactory | ||||
| 	serverTransport        TServerTransport | ||||
| 	inputTransportFactory  TTransportFactory | ||||
| 	outputTransportFactory TTransportFactory | ||||
| 	inputProtocolFactory   TProtocolFactory | ||||
| 	outputProtocolFactory  TProtocolFactory | ||||
| 
 | ||||
| 	// Headers to auto forward in THeaderProtocol | ||||
| 	forwardHeaders []string | ||||
| 
 | ||||
| 	logger Logger | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { | ||||
| 	return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport) | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { | ||||
| 	return NewTSimpleServerFactory4(NewTProcessorFactory(processor), | ||||
| 		serverTransport, | ||||
| 		transportFactory, | ||||
| 		protocolFactory, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { | ||||
| 	return NewTSimpleServerFactory6(NewTProcessorFactory(processor), | ||||
| 		serverTransport, | ||||
| 		inputTransportFactory, | ||||
| 		outputTransportFactory, | ||||
| 		inputProtocolFactory, | ||||
| 		outputProtocolFactory, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer { | ||||
| 	return NewTSimpleServerFactory6(processorFactory, | ||||
| 		serverTransport, | ||||
| 		NewTTransportFactory(), | ||||
| 		NewTTransportFactory(), | ||||
| 		NewTBinaryProtocolFactoryDefault(), | ||||
| 		NewTBinaryProtocolFactoryDefault(), | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { | ||||
| 	return NewTSimpleServerFactory6(processorFactory, | ||||
| 		serverTransport, | ||||
| 		transportFactory, | ||||
| 		transportFactory, | ||||
| 		protocolFactory, | ||||
| 		protocolFactory, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { | ||||
| 	return &TSimpleServer{ | ||||
| 		processorFactory:       processorFactory, | ||||
| 		serverTransport:        serverTransport, | ||||
| 		inputTransportFactory:  inputTransportFactory, | ||||
| 		outputTransportFactory: outputTransportFactory, | ||||
| 		inputProtocolFactory:   inputProtocolFactory, | ||||
| 		outputProtocolFactory:  outputProtocolFactory, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) ProcessorFactory() TProcessorFactory { | ||||
| 	return p.processorFactory | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) ServerTransport() TServerTransport { | ||||
| 	return p.serverTransport | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) InputTransportFactory() TTransportFactory { | ||||
| 	return p.inputTransportFactory | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) OutputTransportFactory() TTransportFactory { | ||||
| 	return p.outputTransportFactory | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory { | ||||
| 	return p.inputProtocolFactory | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory { | ||||
| 	return p.outputProtocolFactory | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) Listen() error { | ||||
| 	return p.serverTransport.Listen() | ||||
| } | ||||
| 
 | ||||
| // SetForwardHeaders sets the list of header keys that will be auto forwarded | ||||
| // while using THeaderProtocol. | ||||
| // | ||||
| // "forward" means that when the server is also a client to other upstream | ||||
| // thrift servers, the context object user gets in the processor functions will | ||||
| // have both read and write headers set, with write headers being forwarded. | ||||
| // Users can always override the write headers by calling SetWriteHeaderList | ||||
| // before calling thrift client functions. | ||||
| func (p *TSimpleServer) SetForwardHeaders(headers []string) { | ||||
| 	size := len(headers) | ||||
| 	if size == 0 { | ||||
| 		p.forwardHeaders = nil | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	keys := make([]string, size) | ||||
| 	copy(keys, headers) | ||||
| 	p.forwardHeaders = keys | ||||
| } | ||||
| 
 | ||||
| // SetLogger sets the logger used by this TSimpleServer. | ||||
| // | ||||
| // If no logger was set before Serve is called, a default logger using standard | ||||
| // log library will be used. | ||||
| func (p *TSimpleServer) SetLogger(logger Logger) { | ||||
| 	p.logger = logger | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) innerAccept() (int32, error) { | ||||
| 	client, err := p.serverTransport.Accept() | ||||
| 	p.mu.Lock() | ||||
| 	defer p.mu.Unlock() | ||||
| 	closed := atomic.LoadInt32(&p.closed) | ||||
| 	if closed != 0 { | ||||
| 		return closed, nil | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	if client != nil { | ||||
| 		p.wg.Add(1) | ||||
| 		go func() { | ||||
| 			defer p.wg.Done() | ||||
| 			if err := p.processRequests(client); err != nil { | ||||
| 				p.logger(fmt.Sprintf("error processing request: %v", err)) | ||||
| 			} | ||||
| 		}() | ||||
| 	} | ||||
| 	return 0, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) AcceptLoop() error { | ||||
| 	for { | ||||
| 		closed, err := p.innerAccept() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if closed != 0 { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) Serve() error { | ||||
| 	p.logger = fallbackLogger(p.logger) | ||||
| 
 | ||||
| 	err := p.Listen() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.AcceptLoop() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) Stop() error { | ||||
| 	p.mu.Lock() | ||||
| 	defer p.mu.Unlock() | ||||
| 	if atomic.LoadInt32(&p.closed) != 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	atomic.StoreInt32(&p.closed, 1) | ||||
| 	p.serverTransport.Interrupt() | ||||
| 	p.wg.Wait() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // If err is actually EOF, return nil, otherwise return err as-is. | ||||
| func treatEOFErrorsAsNil(err error) error { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if errors.Is(err, io.EOF) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	var te TTransportException | ||||
| 	if errors.As(err, &te) && te.TypeId() == END_OF_FILE { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *TSimpleServer) processRequests(client TTransport) (err error) { | ||||
| 	defer func() { | ||||
| 		err = treatEOFErrorsAsNil(err) | ||||
| 	}() | ||||
| 
 | ||||
| 	processor := p.processorFactory.GetProcessor(client) | ||||
| 	inputTransport, err := p.inputTransportFactory.GetTransport(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) | ||||
| 	var outputTransport TTransport | ||||
| 	var outputProtocol TProtocol | ||||
| 
 | ||||
| 	// for THeaderProtocol, we must use the same protocol instance for | ||||
| 	// input and output so that the response is in the same dialect that | ||||
| 	// the server detected the request was in. | ||||
| 	headerProtocol, ok := inputProtocol.(*THeaderProtocol) | ||||
| 	if ok { | ||||
| 		outputProtocol = inputProtocol | ||||
| 	} else { | ||||
| 		oTrans, err := p.outputTransportFactory.GetTransport(client) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		outputTransport = oTrans | ||||
| 		outputProtocol = p.outputProtocolFactory.GetProtocol(outputTransport) | ||||
| 	} | ||||
| 
 | ||||
| 	if inputTransport != nil { | ||||
| 		defer inputTransport.Close() | ||||
| 	} | ||||
| 	if outputTransport != nil { | ||||
| 		defer outputTransport.Close() | ||||
| 	} | ||||
| 	for { | ||||
| 		if atomic.LoadInt32(&p.closed) != 0 { | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		ctx := SetResponseHelper( | ||||
| 			defaultCtx, | ||||
| 			TResponseHelper{ | ||||
| 				THeaderResponseHelper: NewTHeaderResponseHelper(outputProtocol), | ||||
| 			}, | ||||
| 		) | ||||
| 		if headerProtocol != nil { | ||||
| 			// We need to call ReadFrame here, otherwise we won't | ||||
| 			// get any headers on the AddReadTHeaderToContext call. | ||||
| 			// | ||||
| 			// ReadFrame is safe to be called multiple times so it | ||||
| 			// won't break when it's called again later when we | ||||
| 			// actually start to read the message. | ||||
| 			if err := headerProtocol.ReadFrame(ctx); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ctx = AddReadTHeaderToContext(ctx, headerProtocol.GetReadHeaders()) | ||||
| 			ctx = SetWriteHeaderList(ctx, p.forwardHeaders) | ||||
| 		} | ||||
| 
 | ||||
| 		ok, err := processor.Process(ctx, inputProtocol, outputProtocol) | ||||
| 		if errors.Is(err, ErrAbandonRequest) { | ||||
| 			return client.Close() | ||||
| 		} | ||||
| 		if errors.As(err, new(TTransportException)) && err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		var tae TApplicationException | ||||
| 		if errors.As(err, &tae) && tae.TypeId() == UNKNOWN_METHOD { | ||||
| 			continue | ||||
| 		} | ||||
| 		if !ok { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,238 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type TSocket struct { | ||||
| 	conn *socketConn | ||||
| 	addr net.Addr | ||||
| 	cfg  *TConfiguration | ||||
| 
 | ||||
| 	connectTimeout time.Duration | ||||
| 	socketTimeout  time.Duration | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSocketConf instead. | ||||
| func NewTSocket(hostPort string) (*TSocket, error) { | ||||
| 	return NewTSocketConf(hostPort, &TConfiguration{ | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTSocketConf creates a net.Conn-backed TTransport, given a host and port. | ||||
| // | ||||
| // Example: | ||||
| // | ||||
| //     trans, err := thrift.NewTSocketConf("localhost:9090", &TConfiguration{ | ||||
| //         ConnectTimeout: time.Second, // Use 0 for no timeout | ||||
| //         SocketTimeout:  time.Second, // Use 0 for no timeout | ||||
| //     }) | ||||
| func NewTSocketConf(hostPort string, conf *TConfiguration) (*TSocket, error) { | ||||
| 	addr, err := net.ResolveTCPAddr("tcp", hostPort) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewTSocketFromAddrConf(addr, conf), nil | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSocketConf instead. | ||||
| func NewTSocketTimeout(hostPort string, connTimeout time.Duration, soTimeout time.Duration) (*TSocket, error) { | ||||
| 	return NewTSocketConf(hostPort, &TConfiguration{ | ||||
| 		ConnectTimeout: connTimeout, | ||||
| 		SocketTimeout:  soTimeout, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTSocketFromAddrConf creates a TSocket from a net.Addr | ||||
| func NewTSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSocket { | ||||
| 	return &TSocket{ | ||||
| 		addr: addr, | ||||
| 		cfg:  conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSocketFromAddrConf instead. | ||||
| func NewTSocketFromAddrTimeout(addr net.Addr, connTimeout time.Duration, soTimeout time.Duration) *TSocket { | ||||
| 	return NewTSocketFromAddrConf(addr, &TConfiguration{ | ||||
| 		ConnectTimeout: connTimeout, | ||||
| 		SocketTimeout:  soTimeout, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTSocketFromConnConf creates a TSocket from an existing net.Conn. | ||||
| func NewTSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSocket { | ||||
| 	return &TSocket{ | ||||
| 		conn: wrapSocketConn(conn), | ||||
| 		addr: conn.RemoteAddr(), | ||||
| 		cfg:  conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSocketFromConnConf instead. | ||||
| func NewTSocketFromConnTimeout(conn net.Conn, socketTimeout time.Duration) *TSocket { | ||||
| 	return NewTSocketFromConnConf(conn, &TConfiguration{ | ||||
| 		SocketTimeout: socketTimeout, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| // | ||||
| // It can be used to set connect and socket timeouts. | ||||
| func (p *TSocket) SetTConfiguration(conf *TConfiguration) { | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| // Sets the connect timeout | ||||
| func (p *TSocket) SetConnTimeout(timeout time.Duration) error { | ||||
| 	if p.cfg == nil { | ||||
| 		p.cfg = &TConfiguration{ | ||||
| 			noPropagation: true, | ||||
| 		} | ||||
| 	} | ||||
| 	p.cfg.ConnectTimeout = timeout | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Sets the socket timeout | ||||
| func (p *TSocket) SetSocketTimeout(timeout time.Duration) error { | ||||
| 	if p.cfg == nil { | ||||
| 		p.cfg = &TConfiguration{ | ||||
| 			noPropagation: true, | ||||
| 		} | ||||
| 	} | ||||
| 	p.cfg.SocketTimeout = timeout | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) pushDeadline(read, write bool) { | ||||
| 	var t time.Time | ||||
| 	if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { | ||||
| 		t = time.Now().Add(time.Duration(timeout)) | ||||
| 	} | ||||
| 	if read && write { | ||||
| 		p.conn.SetDeadline(t) | ||||
| 	} else if read { | ||||
| 		p.conn.SetReadDeadline(t) | ||||
| 	} else if write { | ||||
| 		p.conn.SetWriteDeadline(t) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Connects the socket, creating a new socket object if necessary. | ||||
| func (p *TSocket) Open() error { | ||||
| 	if p.conn.isValid() { | ||||
| 		return NewTTransportException(ALREADY_OPEN, "Socket already connected.") | ||||
| 	} | ||||
| 	if p.addr == nil { | ||||
| 		return NewTTransportException(NOT_OPEN, "Cannot open nil address.") | ||||
| 	} | ||||
| 	if len(p.addr.Network()) == 0 { | ||||
| 		return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") | ||||
| 	} | ||||
| 	if len(p.addr.String()) == 0 { | ||||
| 		return NewTTransportException(NOT_OPEN, "Cannot open bad address.") | ||||
| 	} | ||||
| 	var err error | ||||
| 	if p.conn, err = createSocketConnFromReturn(net.DialTimeout( | ||||
| 		p.addr.Network(), | ||||
| 		p.addr.String(), | ||||
| 		p.cfg.GetConnectTimeout(), | ||||
| 	)); err != nil { | ||||
| 		return NewTTransportException(NOT_OPEN, err.Error()) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Retrieve the underlying net.Conn | ||||
| func (p *TSocket) Conn() net.Conn { | ||||
| 	return p.conn | ||||
| } | ||||
| 
 | ||||
| // Returns true if the connection is open | ||||
| func (p *TSocket) IsOpen() bool { | ||||
| 	return p.conn.IsOpen() | ||||
| } | ||||
| 
 | ||||
| // Closes the socket. | ||||
| func (p *TSocket) Close() error { | ||||
| 	// Close the socket | ||||
| 	if p.conn != nil { | ||||
| 		err := p.conn.Close() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		p.conn = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| //Returns the remote address of the socket. | ||||
| func (p *TSocket) Addr() net.Addr { | ||||
| 	return p.addr | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) Read(buf []byte) (int, error) { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Connection not open") | ||||
| 	} | ||||
| 	p.pushDeadline(true, false) | ||||
| 	// NOTE: Calling any of p.IsOpen, p.conn.read0, or p.conn.IsOpen between | ||||
| 	// p.pushDeadline and p.conn.Read could cause the deadline set inside | ||||
| 	// p.pushDeadline being reset, thus need to be avoided. | ||||
| 	n, err := p.conn.Read(buf) | ||||
| 	return n, NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) Write(buf []byte) (int, error) { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Connection not open") | ||||
| 	} | ||||
| 	p.pushDeadline(false, true) | ||||
| 	return p.conn.Write(buf) | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) Flush(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) Interrupt() error { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return p.conn.Close() | ||||
| } | ||||
| 
 | ||||
| func (p *TSocket) RemainingBytes() (num_bytes uint64) { | ||||
| 	const maxSize = ^uint64(0) | ||||
| 	return maxSize // the truth is, we just don't know unless framed is used | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TSocket)(nil) | ||||
|  | @ -1,102 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| ) | ||||
| 
 | ||||
| // socketConn is a wrapped net.Conn that tries to do connectivity check. | ||||
| type socketConn struct { | ||||
| 	net.Conn | ||||
| 
 | ||||
| 	buffer [1]byte | ||||
| } | ||||
| 
 | ||||
| var _ net.Conn = (*socketConn)(nil) | ||||
| 
 | ||||
| // createSocketConnFromReturn is a language sugar to help create socketConn from | ||||
| // return values of functions like net.Dial, tls.Dial, net.Listener.Accept, etc. | ||||
| func createSocketConnFromReturn(conn net.Conn, err error) (*socketConn, error) { | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &socketConn{ | ||||
| 		Conn: conn, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // wrapSocketConn wraps an existing net.Conn into *socketConn. | ||||
| func wrapSocketConn(conn net.Conn) *socketConn { | ||||
| 	// In case conn is already wrapped, | ||||
| 	// return it as-is and avoid double wrapping. | ||||
| 	if sc, ok := conn.(*socketConn); ok { | ||||
| 		return sc | ||||
| 	} | ||||
| 
 | ||||
| 	return &socketConn{ | ||||
| 		Conn: conn, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // isValid checks whether there's a valid connection. | ||||
| // | ||||
| // It's nil safe, and returns false if sc itself is nil, or if the underlying | ||||
| // connection is nil. | ||||
| // | ||||
| // It's the same as the previous implementation of TSocket.IsOpen and | ||||
| // TSSLSocket.IsOpen before we added connectivity check. | ||||
| func (sc *socketConn) isValid() bool { | ||||
| 	return sc != nil && sc.Conn != nil | ||||
| } | ||||
| 
 | ||||
| // IsOpen checks whether the connection is open. | ||||
| // | ||||
| // It's nil safe, and returns false if sc itself is nil, or if the underlying | ||||
| // connection is nil. | ||||
| // | ||||
| // Otherwise, it tries to do a connectivity check and returns the result. | ||||
| // | ||||
| // It also has the side effect of resetting the previously set read deadline on | ||||
| // the socket. As a result, it shouldn't be called between setting read deadline | ||||
| // and doing actual read. | ||||
| func (sc *socketConn) IsOpen() bool { | ||||
| 	if !sc.isValid() { | ||||
| 		return false | ||||
| 	} | ||||
| 	return sc.checkConn() == nil | ||||
| } | ||||
| 
 | ||||
| // Read implements io.Reader. | ||||
| // | ||||
| // On Windows, it behaves the same as the underlying net.Conn.Read. | ||||
| // | ||||
| // On non-Windows, it treats len(p) == 0 as a connectivity check instead of | ||||
| // readability check, which means instead of blocking until there's something to | ||||
| // read (readability check), or always return (0, nil) (the default behavior of | ||||
| // go's stdlib implementation on non-Windows), it never blocks, and will return | ||||
| // an error if the connection is lost. | ||||
| func (sc *socketConn) Read(p []byte) (n int, err error) { | ||||
| 	if len(p) == 0 { | ||||
| 		return 0, sc.read0() | ||||
| 	} | ||||
| 
 | ||||
| 	return sc.Conn.Read(p) | ||||
| } | ||||
|  | @ -1,83 +0,0 @@ | |||
| // +build !windows | ||||
| 
 | ||||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // We rely on this variable to be the zero time, | ||||
| // but define it as global variable to avoid repetitive allocations. | ||||
| // Please DO NOT mutate this variable in any way. | ||||
| var zeroTime time.Time | ||||
| 
 | ||||
| func (sc *socketConn) read0() error { | ||||
| 	return sc.checkConn() | ||||
| } | ||||
| 
 | ||||
| func (sc *socketConn) checkConn() error { | ||||
| 	syscallConn, ok := sc.Conn.(syscall.Conn) | ||||
| 	if !ok { | ||||
| 		// No way to check, return nil | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// The reading about to be done here is non-blocking so we don't really | ||||
| 	// need a read deadline. We just need to clear the previously set read | ||||
| 	// deadline, if any. | ||||
| 	sc.Conn.SetReadDeadline(zeroTime) | ||||
| 
 | ||||
| 	rc, err := syscallConn.SyscallConn() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	var n int | ||||
| 
 | ||||
| 	if readErr := rc.Read(func(fd uintptr) bool { | ||||
| 		n, _, err = syscall.Recvfrom(int(fd), sc.buffer[:], syscall.MSG_PEEK|syscall.MSG_DONTWAIT) | ||||
| 		return true | ||||
| 	}); readErr != nil { | ||||
| 		return readErr | ||||
| 	} | ||||
| 
 | ||||
| 	if n > 0 { | ||||
| 		// We got something, which means we are good | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EWOULDBLOCK) { | ||||
| 		// This means the connection is still open but we don't have | ||||
| 		// anything to read right now. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// At this point, it means the other side already closed the connection. | ||||
| 	return io.EOF | ||||
| } | ||||
|  | @ -1,34 +0,0 @@ | |||
| // +build windows | ||||
| 
 | ||||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| func (sc *socketConn) read0() error { | ||||
| 	// On windows, we fallback to the default behavior of reading 0 bytes. | ||||
| 	var p []byte | ||||
| 	_, err := sc.Conn.Read(p) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (sc *socketConn) checkConn() error { | ||||
| 	// On windows, we always return nil for this check. | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,112 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"net" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type TSSLServerSocket struct { | ||||
| 	listener      net.Listener | ||||
| 	addr          net.Addr | ||||
| 	clientTimeout time.Duration | ||||
| 	interrupted   bool | ||||
| 	cfg           *tls.Config | ||||
| } | ||||
| 
 | ||||
| func NewTSSLServerSocket(listenAddr string, cfg *tls.Config) (*TSSLServerSocket, error) { | ||||
| 	return NewTSSLServerSocketTimeout(listenAddr, cfg, 0) | ||||
| } | ||||
| 
 | ||||
| func NewTSSLServerSocketTimeout(listenAddr string, cfg *tls.Config, clientTimeout time.Duration) (*TSSLServerSocket, error) { | ||||
| 	if cfg.MinVersion == 0 { | ||||
| 		cfg.MinVersion = tls.VersionTLS10 | ||||
| 	} | ||||
| 	addr, err := net.ResolveTCPAddr("tcp", listenAddr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &TSSLServerSocket{addr: addr, clientTimeout: clientTimeout, cfg: cfg}, nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLServerSocket) Listen() error { | ||||
| 	if p.IsListening() { | ||||
| 		return nil | ||||
| 	} | ||||
| 	l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.listener = l | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLServerSocket) Accept() (TTransport, error) { | ||||
| 	if p.interrupted { | ||||
| 		return nil, errTransportInterrupted | ||||
| 	} | ||||
| 	if p.listener == nil { | ||||
| 		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") | ||||
| 	} | ||||
| 	conn, err := p.listener.Accept() | ||||
| 	if err != nil { | ||||
| 		return nil, NewTTransportExceptionFromError(err) | ||||
| 	} | ||||
| 	return NewTSSLSocketFromConnTimeout(conn, p.cfg, p.clientTimeout), nil | ||||
| } | ||||
| 
 | ||||
| // Checks whether the socket is listening. | ||||
| func (p *TSSLServerSocket) IsListening() bool { | ||||
| 	return p.listener != nil | ||||
| } | ||||
| 
 | ||||
| // Connects the socket, creating a new socket object if necessary. | ||||
| func (p *TSSLServerSocket) Open() error { | ||||
| 	if p.IsListening() { | ||||
| 		return NewTTransportException(ALREADY_OPEN, "Server socket already open") | ||||
| 	} | ||||
| 	if l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg); err != nil { | ||||
| 		return err | ||||
| 	} else { | ||||
| 		p.listener = l | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLServerSocket) Addr() net.Addr { | ||||
| 	return p.addr | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLServerSocket) Close() error { | ||||
| 	defer func() { | ||||
| 		p.listener = nil | ||||
| 	}() | ||||
| 	if p.IsListening() { | ||||
| 		return p.listener.Close() | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLServerSocket) Interrupt() error { | ||||
| 	p.interrupted = true | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,258 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"net" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type TSSLSocket struct { | ||||
| 	conn *socketConn | ||||
| 	// hostPort contains host:port (e.g. "asdf.com:12345"). The field is | ||||
| 	// only valid if addr is nil. | ||||
| 	hostPort string | ||||
| 	// addr is nil when hostPort is not "", and is only used when the | ||||
| 	// TSSLSocket is constructed from a net.Addr. | ||||
| 	addr net.Addr | ||||
| 
 | ||||
| 	cfg *TConfiguration | ||||
| } | ||||
| 
 | ||||
| // NewTSSLSocketConf creates a net.Conn-backed TTransport, given a host and port. | ||||
| // | ||||
| // Example: | ||||
| // | ||||
| //     trans, err := thrift.NewTSSLSocketConf("localhost:9090", nil, &TConfiguration{ | ||||
| //         ConnectTimeout: time.Second, // Use 0 for no timeout | ||||
| //         SocketTimeout:  time.Second, // Use 0 for no timeout | ||||
| //     }) | ||||
| func NewTSSLSocketConf(hostPort string, conf *TConfiguration) (*TSSLSocket, error) { | ||||
| 	if cfg := conf.GetTLSConfig(); cfg != nil && cfg.MinVersion == 0 { | ||||
| 		cfg.MinVersion = tls.VersionTLS10 | ||||
| 	} | ||||
| 	return &TSSLSocket{ | ||||
| 		hostPort: hostPort, | ||||
| 		cfg:      conf, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSSLSocketConf instead. | ||||
| func NewTSSLSocket(hostPort string, cfg *tls.Config) (*TSSLSocket, error) { | ||||
| 	return NewTSSLSocketConf(hostPort, &TConfiguration{ | ||||
| 		TLSConfig: cfg, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSSLSocketConf instead. | ||||
| func NewTSSLSocketTimeout(hostPort string, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) (*TSSLSocket, error) { | ||||
| 	return NewTSSLSocketConf(hostPort, &TConfiguration{ | ||||
| 		ConnectTimeout: connectTimeout, | ||||
| 		SocketTimeout:  socketTimeout, | ||||
| 		TLSConfig:      cfg, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTSSLSocketFromAddrConf creates a TSSLSocket from a net.Addr. | ||||
| func NewTSSLSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSSLSocket { | ||||
| 	return &TSSLSocket{ | ||||
| 		addr: addr, | ||||
| 		cfg:  conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSSLSocketFromAddrConf instead. | ||||
| func NewTSSLSocketFromAddrTimeout(addr net.Addr, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) *TSSLSocket { | ||||
| 	return NewTSSLSocketFromAddrConf(addr, &TConfiguration{ | ||||
| 		ConnectTimeout: connectTimeout, | ||||
| 		SocketTimeout:  socketTimeout, | ||||
| 		TLSConfig:      cfg, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // NewTSSLSocketFromConnConf creates a TSSLSocket from an existing net.Conn. | ||||
| func NewTSSLSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSSLSocket { | ||||
| 	return &TSSLSocket{ | ||||
| 		conn: wrapSocketConn(conn), | ||||
| 		addr: conn.RemoteAddr(), | ||||
| 		cfg:  conf, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Deprecated: Use NewTSSLSocketFromConnConf instead. | ||||
| func NewTSSLSocketFromConnTimeout(conn net.Conn, cfg *tls.Config, socketTimeout time.Duration) *TSSLSocket { | ||||
| 	return NewTSSLSocketFromConnConf(conn, &TConfiguration{ | ||||
| 		SocketTimeout: socketTimeout, | ||||
| 		TLSConfig:     cfg, | ||||
| 
 | ||||
| 		noPropagation: true, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter. | ||||
| // | ||||
| // It can be used to change connect and socket timeouts. | ||||
| func (p *TSSLSocket) SetTConfiguration(conf *TConfiguration) { | ||||
| 	p.cfg = conf | ||||
| } | ||||
| 
 | ||||
| // Sets the connect timeout | ||||
| func (p *TSSLSocket) SetConnTimeout(timeout time.Duration) error { | ||||
| 	if p.cfg == nil { | ||||
| 		p.cfg = &TConfiguration{} | ||||
| 	} | ||||
| 	p.cfg.ConnectTimeout = timeout | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Sets the socket timeout | ||||
| func (p *TSSLSocket) SetSocketTimeout(timeout time.Duration) error { | ||||
| 	if p.cfg == nil { | ||||
| 		p.cfg = &TConfiguration{} | ||||
| 	} | ||||
| 	p.cfg.SocketTimeout = timeout | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) pushDeadline(read, write bool) { | ||||
| 	var t time.Time | ||||
| 	if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { | ||||
| 		t = time.Now().Add(time.Duration(timeout)) | ||||
| 	} | ||||
| 	if read && write { | ||||
| 		p.conn.SetDeadline(t) | ||||
| 	} else if read { | ||||
| 		p.conn.SetReadDeadline(t) | ||||
| 	} else if write { | ||||
| 		p.conn.SetWriteDeadline(t) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Connects the socket, creating a new socket object if necessary. | ||||
| func (p *TSSLSocket) Open() error { | ||||
| 	var err error | ||||
| 	// If we have a hostname, we need to pass the hostname to tls.Dial for | ||||
| 	// certificate hostname checks. | ||||
| 	if p.hostPort != "" { | ||||
| 		if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( | ||||
| 			&net.Dialer{ | ||||
| 				Timeout: p.cfg.GetConnectTimeout(), | ||||
| 			}, | ||||
| 			"tcp", | ||||
| 			p.hostPort, | ||||
| 			p.cfg.GetTLSConfig(), | ||||
| 		)); err != nil { | ||||
| 			return NewTTransportException(NOT_OPEN, err.Error()) | ||||
| 		} | ||||
| 	} else { | ||||
| 		if p.conn.isValid() { | ||||
| 			return NewTTransportException(ALREADY_OPEN, "Socket already connected.") | ||||
| 		} | ||||
| 		if p.addr == nil { | ||||
| 			return NewTTransportException(NOT_OPEN, "Cannot open nil address.") | ||||
| 		} | ||||
| 		if len(p.addr.Network()) == 0 { | ||||
| 			return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") | ||||
| 		} | ||||
| 		if len(p.addr.String()) == 0 { | ||||
| 			return NewTTransportException(NOT_OPEN, "Cannot open bad address.") | ||||
| 		} | ||||
| 		if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( | ||||
| 			&net.Dialer{ | ||||
| 				Timeout: p.cfg.GetConnectTimeout(), | ||||
| 			}, | ||||
| 			p.addr.Network(), | ||||
| 			p.addr.String(), | ||||
| 			p.cfg.GetTLSConfig(), | ||||
| 		)); err != nil { | ||||
| 			return NewTTransportException(NOT_OPEN, err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Retrieve the underlying net.Conn | ||||
| func (p *TSSLSocket) Conn() net.Conn { | ||||
| 	return p.conn | ||||
| } | ||||
| 
 | ||||
| // Returns true if the connection is open | ||||
| func (p *TSSLSocket) IsOpen() bool { | ||||
| 	return p.conn.IsOpen() | ||||
| } | ||||
| 
 | ||||
| // Closes the socket. | ||||
| func (p *TSSLSocket) Close() error { | ||||
| 	// Close the socket | ||||
| 	if p.conn != nil { | ||||
| 		err := p.conn.Close() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		p.conn = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) Read(buf []byte) (int, error) { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Connection not open") | ||||
| 	} | ||||
| 	p.pushDeadline(true, false) | ||||
| 	// NOTE: Calling any of p.IsOpen, p.conn.read0, or p.conn.IsOpen between | ||||
| 	// p.pushDeadline and p.conn.Read could cause the deadline set inside | ||||
| 	// p.pushDeadline being reset, thus need to be avoided. | ||||
| 	n, err := p.conn.Read(buf) | ||||
| 	return n, NewTTransportExceptionFromError(err) | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) Write(buf []byte) (int, error) { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return 0, NewTTransportException(NOT_OPEN, "Connection not open") | ||||
| 	} | ||||
| 	p.pushDeadline(false, true) | ||||
| 	return p.conn.Write(buf) | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) Flush(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) Interrupt() error { | ||||
| 	if !p.conn.isValid() { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return p.conn.Close() | ||||
| } | ||||
| 
 | ||||
| func (p *TSSLSocket) RemainingBytes() (num_bytes uint64) { | ||||
| 	const maxSize = ^uint64(0) | ||||
| 	return maxSize // the truth is, we just don't know unless framed is used | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TSSLSocket)(nil) | ||||
|  | @ -1,70 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| var errTransportInterrupted = errors.New("Transport Interrupted") | ||||
| 
 | ||||
| type Flusher interface { | ||||
| 	Flush() (err error) | ||||
| } | ||||
| 
 | ||||
| type ContextFlusher interface { | ||||
| 	Flush(ctx context.Context) (err error) | ||||
| } | ||||
| 
 | ||||
| type ReadSizeProvider interface { | ||||
| 	RemainingBytes() (num_bytes uint64) | ||||
| } | ||||
| 
 | ||||
| // Encapsulates the I/O layer | ||||
| type TTransport interface { | ||||
| 	io.ReadWriteCloser | ||||
| 	ContextFlusher | ||||
| 	ReadSizeProvider | ||||
| 
 | ||||
| 	// Opens the transport for communication | ||||
| 	Open() error | ||||
| 
 | ||||
| 	// Returns true if the transport is open | ||||
| 	IsOpen() bool | ||||
| } | ||||
| 
 | ||||
| type stringWriter interface { | ||||
| 	WriteString(s string) (n int, err error) | ||||
| } | ||||
| 
 | ||||
| // This is "enhanced" transport with extra capabilities. You need to use one of these | ||||
| // to construct protocol. | ||||
| // Notably, TSocket does not implement this interface, and it is always a mistake to use | ||||
| // TSocket directly in protocol. | ||||
| type TRichTransport interface { | ||||
| 	io.ReadWriter | ||||
| 	io.ByteReader | ||||
| 	io.ByteWriter | ||||
| 	stringWriter | ||||
| 	ContextFlusher | ||||
| 	ReadSizeProvider | ||||
| } | ||||
|  | @ -1,131 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| type timeoutable interface { | ||||
| 	Timeout() bool | ||||
| } | ||||
| 
 | ||||
| // Thrift Transport exception | ||||
| type TTransportException interface { | ||||
| 	TException | ||||
| 	TypeId() int | ||||
| 	Err() error | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	UNKNOWN_TRANSPORT_EXCEPTION = 0 | ||||
| 	NOT_OPEN                    = 1 | ||||
| 	ALREADY_OPEN                = 2 | ||||
| 	TIMED_OUT                   = 3 | ||||
| 	END_OF_FILE                 = 4 | ||||
| ) | ||||
| 
 | ||||
| type tTransportException struct { | ||||
| 	typeId int | ||||
| 	err    error | ||||
| 	msg    string | ||||
| } | ||||
| 
 | ||||
| var _ TTransportException = (*tTransportException)(nil) | ||||
| 
 | ||||
| func (tTransportException) TExceptionType() TExceptionType { | ||||
| 	return TExceptionTypeTransport | ||||
| } | ||||
| 
 | ||||
| func (p *tTransportException) TypeId() int { | ||||
| 	return p.typeId | ||||
| } | ||||
| 
 | ||||
| func (p *tTransportException) Error() string { | ||||
| 	return p.msg | ||||
| } | ||||
| 
 | ||||
| func (p *tTransportException) Err() error { | ||||
| 	return p.err | ||||
| } | ||||
| 
 | ||||
| func (p *tTransportException) Unwrap() error { | ||||
| 	return p.err | ||||
| } | ||||
| 
 | ||||
| func (p *tTransportException) Timeout() bool { | ||||
| 	return p.typeId == TIMED_OUT | ||||
| } | ||||
| 
 | ||||
| func NewTTransportException(t int, e string) TTransportException { | ||||
| 	return &tTransportException{ | ||||
| 		typeId: t, | ||||
| 		err:    errors.New(e), | ||||
| 		msg:    e, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewTTransportExceptionFromError(e error) TTransportException { | ||||
| 	if e == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if t, ok := e.(TTransportException); ok { | ||||
| 		return t | ||||
| 	} | ||||
| 
 | ||||
| 	te := &tTransportException{ | ||||
| 		typeId: UNKNOWN_TRANSPORT_EXCEPTION, | ||||
| 		err:    e, | ||||
| 		msg:    e.Error(), | ||||
| 	} | ||||
| 
 | ||||
| 	if isTimeoutError(e) { | ||||
| 		te.typeId = TIMED_OUT | ||||
| 		return te | ||||
| 	} | ||||
| 
 | ||||
| 	if errors.Is(e, io.EOF) { | ||||
| 		te.typeId = END_OF_FILE | ||||
| 		return te | ||||
| 	} | ||||
| 
 | ||||
| 	return te | ||||
| } | ||||
| 
 | ||||
| func prependTTransportException(prepend string, e TTransportException) TTransportException { | ||||
| 	return &tTransportException{ | ||||
| 		typeId: e.TypeId(), | ||||
| 		err:    e, | ||||
| 		msg:    prepend + e.Error(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // isTimeoutError returns true when err is an error caused by timeout. | ||||
| // | ||||
| // Note that this also includes TTransportException wrapped timeout errors. | ||||
| func isTimeoutError(err error) bool { | ||||
| 	var t timeoutable | ||||
| 	if errors.As(err, &t) { | ||||
| 		return t.Timeout() | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | @ -1,39 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| // Factory class used to create wrapped instance of Transports. | ||||
| // This is used primarily in servers, which get Transports from | ||||
| // a ServerTransport and then may want to mutate them (i.e. create | ||||
| // a BufferedTransport from the underlying base transport) | ||||
| type TTransportFactory interface { | ||||
| 	GetTransport(trans TTransport) (TTransport, error) | ||||
| } | ||||
| 
 | ||||
| type tTransportFactory struct{} | ||||
| 
 | ||||
| // Return a wrapped instance of the base Transport. | ||||
| func (p *tTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	return trans, nil | ||||
| } | ||||
| 
 | ||||
| func NewTTransportFactory() TTransportFactory { | ||||
| 	return &tTransportFactory{} | ||||
| } | ||||
|  | @ -1,69 +0,0 @@ | |||
| /* | ||||
|  * Licensed to the Apache Software Foundation (ASF) under one | ||||
|  * or more contributor license agreements. See the NOTICE file | ||||
|  * distributed with this work for additional information | ||||
|  * regarding copyright ownership. The ASF licenses this file | ||||
|  * to you under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance | ||||
|  * with the License. You may obtain a copy of the License at | ||||
|  * | ||||
|  *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, | ||||
|  * software distributed under the License is distributed on an | ||||
|  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
|  * KIND, either express or implied. See the License for the | ||||
|  * specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| // Type constants in the Thrift protocol | ||||
| type TType byte | ||||
| 
 | ||||
| const ( | ||||
| 	STOP   = 0 | ||||
| 	VOID   = 1 | ||||
| 	BOOL   = 2 | ||||
| 	BYTE   = 3 | ||||
| 	I08    = 3 | ||||
| 	DOUBLE = 4 | ||||
| 	I16    = 6 | ||||
| 	I32    = 8 | ||||
| 	I64    = 10 | ||||
| 	STRING = 11 | ||||
| 	UTF7   = 11 | ||||
| 	STRUCT = 12 | ||||
| 	MAP    = 13 | ||||
| 	SET    = 14 | ||||
| 	LIST   = 15 | ||||
| 	UTF8   = 16 | ||||
| 	UTF16  = 17 | ||||
| 	//BINARY = 18   wrong and unused | ||||
| ) | ||||
| 
 | ||||
| var typeNames = map[int]string{ | ||||
| 	STOP:   "STOP", | ||||
| 	VOID:   "VOID", | ||||
| 	BOOL:   "BOOL", | ||||
| 	BYTE:   "BYTE", | ||||
| 	DOUBLE: "DOUBLE", | ||||
| 	I16:    "I16", | ||||
| 	I32:    "I32", | ||||
| 	I64:    "I64", | ||||
| 	STRING: "STRING", | ||||
| 	STRUCT: "STRUCT", | ||||
| 	MAP:    "MAP", | ||||
| 	SET:    "SET", | ||||
| 	LIST:   "LIST", | ||||
| 	UTF8:   "UTF8", | ||||
| 	UTF16:  "UTF16", | ||||
| } | ||||
| 
 | ||||
| func (p TType) String() string { | ||||
| 	if s, ok := typeNames[int(p)]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	return "Unknown" | ||||
| } | ||||
|  | @ -1,137 +0,0 @@ | |||
| /* | ||||
| * Licensed to the Apache Software Foundation (ASF) under one | ||||
| * or more contributor license agreements. See the NOTICE file | ||||
| * distributed with this work for additional information | ||||
| * regarding copyright ownership. The ASF licenses this file | ||||
| * to you under the Apache License, Version 2.0 (the | ||||
| * "License"); you may not use this file except in compliance | ||||
| * with the License. You may obtain a copy of the License at | ||||
| * | ||||
| *   http://www.apache.org/licenses/LICENSE-2.0 | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, | ||||
| * software distributed under the License is distributed on an | ||||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
| * KIND, either express or implied. See the License for the | ||||
| * specific language governing permissions and limitations | ||||
| * under the License. | ||||
|  */ | ||||
| 
 | ||||
| package thrift | ||||
| 
 | ||||
| import ( | ||||
| 	"compress/zlib" | ||||
| 	"context" | ||||
| 	"io" | ||||
| ) | ||||
| 
 | ||||
| // TZlibTransportFactory is a factory for TZlibTransport instances | ||||
| type TZlibTransportFactory struct { | ||||
| 	level   int | ||||
| 	factory TTransportFactory | ||||
| } | ||||
| 
 | ||||
| // TZlibTransport is a TTransport implementation that makes use of zlib compression. | ||||
| type TZlibTransport struct { | ||||
| 	reader    io.ReadCloser | ||||
| 	transport TTransport | ||||
| 	writer    *zlib.Writer | ||||
| } | ||||
| 
 | ||||
| // GetTransport constructs a new instance of NewTZlibTransport | ||||
| func (p *TZlibTransportFactory) GetTransport(trans TTransport) (TTransport, error) { | ||||
| 	if p.factory != nil { | ||||
| 		// wrap other factory | ||||
| 		var err error | ||||
| 		trans, err = p.factory.GetTransport(trans) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return NewTZlibTransport(trans, p.level) | ||||
| } | ||||
| 
 | ||||
| // NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory | ||||
| func NewTZlibTransportFactory(level int) *TZlibTransportFactory { | ||||
| 	return &TZlibTransportFactory{level: level, factory: nil} | ||||
| } | ||||
| 
 | ||||
| // NewTZlibTransportFactory constructs a new instance of TZlibTransportFactory | ||||
| // as a wrapper over existing transport factory | ||||
| func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) *TZlibTransportFactory { | ||||
| 	return &TZlibTransportFactory{level: level, factory: factory} | ||||
| } | ||||
| 
 | ||||
| // NewTZlibTransport constructs a new instance of TZlibTransport | ||||
| func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) { | ||||
| 	w, err := zlib.NewWriterLevel(trans, level) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &TZlibTransport{ | ||||
| 		writer:    w, | ||||
| 		transport: trans, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // Close closes the reader and writer (flushing any unwritten data) and closes | ||||
| // the underlying transport. | ||||
| func (z *TZlibTransport) Close() error { | ||||
| 	if z.reader != nil { | ||||
| 		if err := z.reader.Close(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := z.writer.Close(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return z.transport.Close() | ||||
| } | ||||
| 
 | ||||
| // Flush flushes the writer and its underlying transport. | ||||
| func (z *TZlibTransport) Flush(ctx context.Context) error { | ||||
| 	if err := z.writer.Flush(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return z.transport.Flush(ctx) | ||||
| } | ||||
| 
 | ||||
| // IsOpen returns true if the transport is open | ||||
| func (z *TZlibTransport) IsOpen() bool { | ||||
| 	return z.transport.IsOpen() | ||||
| } | ||||
| 
 | ||||
| // Open opens the transport for communication | ||||
| func (z *TZlibTransport) Open() error { | ||||
| 	return z.transport.Open() | ||||
| } | ||||
| 
 | ||||
| func (z *TZlibTransport) Read(p []byte) (int, error) { | ||||
| 	if z.reader == nil { | ||||
| 		r, err := zlib.NewReader(z.transport) | ||||
| 		if err != nil { | ||||
| 			return 0, NewTTransportExceptionFromError(err) | ||||
| 		} | ||||
| 		z.reader = r | ||||
| 	} | ||||
| 
 | ||||
| 	return z.reader.Read(p) | ||||
| } | ||||
| 
 | ||||
| // RemainingBytes returns the size in bytes of the data that is still to be | ||||
| // read. | ||||
| func (z *TZlibTransport) RemainingBytes() uint64 { | ||||
| 	return z.transport.RemainingBytes() | ||||
| } | ||||
| 
 | ||||
| func (z *TZlibTransport) Write(p []byte) (int, error) { | ||||
| 	return z.writer.Write(p) | ||||
| } | ||||
| 
 | ||||
| // SetTConfiguration implements TConfigurationSetter for propagation. | ||||
| func (z *TZlibTransport) SetTConfiguration(conf *TConfiguration) { | ||||
| 	PropagateTConfiguration(z.transport, conf) | ||||
| } | ||||
| 
 | ||||
| var _ TConfigurationSetter = (*TZlibTransport)(nil) | ||||
							
								
								
									
										360
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/jaeger.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										360
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/jaeger.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,360 +0,0 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package jaeger // import "go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/codes" | ||||
| 	gen "go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger" | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| 	sdktrace "go.opentelemetry.io/otel/sdk/trace" | ||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.17.0" | ||||
| 	"go.opentelemetry.io/otel/trace" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	keyInstrumentationLibraryName    = "otel.library.name" | ||||
| 	keyInstrumentationLibraryVersion = "otel.library.version" | ||||
| 	keyError                         = "error" | ||||
| 	keySpanKind                      = "span.kind" | ||||
| 	keyStatusCode                    = "otel.status_code" | ||||
| 	keyStatusMessage                 = "otel.status_description" | ||||
| 	keyDroppedAttributeCount         = "otel.event.dropped_attributes_count" | ||||
| 	keyEventName                     = "event" | ||||
| ) | ||||
| 
 | ||||
| // New returns an OTel Exporter implementation that exports the collected | ||||
| // spans to Jaeger. | ||||
| func New(endpointOption EndpointOption) (*Exporter, error) { | ||||
| 	uploader, err := endpointOption.newBatchUploader() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Fetch default service.name from default resource for backup | ||||
| 	var defaultServiceName string | ||||
| 	defaultResource := resource.Default() | ||||
| 	if value, exists := defaultResource.Set().Value(semconv.ServiceNameKey); exists { | ||||
| 		defaultServiceName = value.AsString() | ||||
| 	} | ||||
| 	if defaultServiceName == "" { | ||||
| 		return nil, fmt.Errorf("failed to get service name from default resource") | ||||
| 	} | ||||
| 
 | ||||
| 	stopCh := make(chan struct{}) | ||||
| 	e := &Exporter{ | ||||
| 		uploader:           uploader, | ||||
| 		stopCh:             stopCh, | ||||
| 		defaultServiceName: defaultServiceName, | ||||
| 	} | ||||
| 	return e, nil | ||||
| } | ||||
| 
 | ||||
| // Exporter exports OpenTelemetry spans to a Jaeger agent or collector. | ||||
| type Exporter struct { | ||||
| 	uploader           batchUploader | ||||
| 	stopOnce           sync.Once | ||||
| 	stopCh             chan struct{} | ||||
| 	defaultServiceName string | ||||
| } | ||||
| 
 | ||||
| var _ sdktrace.SpanExporter = (*Exporter)(nil) | ||||
| 
 | ||||
| // ExportSpans transforms and exports OpenTelemetry spans to Jaeger. | ||||
| func (e *Exporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) error { | ||||
| 	// Return fast if context is already canceled or Exporter shutdown. | ||||
| 	select { | ||||
| 	case <-ctx.Done(): | ||||
| 		return ctx.Err() | ||||
| 	case <-e.stopCh: | ||||
| 		return nil | ||||
| 	default: | ||||
| 	} | ||||
| 
 | ||||
| 	// Cancel export if Exporter is shutdown. | ||||
| 	var cancel context.CancelFunc | ||||
| 	ctx, cancel = context.WithCancel(ctx) | ||||
| 	defer cancel() | ||||
| 	go func(ctx context.Context, cancel context.CancelFunc) { | ||||
| 		select { | ||||
| 		case <-ctx.Done(): | ||||
| 		case <-e.stopCh: | ||||
| 			cancel() | ||||
| 		} | ||||
| 	}(ctx, cancel) | ||||
| 
 | ||||
| 	for _, batch := range jaegerBatchList(spans, e.defaultServiceName) { | ||||
| 		if err := e.uploader.upload(ctx, batch); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Shutdown stops the Exporter. This will close all connections and release | ||||
| // all resources held by the Exporter. | ||||
| func (e *Exporter) Shutdown(ctx context.Context) error { | ||||
| 	// Stop any active and subsequent exports. | ||||
| 	e.stopOnce.Do(func() { close(e.stopCh) }) | ||||
| 	select { | ||||
| 	case <-ctx.Done(): | ||||
| 		return ctx.Err() | ||||
| 	default: | ||||
| 	} | ||||
| 	return e.uploader.shutdown(ctx) | ||||
| } | ||||
| 
 | ||||
| // MarshalLog is the marshaling function used by the logging system to represent this exporter. | ||||
| func (e *Exporter) MarshalLog() interface{} { | ||||
| 	return struct { | ||||
| 		Type string | ||||
| 	}{ | ||||
| 		Type: "jaeger", | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func spanToThrift(ss sdktrace.ReadOnlySpan) *gen.Span { | ||||
| 	attr := ss.Attributes() | ||||
| 	tags := make([]*gen.Tag, 0, len(attr)) | ||||
| 	for _, kv := range attr { | ||||
| 		tag := keyValueToTag(kv) | ||||
| 		if tag != nil { | ||||
| 			tags = append(tags, tag) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if is := ss.InstrumentationScope(); is.Name != "" { | ||||
| 		tags = append(tags, getStringTag(keyInstrumentationLibraryName, is.Name)) | ||||
| 		if is.Version != "" { | ||||
| 			tags = append(tags, getStringTag(keyInstrumentationLibraryVersion, is.Version)) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ss.SpanKind() != trace.SpanKindInternal { | ||||
| 		tags = append(tags, | ||||
| 			getStringTag(keySpanKind, ss.SpanKind().String()), | ||||
| 		) | ||||
| 	} | ||||
| 
 | ||||
| 	if ss.Status().Code != codes.Unset { | ||||
| 		switch ss.Status().Code { | ||||
| 		case codes.Ok: | ||||
| 			tags = append(tags, getStringTag(keyStatusCode, "OK")) | ||||
| 		case codes.Error: | ||||
| 			tags = append(tags, getBoolTag(keyError, true)) | ||||
| 			tags = append(tags, getStringTag(keyStatusCode, "ERROR")) | ||||
| 		} | ||||
| 		if ss.Status().Description != "" { | ||||
| 			tags = append(tags, getStringTag(keyStatusMessage, ss.Status().Description)) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var logs []*gen.Log | ||||
| 	for _, a := range ss.Events() { | ||||
| 		nTags := len(a.Attributes) | ||||
| 		if a.Name != "" { | ||||
| 			nTags++ | ||||
| 		} | ||||
| 		if a.DroppedAttributeCount != 0 { | ||||
| 			nTags++ | ||||
| 		} | ||||
| 		fields := make([]*gen.Tag, 0, nTags) | ||||
| 		if a.Name != "" { | ||||
| 			// If an event contains an attribute with the same key, it needs | ||||
| 			// to be given precedence and overwrite this. | ||||
| 			fields = append(fields, getStringTag(keyEventName, a.Name)) | ||||
| 		} | ||||
| 		for _, kv := range a.Attributes { | ||||
| 			tag := keyValueToTag(kv) | ||||
| 			if tag != nil { | ||||
| 				fields = append(fields, tag) | ||||
| 			} | ||||
| 		} | ||||
| 		if a.DroppedAttributeCount != 0 { | ||||
| 			fields = append(fields, getInt64Tag(keyDroppedAttributeCount, int64(a.DroppedAttributeCount))) | ||||
| 		} | ||||
| 		logs = append(logs, &gen.Log{ | ||||
| 			Timestamp: a.Time.UnixNano() / 1000, | ||||
| 			Fields:    fields, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	var refs []*gen.SpanRef | ||||
| 	for _, link := range ss.Links() { | ||||
| 		tid := link.SpanContext.TraceID() | ||||
| 		sid := link.SpanContext.SpanID() | ||||
| 		refs = append(refs, &gen.SpanRef{ | ||||
| 			TraceIdHigh: int64(binary.BigEndian.Uint64(tid[0:8])), | ||||
| 			TraceIdLow:  int64(binary.BigEndian.Uint64(tid[8:16])), | ||||
| 			SpanId:      int64(binary.BigEndian.Uint64(sid[:])), | ||||
| 			RefType:     gen.SpanRefType_FOLLOWS_FROM, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	tid := ss.SpanContext().TraceID() | ||||
| 	sid := ss.SpanContext().SpanID() | ||||
| 	psid := ss.Parent().SpanID() | ||||
| 	return &gen.Span{ | ||||
| 		TraceIdHigh:   int64(binary.BigEndian.Uint64(tid[0:8])), | ||||
| 		TraceIdLow:    int64(binary.BigEndian.Uint64(tid[8:16])), | ||||
| 		SpanId:        int64(binary.BigEndian.Uint64(sid[:])), | ||||
| 		ParentSpanId:  int64(binary.BigEndian.Uint64(psid[:])), | ||||
| 		OperationName: ss.Name(), // TODO: if span kind is added then add prefix "Sent"/"Recv" | ||||
| 		Flags:         int32(ss.SpanContext().TraceFlags()), | ||||
| 		StartTime:     ss.StartTime().UnixNano() / 1000, | ||||
| 		Duration:      ss.EndTime().Sub(ss.StartTime()).Nanoseconds() / 1000, | ||||
| 		Tags:          tags, | ||||
| 		Logs:          logs, | ||||
| 		References:    refs, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func keyValueToTag(keyValue attribute.KeyValue) *gen.Tag { | ||||
| 	var tag *gen.Tag | ||||
| 	switch keyValue.Value.Type() { | ||||
| 	case attribute.STRING: | ||||
| 		s := keyValue.Value.AsString() | ||||
| 		tag = &gen.Tag{ | ||||
| 			Key:   string(keyValue.Key), | ||||
| 			VStr:  &s, | ||||
| 			VType: gen.TagType_STRING, | ||||
| 		} | ||||
| 	case attribute.BOOL: | ||||
| 		b := keyValue.Value.AsBool() | ||||
| 		tag = &gen.Tag{ | ||||
| 			Key:   string(keyValue.Key), | ||||
| 			VBool: &b, | ||||
| 			VType: gen.TagType_BOOL, | ||||
| 		} | ||||
| 	case attribute.INT64: | ||||
| 		i := keyValue.Value.AsInt64() | ||||
| 		tag = &gen.Tag{ | ||||
| 			Key:   string(keyValue.Key), | ||||
| 			VLong: &i, | ||||
| 			VType: gen.TagType_LONG, | ||||
| 		} | ||||
| 	case attribute.FLOAT64: | ||||
| 		f := keyValue.Value.AsFloat64() | ||||
| 		tag = &gen.Tag{ | ||||
| 			Key:     string(keyValue.Key), | ||||
| 			VDouble: &f, | ||||
| 			VType:   gen.TagType_DOUBLE, | ||||
| 		} | ||||
| 	case attribute.BOOLSLICE, | ||||
| 		attribute.INT64SLICE, | ||||
| 		attribute.FLOAT64SLICE, | ||||
| 		attribute.STRINGSLICE: | ||||
| 		data, _ := json.Marshal(keyValue.Value.AsInterface()) | ||||
| 		a := (string)(data) | ||||
| 		tag = &gen.Tag{ | ||||
| 			Key:   string(keyValue.Key), | ||||
| 			VStr:  &a, | ||||
| 			VType: gen.TagType_STRING, | ||||
| 		} | ||||
| 	} | ||||
| 	return tag | ||||
| } | ||||
| 
 | ||||
| func getInt64Tag(k string, i int64) *gen.Tag { | ||||
| 	return &gen.Tag{ | ||||
| 		Key:   k, | ||||
| 		VLong: &i, | ||||
| 		VType: gen.TagType_LONG, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getStringTag(k, s string) *gen.Tag { | ||||
| 	return &gen.Tag{ | ||||
| 		Key:   k, | ||||
| 		VStr:  &s, | ||||
| 		VType: gen.TagType_STRING, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getBoolTag(k string, b bool) *gen.Tag { | ||||
| 	return &gen.Tag{ | ||||
| 		Key:   k, | ||||
| 		VBool: &b, | ||||
| 		VType: gen.TagType_BOOL, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // jaegerBatchList transforms a slice of spans into a slice of jaeger Batch. | ||||
| func jaegerBatchList(ssl []sdktrace.ReadOnlySpan, defaultServiceName string) []*gen.Batch { | ||||
| 	if len(ssl) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	batchDict := make(map[attribute.Distinct]*gen.Batch) | ||||
| 
 | ||||
| 	for _, ss := range ssl { | ||||
| 		if ss == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		resourceKey := ss.Resource().Equivalent() | ||||
| 		batch, bOK := batchDict[resourceKey] | ||||
| 		if !bOK { | ||||
| 			batch = &gen.Batch{ | ||||
| 				Process: process(ss.Resource(), defaultServiceName), | ||||
| 				Spans:   []*gen.Span{}, | ||||
| 			} | ||||
| 		} | ||||
| 		batch.Spans = append(batch.Spans, spanToThrift(ss)) | ||||
| 		batchDict[resourceKey] = batch | ||||
| 	} | ||||
| 
 | ||||
| 	// Transform the categorized map into a slice | ||||
| 	batchList := make([]*gen.Batch, 0, len(batchDict)) | ||||
| 	for _, batch := range batchDict { | ||||
| 		batchList = append(batchList, batch) | ||||
| 	} | ||||
| 	return batchList | ||||
| } | ||||
| 
 | ||||
| // process transforms an OTel Resource into a jaeger Process. | ||||
| func process(res *resource.Resource, defaultServiceName string) *gen.Process { | ||||
| 	var process gen.Process | ||||
| 
 | ||||
| 	var serviceName attribute.KeyValue | ||||
| 	if res != nil { | ||||
| 		for iter := res.Iter(); iter.Next(); { | ||||
| 			if iter.Attribute().Key == semconv.ServiceNameKey { | ||||
| 				serviceName = iter.Attribute() | ||||
| 				// Don't convert service.name into tag. | ||||
| 				continue | ||||
| 			} | ||||
| 			if tag := keyValueToTag(iter.Attribute()); tag != nil { | ||||
| 				process.Tags = append(process.Tags, tag) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// If no service.name is contained in a Span's Resource, | ||||
| 	// that field MUST be populated from the default Resource. | ||||
| 	if serviceName.Value.AsString() == "" { | ||||
| 		serviceName = semconv.ServiceName(defaultServiceName) | ||||
| 	} | ||||
| 	process.ServiceName = serviceName.Value.AsString() | ||||
| 
 | ||||
| 	return &process | ||||
| } | ||||
							
								
								
									
										204
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/reconnecting_udp_client.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										204
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/reconnecting_udp_client.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,204 +0,0 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package jaeger // import "go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/go-logr/logr" | ||||
| ) | ||||
| 
 | ||||
| // reconnectingUDPConn is an implementation of udpConn that resolves hostPort every resolveTimeout, if the resolved address is | ||||
| // different than the current conn then the new address is dialed and the conn is swapped. | ||||
| type reconnectingUDPConn struct { | ||||
| 	// `sync/atomic` expects the first word in an allocated struct to be 64-bit | ||||
| 	// aligned on both ARM and x86-32. See https://goo.gl/zW7dgq for more details. | ||||
| 	bufferBytes int64 | ||||
| 	hostPort    string | ||||
| 	resolveFunc resolveFunc | ||||
| 	dialFunc    dialFunc | ||||
| 	logger      logr.Logger | ||||
| 
 | ||||
| 	connMtx   sync.RWMutex | ||||
| 	conn      *net.UDPConn | ||||
| 	destAddr  *net.UDPAddr | ||||
| 	closeChan chan struct{} | ||||
| } | ||||
| 
 | ||||
| type resolveFunc func(network string, hostPort string) (*net.UDPAddr, error) | ||||
| type dialFunc func(network string, laddr, raddr *net.UDPAddr) (*net.UDPConn, error) | ||||
| 
 | ||||
| // newReconnectingUDPConn returns a new udpConn that resolves hostPort every resolveTimeout, if the resolved address is | ||||
| // different than the current conn then the new address is dialed and the conn is swapped. | ||||
| func newReconnectingUDPConn(hostPort string, bufferBytes int, resolveTimeout time.Duration, resolveFunc resolveFunc, dialFunc dialFunc, logger logr.Logger) (*reconnectingUDPConn, error) { | ||||
| 	conn := &reconnectingUDPConn{ | ||||
| 		hostPort:    hostPort, | ||||
| 		resolveFunc: resolveFunc, | ||||
| 		dialFunc:    dialFunc, | ||||
| 		logger:      logger, | ||||
| 		closeChan:   make(chan struct{}), | ||||
| 		bufferBytes: int64(bufferBytes), | ||||
| 	} | ||||
| 
 | ||||
| 	if err := conn.attemptResolveAndDial(); err != nil { | ||||
| 		conn.logf("failed resolving destination address on connection startup, with err: %q. retrying in %s", err.Error(), resolveTimeout) | ||||
| 	} | ||||
| 
 | ||||
| 	go conn.reconnectLoop(resolveTimeout) | ||||
| 
 | ||||
| 	return conn, nil | ||||
| } | ||||
| 
 | ||||
| func (c *reconnectingUDPConn) logf(format string, args ...interface{}) { | ||||
| 	if c.logger != emptyLogger { | ||||
| 		c.logger.Info(format, args...) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (c *reconnectingUDPConn) reconnectLoop(resolveTimeout time.Duration) { | ||||
| 	ticker := time.NewTicker(resolveTimeout) | ||||
| 	defer ticker.Stop() | ||||
| 
 | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-c.closeChan: | ||||
| 			return | ||||
| 		case <-ticker.C: | ||||
| 			if err := c.attemptResolveAndDial(); err != nil { | ||||
| 				c.logf("%s", err.Error()) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (c *reconnectingUDPConn) attemptResolveAndDial() error { | ||||
| 	newAddr, err := c.resolveFunc("udp", c.hostPort) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to resolve new addr for host %q, with err: %w", c.hostPort, err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.connMtx.RLock() | ||||
| 	curAddr := c.destAddr | ||||
| 	c.connMtx.RUnlock() | ||||
| 
 | ||||
| 	// dont attempt dial if an addr was successfully dialed previously and, resolved addr is the same as current conn | ||||
| 	if curAddr != nil && newAddr.String() == curAddr.String() { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if err := c.attemptDialNewAddr(newAddr); err != nil { | ||||
| 		return fmt.Errorf("failed to dial newly resolved addr '%s', with err: %w", newAddr, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *reconnectingUDPConn) attemptDialNewAddr(newAddr *net.UDPAddr) error { | ||||
| 	connUDP, err := c.dialFunc(newAddr.Network(), nil, newAddr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if bufferBytes := int(atomic.LoadInt64(&c.bufferBytes)); bufferBytes != 0 { | ||||
| 		if err = connUDP.SetWriteBuffer(bufferBytes); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	c.connMtx.Lock() | ||||
| 	c.destAddr = newAddr | ||||
| 	// store prev to close later | ||||
| 	prevConn := c.conn | ||||
| 	c.conn = connUDP | ||||
| 	c.connMtx.Unlock() | ||||
| 
 | ||||
| 	if prevConn != nil { | ||||
| 		return prevConn.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Write calls net.udpConn.Write, if it fails an attempt is made to connect to a new addr, if that succeeds the write is retried before returning. | ||||
| func (c *reconnectingUDPConn) Write(b []byte) (int, error) { | ||||
| 	var bytesWritten int | ||||
| 	var err error | ||||
| 
 | ||||
| 	c.connMtx.RLock() | ||||
| 	conn := c.conn | ||||
| 	c.connMtx.RUnlock() | ||||
| 
 | ||||
| 	if conn == nil { | ||||
| 		// if connection is not initialized indicate this with err in order to hook into retry logic | ||||
| 		err = fmt.Errorf("UDP connection not yet initialized, an address has not been resolved") | ||||
| 	} else { | ||||
| 		bytesWritten, err = conn.Write(b) | ||||
| 	} | ||||
| 
 | ||||
| 	if err == nil { | ||||
| 		return bytesWritten, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// attempt to resolve and dial new address in case that's the problem, if resolve and dial succeeds, try write again | ||||
| 	if reconnErr := c.attemptResolveAndDial(); reconnErr == nil { | ||||
| 		c.connMtx.RLock() | ||||
| 		conn := c.conn | ||||
| 		c.connMtx.RUnlock() | ||||
| 
 | ||||
| 		return conn.Write(b) | ||||
| 	} | ||||
| 
 | ||||
| 	// return original error if reconn fails | ||||
| 	return bytesWritten, err | ||||
| } | ||||
| 
 | ||||
| // Close stops the reconnectLoop, then closes the connection via net.udpConn 's implementation. | ||||
| func (c *reconnectingUDPConn) Close() error { | ||||
| 	close(c.closeChan) | ||||
| 
 | ||||
| 	// acquire rw lock before closing conn to ensure calls to Write drain | ||||
| 	c.connMtx.Lock() | ||||
| 	defer c.connMtx.Unlock() | ||||
| 
 | ||||
| 	if c.conn != nil { | ||||
| 		return c.conn.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SetWriteBuffer defers to the net.udpConn SetWriteBuffer implementation wrapped with a RLock. if no conn is currently held | ||||
| // and SetWriteBuffer is called store bufferBytes to be set for new conns. | ||||
| func (c *reconnectingUDPConn) SetWriteBuffer(bytes int) error { | ||||
| 	var err error | ||||
| 
 | ||||
| 	c.connMtx.RLock() | ||||
| 	conn := c.conn | ||||
| 	c.connMtx.RUnlock() | ||||
| 
 | ||||
| 	if conn != nil { | ||||
| 		err = c.conn.SetWriteBuffer(bytes) | ||||
| 	} | ||||
| 
 | ||||
| 	if err == nil { | ||||
| 		atomic.StoreInt64(&c.bufferBytes, int64(bytes)) | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										339
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/uploader.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										339
									
								
								vendor/go.opentelemetry.io/otel/exporters/jaeger/uploader.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,339 +0,0 @@ | |||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
| 
 | ||||
| package jaeger // import "go.opentelemetry.io/otel/exporters/jaeger" | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/go-logr/logr" | ||||
| 	"github.com/go-logr/stdr" | ||||
| 
 | ||||
| 	gen "go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger" | ||||
| 	"go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift" | ||||
| ) | ||||
| 
 | ||||
| // batchUploader send a batch of spans to Jaeger. | ||||
| type batchUploader interface { | ||||
| 	upload(context.Context, *gen.Batch) error | ||||
| 	shutdown(context.Context) error | ||||
| } | ||||
| 
 | ||||
| // EndpointOption configures a Jaeger endpoint. | ||||
| type EndpointOption interface { | ||||
| 	newBatchUploader() (batchUploader, error) | ||||
| } | ||||
| 
 | ||||
| type endpointOptionFunc func() (batchUploader, error) | ||||
| 
 | ||||
| func (fn endpointOptionFunc) newBatchUploader() (batchUploader, error) { | ||||
| 	return fn() | ||||
| } | ||||
| 
 | ||||
| // WithAgentEndpoint configures the Jaeger exporter to send spans to a Jaeger agent | ||||
| // over compact thrift protocol. This will use the following environment variables for | ||||
| // configuration if no explicit option is provided: | ||||
| // | ||||
| // - OTEL_EXPORTER_JAEGER_AGENT_HOST is used for the agent address host | ||||
| // - OTEL_EXPORTER_JAEGER_AGENT_PORT is used for the agent address port | ||||
| // | ||||
| // The passed options will take precedence over any environment variables and default values | ||||
| // will be used if neither are provided. | ||||
| func WithAgentEndpoint(options ...AgentEndpointOption) EndpointOption { | ||||
| 	return endpointOptionFunc(func() (batchUploader, error) { | ||||
| 		cfg := agentEndpointConfig{ | ||||
| 			agentClientUDPParams{ | ||||
| 				AttemptReconnecting: true, | ||||
| 				Host:                envOr(envAgentHost, "localhost"), | ||||
| 				Port:                envOr(envAgentPort, "6831"), | ||||
| 			}, | ||||
| 		} | ||||
| 		for _, opt := range options { | ||||
| 			cfg = opt.apply(cfg) | ||||
| 		} | ||||
| 
 | ||||
| 		client, err := newAgentClientUDP(cfg.agentClientUDPParams) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		return &agentUploader{client: client}, nil | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // AgentEndpointOption configures a Jaeger agent endpoint. | ||||
| type AgentEndpointOption interface { | ||||
| 	apply(agentEndpointConfig) agentEndpointConfig | ||||
| } | ||||
| 
 | ||||
| type agentEndpointConfig struct { | ||||
| 	agentClientUDPParams | ||||
| } | ||||
| 
 | ||||
| type agentEndpointOptionFunc func(agentEndpointConfig) agentEndpointConfig | ||||
| 
 | ||||
| func (fn agentEndpointOptionFunc) apply(cfg agentEndpointConfig) agentEndpointConfig { | ||||
| 	return fn(cfg) | ||||
| } | ||||
| 
 | ||||
| // WithAgentHost sets a host to be used in the agent client endpoint. | ||||
| // This option overrides any value set for the | ||||
| // OTEL_EXPORTER_JAEGER_AGENT_HOST environment variable. | ||||
| // If this option is not passed and the env var is not set, "localhost" will be used by default. | ||||
| func WithAgentHost(host string) AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.Host = host | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithAgentPort sets a port to be used in the agent client endpoint. | ||||
| // This option overrides any value set for the | ||||
| // OTEL_EXPORTER_JAEGER_AGENT_PORT environment variable. | ||||
| // If this option is not passed and the env var is not set, "6831" will be used by default. | ||||
| func WithAgentPort(port string) AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.Port = port | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| var emptyLogger = logr.Logger{} | ||||
| 
 | ||||
| // WithLogger sets a logger to be used by agent client. | ||||
| // WithLogger and WithLogr will overwrite each other. | ||||
| func WithLogger(logger *log.Logger) AgentEndpointOption { | ||||
| 	return WithLogr(stdr.New(logger)) | ||||
| } | ||||
| 
 | ||||
| // WithLogr sets a logr.Logger to be used by agent client. | ||||
| // WithLogr and WithLogger will overwrite each other. | ||||
| func WithLogr(logger logr.Logger) AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.Logger = logger | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithDisableAttemptReconnecting sets option to disable reconnecting udp client. | ||||
| func WithDisableAttemptReconnecting() AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.AttemptReconnecting = false | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithAttemptReconnectingInterval sets the interval between attempts to re resolve agent endpoint. | ||||
| func WithAttemptReconnectingInterval(interval time.Duration) AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.AttemptReconnectInterval = interval | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithMaxPacketSize sets the maximum UDP packet size for transport to the Jaeger agent. | ||||
| func WithMaxPacketSize(size int) AgentEndpointOption { | ||||
| 	return agentEndpointOptionFunc(func(o agentEndpointConfig) agentEndpointConfig { | ||||
| 		o.MaxPacketSize = size | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithCollectorEndpoint defines the full URL to the Jaeger HTTP Thrift collector. This will | ||||
| // use the following environment variables for configuration if no explicit option is provided: | ||||
| // | ||||
| // - OTEL_EXPORTER_JAEGER_ENDPOINT is the HTTP endpoint for sending spans directly to a collector. | ||||
| // - OTEL_EXPORTER_JAEGER_USER is the username to be sent as authentication to the collector endpoint. | ||||
| // - OTEL_EXPORTER_JAEGER_PASSWORD is the password to be sent as authentication to the collector endpoint. | ||||
| // | ||||
| // The passed options will take precedence over any environment variables. | ||||
| // If neither values are provided for the endpoint, the default value of "http://localhost:14268/api/traces" will be used. | ||||
| // If neither values are provided for the username or the password, they will not be set since there is no default. | ||||
| func WithCollectorEndpoint(options ...CollectorEndpointOption) EndpointOption { | ||||
| 	return endpointOptionFunc(func() (batchUploader, error) { | ||||
| 		cfg := collectorEndpointConfig{ | ||||
| 			endpoint:   envOr(envEndpoint, "http://localhost:14268/api/traces"), | ||||
| 			username:   envOr(envUser, ""), | ||||
| 			password:   envOr(envPassword, ""), | ||||
| 			httpClient: http.DefaultClient, | ||||
| 		} | ||||
| 
 | ||||
| 		for _, opt := range options { | ||||
| 			cfg = opt.apply(cfg) | ||||
| 		} | ||||
| 
 | ||||
| 		return &collectorUploader{ | ||||
| 			endpoint:   cfg.endpoint, | ||||
| 			username:   cfg.username, | ||||
| 			password:   cfg.password, | ||||
| 			httpClient: cfg.httpClient, | ||||
| 		}, nil | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // CollectorEndpointOption configures a Jaeger collector endpoint. | ||||
| type CollectorEndpointOption interface { | ||||
| 	apply(collectorEndpointConfig) collectorEndpointConfig | ||||
| } | ||||
| 
 | ||||
| type collectorEndpointConfig struct { | ||||
| 	// endpoint for sending spans directly to a collector. | ||||
| 	endpoint string | ||||
| 
 | ||||
| 	// username to be used for authentication with the collector endpoint. | ||||
| 	username string | ||||
| 
 | ||||
| 	// password to be used for authentication with the collector endpoint. | ||||
| 	password string | ||||
| 
 | ||||
| 	// httpClient to be used to make requests to the collector endpoint. | ||||
| 	httpClient *http.Client | ||||
| } | ||||
| 
 | ||||
| type collectorEndpointOptionFunc func(collectorEndpointConfig) collectorEndpointConfig | ||||
| 
 | ||||
| func (fn collectorEndpointOptionFunc) apply(cfg collectorEndpointConfig) collectorEndpointConfig { | ||||
| 	return fn(cfg) | ||||
| } | ||||
| 
 | ||||
| // WithEndpoint is the URL for the Jaeger collector that spans are sent to. | ||||
| // This option overrides any value set for the | ||||
| // OTEL_EXPORTER_JAEGER_ENDPOINT environment variable. | ||||
| // If this option is not passed and the environment variable is not set, | ||||
| // "http://localhost:14268/api/traces" will be used by default. | ||||
| func WithEndpoint(endpoint string) CollectorEndpointOption { | ||||
| 	return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { | ||||
| 		o.endpoint = endpoint | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithUsername sets the username to be used in the authorization header sent for all requests to the collector. | ||||
| // This option overrides any value set for the | ||||
| // OTEL_EXPORTER_JAEGER_USER environment variable. | ||||
| // If this option is not passed and the environment variable is not set, no username will be set. | ||||
| func WithUsername(username string) CollectorEndpointOption { | ||||
| 	return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { | ||||
| 		o.username = username | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithPassword sets the password to be used in the authorization header sent for all requests to the collector. | ||||
| // This option overrides any value set for the | ||||
| // OTEL_EXPORTER_JAEGER_PASSWORD environment variable. | ||||
| // If this option is not passed and the environment variable is not set, no password will be set. | ||||
| func WithPassword(password string) CollectorEndpointOption { | ||||
| 	return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { | ||||
| 		o.password = password | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // WithHTTPClient sets the http client to be used to make request to the collector endpoint. | ||||
| func WithHTTPClient(client *http.Client) CollectorEndpointOption { | ||||
| 	return collectorEndpointOptionFunc(func(o collectorEndpointConfig) collectorEndpointConfig { | ||||
| 		o.httpClient = client | ||||
| 		return o | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // agentUploader implements batchUploader interface sending batches to | ||||
| // Jaeger through the UDP agent. | ||||
| type agentUploader struct { | ||||
| 	client *agentClientUDP | ||||
| } | ||||
| 
 | ||||
| var _ batchUploader = (*agentUploader)(nil) | ||||
| 
 | ||||
| func (a *agentUploader) shutdown(ctx context.Context) error { | ||||
| 	done := make(chan error, 1) | ||||
| 	go func() { | ||||
| 		done <- a.client.Close() | ||||
| 	}() | ||||
| 
 | ||||
| 	select { | ||||
| 	case <-ctx.Done(): | ||||
| 		// Prioritize not blocking the calling thread and just leak the | ||||
| 		// spawned goroutine to close the client. | ||||
| 		return ctx.Err() | ||||
| 	case err := <-done: | ||||
| 		return err | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (a *agentUploader) upload(ctx context.Context, batch *gen.Batch) error { | ||||
| 	return a.client.EmitBatch(ctx, batch) | ||||
| } | ||||
| 
 | ||||
| // collectorUploader implements batchUploader interface sending batches to | ||||
| // Jaeger through the collector http endpoint. | ||||
| type collectorUploader struct { | ||||
| 	endpoint   string | ||||
| 	username   string | ||||
| 	password   string | ||||
| 	httpClient *http.Client | ||||
| } | ||||
| 
 | ||||
| var _ batchUploader = (*collectorUploader)(nil) | ||||
| 
 | ||||
| func (c *collectorUploader) shutdown(ctx context.Context) error { | ||||
| 	// The Exporter will cancel any active exports and will prevent all | ||||
| 	// subsequent exports, so nothing to do here. | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *collectorUploader) upload(ctx context.Context, batch *gen.Batch) error { | ||||
| 	body, err := serialize(batch) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	req, err := http.NewRequestWithContext(ctx, "POST", c.endpoint, body) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if c.username != "" && c.password != "" { | ||||
| 		req.SetBasicAuth(c.username, c.password) | ||||
| 	} | ||||
| 	req.Header.Set("Content-Type", "application/x-thrift") | ||||
| 
 | ||||
| 	resp, err := c.httpClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	_, _ = io.Copy(io.Discard, resp.Body) | ||||
| 	if err = resp.Body.Close(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if resp.StatusCode < 200 || resp.StatusCode >= 300 { | ||||
| 		return fmt.Errorf("failed to upload traces; HTTP status code: %d", resp.StatusCode) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func serialize(obj thrift.TStruct) (*bytes.Buffer, error) { | ||||
| 	buf := thrift.NewTMemoryBuffer() | ||||
| 	if err := obj.Write(context.Background(), thrift.NewTBinaryProtocolConf(buf, &thrift.TConfiguration{})); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return buf.Buffer, nil | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue