From 3add8cba871c9114f4e6ed1449a97ef9a1ccec56 Mon Sep 17 00:00:00 2001 From: DeveloperJim <190177081@qq.com> Date: Tue, 4 Aug 2020 18:15:30 +0800 Subject: [PATCH 1/3] docs: update gamestatefulset, issue #0 --- .../doc/deploy/01-resources.yaml | 11 + .../doc/deploy/03-rbac.yaml | 2 +- .../backend/v4http/customresource.go | 6 +- .../bcs-clb-controller/pkg/qcloud/meta.go | 2 +- .../cmd/bscp-bcs-sidecar/service/puller.go | 2 +- .../api-gateway\346\226\271\346\241\210.md" | 75 +- docs/specification/go-micro.md | 183 + docs/specification/license-header.txt | 12 + go.sum | 1 + .../bcs-k8s-watch/bcs-k8s-watch.json.template | 4 +- install/patch/nginx-1.15.8-http2-spdy.patch | 6301 +++++++++++++++++ 11 files changed, 6586 insertions(+), 13 deletions(-) create mode 100644 docs/specification/go-micro.md create mode 100644 install/patch/nginx-1.15.8-http2-spdy.patch diff --git a/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/01-resources.yaml b/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/01-resources.yaml index 4f5e1074e6..94fb15b423 100644 --- a/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/01-resources.yaml +++ b/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/01-resources.yaml @@ -5,6 +5,17 @@ metadata: release: gamestatefulset name: gamestatefulsets.tkex.tencent.com spec: + additionalPrinterColumns: + - JSONPath: .spec.replicas + name: Replicas + type: integer + - JSONPath: .status.readyReplicas + name: ReadyReplicas + type: integer + - JSONPath: .metadata.creationTimestamp + description: Age of the gamestatefulset + name: Age + type: date group: tkex.tencent.com names: kind: GameStatefulSet diff --git a/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/03-rbac.yaml b/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/03-rbac.yaml index 0520358cb5..5776e90c0f 100644 --- a/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/03-rbac.yaml +++ b/bcs-k8s/bcs-gamestatefulset-operator/doc/deploy/03-rbac.yaml @@ -38,7 +38,7 @@ rules: - update - watch - delete -- apiGroups: ["tkex"] +- apiGroups: ["tkex.tencent.com"] resources: - gamestatefulsets - gamestatefulsets/status diff --git a/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/customresource.go b/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/customresource.go index 65a2aaa991..fb7280e714 100644 --- a/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/customresource.go +++ b/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/customresource.go @@ -17,7 +17,6 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/Tencent/bk-bcs/bcs-common/common/blog" "io" "io/ioutil" "net/http" @@ -27,6 +26,8 @@ import ( "strconv" "strings" + "github.com/Tencent/bk-bcs/bcs-common/common/blog" + simplejson "github.com/bitly/go-simplejson" restful "github.com/emicklei/go-restful" corev1 "k8s.io/api/core/v1" @@ -130,6 +131,7 @@ func (proxy *kubeProxy) customResourceNamespaceValidate(req *http.Request) { if req.Method != http.MethodPost { return } + //todo(DeveloperJim): fix panic when all body is empty //validate namespace exist allBytes, err := ioutil.ReadAll(req.Body) if err != nil { @@ -145,7 +147,7 @@ func (proxy *kubeProxy) customResourceNamespaceValidate(req *http.Request) { } jsonObj, err := simplejson.NewJson(allBytes) if err != nil { - blog.Errorf("Custom Resource POST data is not expected json, %s. URL: %s", err.Error(), req.URL.String()) + blog.Errorf("Custom Resource POST data is not expected json, %s. URL: %s. origin data: %s", err.Error(), req.URL.String(), string(allBytes)) return } meta := jsonObj.Get("metadata") diff --git a/bcs-services/bcs-clb-controller/pkg/qcloud/meta.go b/bcs-services/bcs-clb-controller/pkg/qcloud/meta.go index 004ddc96f4..5c3df7daf5 100644 --- a/bcs-services/bcs-clb-controller/pkg/qcloud/meta.go +++ b/bcs-services/bcs-clb-controller/pkg/qcloud/meta.go @@ -78,7 +78,7 @@ func (l GroupList) EncodeValues(key string, urlv *url.Values) error { //param method: http method, GET or POST //param url: qcloud request url //param obj: object to encode, -//example data before hamcSHA1 : "GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA&SignatureMethod=HmacSHA1&Timestamp=1465185768" +//example data before hamcSHA1 : "GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=xxxxxxxxxx&SignatureMethod=HmacSHA1&Timestamp=1465185768" func Signature(key, method, url string, obj interface{}) (string, error) { if obj == nil { return "", fmt.Errorf("Can not signature nil object") diff --git a/bmsf-configuration/cmd/bscp-bcs-sidecar/service/puller.go b/bmsf-configuration/cmd/bscp-bcs-sidecar/service/puller.go index 2079f96925..7c40b2c4a2 100644 --- a/bmsf-configuration/cmd/bscp-bcs-sidecar/service/puller.go +++ b/bmsf-configuration/cmd/bscp-bcs-sidecar/service/puller.go @@ -348,7 +348,7 @@ func (p *Puller) pulling() { // stop pulling signal. case <-p.stopCh: logger.Warn("Puller[%s %s][%+v]-pulling| stop pulling now", p.businessName, p.appName, p.cfgsetid) - // just return, break here is shit. + // just return, Puller is asked to exist. return // handle publishing notifications. diff --git "a/docs/features/bcs-api-gateway/api-gateway\346\226\271\346\241\210.md" "b/docs/features/bcs-api-gateway/api-gateway\346\226\271\346\241\210.md" index 6d6ec5935c..cc4f102a28 100644 --- "a/docs/features/bcs-api-gateway/api-gateway\346\226\271\346\241\210.md" +++ "b/docs/features/bcs-api-gateway/api-gateway\346\226\271\346\241\210.md" @@ -298,9 +298,70 @@ curl -XPOST localhost:8001/routes/kube-agent-tunnel/plugins \ -d"config.token=xxxxxxxxxxxxxxxxxxxxxx" ``` +### openresty支持spdy + +kubectl exec命令使用spdy协议,kong仅默认支持http2,需要重编openresty, kong + +版本信息: +* kong:2.0.4 +* openresty:1.15.8.3 + +编译依赖: +* 外网访问 +* docker +* docker-compose +* nginx-1.15.8-http2-spdy.patch + +编译工具: +* github.com/Kong/kong-build-tools.git,`4.8.1` +* github.com/Kong/kong,`2.0.4` + +```shell +export http_proxy=http://someproxy.com +export https_proxy=http://someproxy.com + +yum install docker-compose + +#准备资源 +cd ~ +git clone github.com/Kong/kong-build-tools +cd ~/kong-build-tools && git checkout 4.8.1 +git clone github.com/Kong/kong +cd ~/kong && git checkout 2.0.4 + +#spdy patch +cp $GOPATH/src/bk-bcs/install/patch/nginx-1.15.8-http2-spdy.patch ~/kong-build-tools/openresty-patches/patches/1.15.8.3 +cd ~/kong-build-tools/openresty-build-tools +sed -i '434a\ "--with-http_spdy_module"' kong-ngx-build +``` + +额外说明:如果需要http_proxy才能访问外网,需要调整kong-build-tools/Makefile中docker build参数, +增加--build-arg http_proxy=http://someproxy.com 等参数。 + +编译kong时需要依赖一些lua组件,部分组件是使用git协议下载的,不支持http_proxy设置。需要调整为http协议,为build-kong.sh增加 +```shell +git config --global url."https://github.com/".insteadOf git@github.com: +git config --global url."https://".insteadOf git:// +``` + +使用centos:7镜像构建kong rpm包 +```shell +cd ~/kong-build-tools +make package-kong RESTY_IMAGE_BASE=centos RESTY_IMAGE_TAG=7 PACKAGE_TYPE=rpm +... +... +... +#编译通过后输出在output目录下 +ls -lhrt ./output/ +total 25M +-rw-r--r-- 1 root root 25M Jul 22 17:43 kong-2.0.4.el7.amd64.rpm +``` + + + ## 正式部署参考流程 -以下为手动流程部署参考,实际部署已Job自动化标准任务或者蓝盾流水线为准。 +以下为手动流程部署参考,实际部署以Job自动化标准任务或者蓝盾流水线为准。 我们需要额外部署kong,bcs-gateway-discovery与bcs-user-manager。二进制发布包目录假设: @@ -386,11 +447,11 @@ kong migrations bootstrap -c /etc/kong/kong.conf kong start -c /etc/kong/kong.conf ``` -### 部署bcs-cluster-manager +### 部署bcs-user-manager -bcs-cluster-manager重构了bcs-api中关于集群和用户管理功能,计划在1.17.x,1.18.x,1.19.x是保持兼容的。 -所以,bcs-cluster-manager与bcs-api共享mysql数据库数据,并且bcs-api中跨云穿透代理的功能默认会合并到该模块, -实际部署时,尽量保障bcs-cluster-manager与kong在相同可用区/同城同园区,避免网络抖动带来跨云穿透长链中断重连。 +bcs-user-manager重构了bcs-api中关于集群和用户管理功能,计划在1.17.x,1.18.x,1.19.x是保持兼容的。 +所以,bcs-user-manager与bcs-api共享mysql数据库数据,并且bcs-api中跨云穿透代理的功能默认会合并到该模块, +实际部署时,尽量保障bcs-user-manager与kong在相同可用区/同城同园区,避免网络抖动带来跨云穿透长链中断重连。 配置文件模板请参照[这里](https://github.com/Tencent/bk-bcs/blob/master/install/conf/bcs-services/bcs-user-manager/bcs-user-manager.json.template)。 @@ -429,7 +490,7 @@ client配置 #client配置后 mkdir -p /var/bcs/ cd /data/bcs/bcs-client -cp bcs.conf.template /var/bcs/ +cp bcs.conf.template /var/bcs/bcs.conf #初始化用户进行授权,主要用于 #* 其他系统调用bcs-api-gateway @@ -499,4 +560,4 @@ do done ``` -重启bcs-gateway-discovery即可。 \ No newline at end of file +重启bcs-gateway-discovery即可。 diff --git a/docs/specification/go-micro.md b/docs/specification/go-micro.md new file mode 100644 index 0000000000..7c6a5c78fe --- /dev/null +++ b/docs/specification/go-micro.md @@ -0,0 +1,183 @@ +# go-micro使用指引 + +解决问题: + +* 优化服务发现,保障体系基础能力 +* 引入服务订阅能力,弥补Service服务能力短板,强化数据体系 +* 规范各模块开发,强化各模块SDK能力 +* 持续优化service层容器化 + +待细化问题: + +* bcs-gateway-discovery两套服务发现机制兼容问题 +* bcs-api-gateway服务映射兼容问题 +* 服务发现体系切换问题 + +## 框架使用原则 + +* go-micro service实现需要使用grpc +* 对接grpc-gateway实现http转发 +* 日志插件不限定,推荐BCS原有日志组件或者logrus +* 服务发现基于etcd,复用BCS Service层etcd集群 +* 事件订阅限定:rabbitMQ、go-nats + +## go-micro框架 + +* registry:服务发现抽象 + * etcd,zookeeper,dns,consul,kubenetes、gossip +* selector:负载均衡抽象 +* store:kv存储抽象 + * consul,etcd,memcached,mysql,redis +* config:配置动态加载与监听 + * 支持文件,etcd,consul,vault,configmap +* broker:消息中间件 + * google、aws、kafka、rabbitMQ,redis +* tracer:链路追踪 + * zipkin,jaeger + +## 使用时注意问题 + +* 使用版本:推荐2.9.x +* 版本问题:etcd与grpc版本相互影响 + +## 基础环境构建 + +统一版本: + +* protoc: 3.12.3 +* micro: v2.9.3 +* go-micro:v2.9.1 +* protoc-gen-go: v1.3.2 +* protoc-gen-micro: v2.9.1 +* protoc-grpc-gateway: v1.14.6 +* protoc-gen-swagger: v1.14.6 + +**注意**,因为grpc与etcd版本存在冲突,protoc-gen-go不能超过1.3.2 + +安装micro命令,[下载链接](https://github.com/micro/micro/releases/download/v2.9.3/micro-v2.9.3-linux-amd64.tar.gz) + +安装protobuf,[下载链接](https://github.com/protocolbuffers/protobuf/releases/download/v3.12.3/protoc-3.12.3-linux-x86_64.zip) + +建议: + +* protoc安装在/usr/local/bin +* google定义建议安装在项目的third_party目录 + +安装protoc-gen-go, protoc-gen-micro + +```shell +#默认安装在$GOPATH/bin下 +export GO111MODULE=on +go get -v github.com/micro/micro/v2/cmd/protoc-gen-micro@master +go get -v github.com/golang/protobuf/protoc-gen-go@v1.3.2 +go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@v1.14.6 +go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@v1.14.6 + +export PATH=$PATH:$GOPATH/bin +``` + +## 项目初始化示例 + +```shell +micro new bcs-data-manager +Creating service go.micro.service.bcs-data-manager in bcs-data-manager + +. +├── main.go +├── generate.go +├── plugin.go +├── handler +│   └── bcs-data-manager.go +├── subscriber +│   └── bcs-data-manager.go +├── proto +│   └── bcs-data-manager +│   └── bcs-data-manager.proto +├── Dockerfile +├── Makefile +├── README.md +├── .gitignore +└── go.mod +``` + +* proto:放置service协议定义 +* subscriber:消息订阅相关实现,依赖proto定义,如无需使用直接删除 +* handler:service对外提供服务接口实现,消息定义依赖proto定义 + +## 服务定义 + +基础定义调整: + +* proto/bcs-data-manager下proto调整,package调整为bcsdatamanager +* 增加go_package信息定义:实际go package的名称为bcsdatamanager + +```protoc +syntax = "proto3"; + +package bcsdatamanager; + +option go_package = "proto/bcs-data-manager;bcsdatamanager"; +``` + +定义数据与grpc服务 + +```protoc +service BcsDataManager { + rpc Call(Request) returns (Response) {} + rpc Stream(StreamingRequest) returns (stream StreamingResponse) {} + rpc PingPong(stream Ping) returns (stream Pong) {} +} +``` + +## http服务定义(可选) + +如果需要对外提供http API接口,并集成至bcs-api-gateway,需要使用grpc-gateway屏蔽grpc接口, +对外提供http API接口。 + +grpc-gateway需要依赖google定义的[annotation](https://github.com/googleapis/googleapis), +需要提前下载,建议放置在项目下的third_party目录下,生成gateway实现时需要引用。 + +```protoc +//grpc-gateway requirement +import "google/api/annotations.proto"; + +service BcsDataManager { + rpc Call(Request) returns (Response) { + option (google.api.http) = { + post: "/v1/hello" + body: "*" + }; + } + rpc Stream(StreamingRequest) returns (stream StreamingResponse) { + option (google.api.http) = { + post: "/v1/stream" + body: "*" + }; + } + rpc PingPong(stream Ping) returns (stream Pong) { + option (google.api.http) = { + post: "/v1/pingpong" + body: "*" + }; + } +} +``` + +gateway实现代码生成,建议合入Makefile中 + +```shell +protoc -I./third_party/ --proto_path=. --grpc-gateway_out=logtostderr=true:. --micro_out=. --go_out=plugins=grpc:. proto/bcs-data-manager/bcs-data-manager.proto +``` + +相对于非gateway版本,grpc-gateway了以下部分代码: + +* bcs-data-manager.pb.go中增加了grpc原生client与Server的定义 +* 增加了文件bcs-data-manager.pb.gw.go,用于实现http至grpc server的动态映射 + +## 命令行参数/配置文件 + +默认集成bcs-common/conf + +## 日志使用 + +默认集成bcs-common/blog diff --git a/docs/specification/license-header.txt b/docs/specification/license-header.txt index e69de29bb2..a620e80a06 100644 --- a/docs/specification/license-header.txt +++ b/docs/specification/license-header.txt @@ -0,0 +1,12 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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. + * + */ diff --git a/go.sum b/go.sum index ea660eb43a..4656edac1f 100644 --- a/go.sum +++ b/go.sum @@ -263,6 +263,7 @@ github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7 h1:ux/56T2xqZO/ github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jinzhu/gorm v1.9.2 h1:lCvgEaqe/HVE+tjAR2mt4HbbHAZsQOv3XAZiEZV37iw= github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= diff --git a/install/conf/bcs-k8s-master/bcs-k8s-watch/bcs-k8s-watch.json.template b/install/conf/bcs-k8s-master/bcs-k8s-watch/bcs-k8s-watch.json.template index d245a120d5..dffb6d52d2 100644 --- a/install/conf/bcs-k8s-master/bcs-k8s-watch/bcs-k8s-watch.json.template +++ b/install/conf/bcs-k8s-master/bcs-k8s-watch/bcs-k8s-watch.json.template @@ -11,7 +11,9 @@ "cert-file": "${clientCertFile}", "key-file": "${clientKeyFile}" }, - "is-external": ${kubeWatchExternal} + "is-external": ${kubeWatchExternal}, + "custom-storage-endpoints": "${customStorage}", + "custom-netservice-endpoints": "${customNetService}" }, "k8s": { "master": "${kubeMaster}", diff --git a/install/patch/nginx-1.15.8-http2-spdy.patch b/install/patch/nginx-1.15.8-http2-spdy.patch new file mode 100644 index 0000000000..e52aab8dfa --- /dev/null +++ b/install/patch/nginx-1.15.8-http2-spdy.patch @@ -0,0 +1,6301 @@ +diff --git a/nginx-1.15.8/auto/modules b/nginx-1.15.8/auto/modules +index f00dc24..d551de8 100644 +--- a/nginx-1.15.8/auto/modules ++++ b/nginx-1.15.8/auto/modules +@@ -135,6 +135,7 @@ if [ $HTTP = YES ]; then + # ngx_http_header_filter + # ngx_http_chunked_filter + # ngx_http_v2_filter ++ # ngx_http_spdy_filter + # ngx_http_range_header_filter + # ngx_http_gzip_filter + # ngx_http_postpone_filter +@@ -167,6 +168,7 @@ if [ $HTTP = YES ]; then + ngx_http_header_filter_module \ + ngx_http_chunked_filter_module \ + ngx_http_v2_filter_module \ ++ ngx_http_spdy_filter_module \ + ngx_http_range_header_filter_module \ + ngx_http_gzip_filter_module \ + ngx_http_postpone_filter_module \ +@@ -228,6 +230,19 @@ if [ $HTTP = YES ]; then + . auto/module + fi + ++ if [ $HTTP_SPDY = YES ]; then ++ have=NGX_HTTP_SPDY . auto/have ++ USE_ZLIB=YES ++ ngx_module_name=ngx_http_spdy_filter_module ++ ngx_module_incs= ++ ngx_module_deps= ++ ngx_module_srcs=src/http/ngx_http_spdy_filter_module.c ++ ngx_module_libs= ++ ngx_module_link=$HTTP_SPDY ++ ++ . auto/module ++ fi ++ + if :; then + ngx_module_name=ngx_http_range_header_filter_module + ngx_module_incs= +@@ -439,6 +454,19 @@ if [ $HTTP = YES ]; then + . auto/module + fi + ++ if [ $HTTP_SPDY = YES ]; then ++ have=NGX_HTTP_SPDY . auto/have ++ ngx_module_name=ngx_http_spdy_module ++ ngx_module_incs=src/http ++ ngx_module_deps="src/http/ngx_http_spdy.h src/http/ngx_http_spdy_module.h" ++ ngx_module_srcs="src/http/ngx_http_spdy.c \ ++ src/http/ngx_http_spdy_module.c" ++ ngx_module_libs= ++ ngx_module_link=$HTTP_SPDY ++ ++ . auto/module ++ fi ++ + if :; then + ngx_module_name=ngx_http_static_module + ngx_module_incs= +diff --git a/nginx-1.15.8/auto/options b/nginx-1.15.8/auto/options +index 2de0504..42a9b56 100644 +--- a/nginx-1.15.8/auto/options ++++ b/nginx-1.15.8/auto/options +@@ -67,6 +67,7 @@ HTTP_CHARSET=YES + HTTP_GZIP=YES + HTTP_SSL=NO + HTTP_V2=NO ++HTTP_SPDY=NO + HTTP_SSI=YES + HTTP_POSTPONE=NO + HTTP_REALIP=NO +@@ -235,6 +236,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated" + + --with-http_ssl_module) HTTP_SSL=YES ;; + --with-http_v2_module) HTTP_V2=YES ;; ++ --with-http_spdy_module) HTTP_SPDY=YES ;; + --with-http_realip_module) HTTP_REALIP=YES ;; + --with-http_addition_module) HTTP_ADDITION=YES ;; + --with-http_xslt_module) HTTP_XSLT=YES ;; +@@ -454,6 +456,7 @@ cat << END + + --with-http_ssl_module enable ngx_http_ssl_module + --with-http_v2_module enable ngx_http_v2_module ++ --with-http_spdy_module enable ngx_http_spdy_module + --with-http_realip_module enable ngx_http_realip_module + --with-http_addition_module enable ngx_http_addition_module + --with-http_xslt_module enable ngx_http_xslt_module +diff --git a/nginx-1.15.8/src/core/ngx_connection.h b/nginx-1.15.8/src/core/ngx_connection.h +index 5405962..f4d3a5d 100644 +--- a/nginx-1.15.8/src/core/ngx_connection.h ++++ b/nginx-1.15.8/src/core/ngx_connection.h +@@ -119,6 +119,7 @@ typedef enum { + #define NGX_LOWLEVEL_BUFFERED 0x0f + #define NGX_SSL_BUFFERED 0x01 + #define NGX_HTTP_V2_BUFFERED 0x02 ++#define NGX_SPDY_BUFFERED 0x04 + + + struct ngx_connection_s { +diff --git a/nginx-1.15.8/src/http/modules/ngx_http_ssl_module.c b/nginx-1.15.8/src/http/modules/ngx_http_ssl_module.c +index 9e243ea..ce24687 100644 +--- a/nginx-1.15.8/src/http/modules/ngx_http_ssl_module.c ++++ b/nginx-1.15.8/src/http/modules/ngx_http_ssl_module.c +@@ -368,10 +368,10 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + #if (NGX_DEBUG) + unsigned int i; + #endif +-#if (NGX_HTTP_V2) ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY) + ngx_http_connection_t *hc; + #endif +-#if (NGX_HTTP_V2 || NGX_DEBUG) ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY || NGX_DEBUG) + ngx_connection_t *c; + + c = ngx_ssl_get_connection(ssl_conn); +@@ -385,9 +385,20 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + } + #endif + +-#if (NGX_HTTP_V2) ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY) + hc = c->data; ++#endif + ++#if (NGX_HTTP_V2 && NGX_HTTP_SPDY) ++ if (hc->addr_conf->http2 && hc->addr_conf->spdy) { ++ srv = (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE ++ NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; ++ srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_SPDY_NPN_ADVERTISE ++ NGX_HTTP_NPN_ADVERTISE) - 1; ++ ++ } else ++#endif ++#if (NGX_HTTP_V2) + if (hc->addr_conf->http2) { + srv = + (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; +@@ -395,6 +406,13 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + + } else + #endif ++#if (NGX_HTTP_SPDY) ++ if (hc->addr_conf->spdy) { ++ srv = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; ++ srvlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; ++ ++ } else ++#endif + { + srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1; +@@ -422,19 +440,32 @@ static int + ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, + const unsigned char **out, unsigned int *outlen, void *arg) + { +-#if (NGX_HTTP_V2 || NGX_DEBUG) ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY || NGX_DEBUG) + ngx_connection_t *c; + + c = ngx_ssl_get_connection(ssl_conn); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised"); + #endif + +-#if (NGX_HTTP_V2) ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY) + { + ngx_http_connection_t *hc; + + hc = c->data; ++#endif + ++#if (NGX_HTTP_V2 && NGX_HTTP_SPDY) ++ if (hc->addr_conf->http2 && hc->addr_conf->spdy) { ++ *out = (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE ++ NGX_SPDY_NPN_ADVERTISE ++ NGX_HTTP_NPN_ADVERTISE; ++ *outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_SPDY_NPN_ADVERTISE ++ NGX_HTTP_NPN_ADVERTISE) - 1; ++ ++ return SSL_TLSEXT_ERR_OK; ++ } else ++#endif ++#if (NGX_HTTP_V2) + if (hc->addr_conf->http2) { + *out = + (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; +@@ -442,6 +473,20 @@ ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, + + return SSL_TLSEXT_ERR_OK; + } ++#endif ++#if (NGX_HTTP_V2 && NGX_HTTP_SPDY) ++ else ++#endif ++#if (NGX_HTTP_SPDY) ++ if (hc->addr_conf->spdy) { ++ *out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; ++ *outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; ++ ++ return SSL_TLSEXT_ERR_OK; ++ } ++#endif ++ ++#if (NGX_HTTP_V2 || NGX_HTTP_SPDY) + } + #endif + +diff --git a/nginx-1.15.8/src/http/ngx_http.c b/nginx-1.15.8/src/http/ngx_http.c +index 85e2399..f0d61fe 100644 +--- a/nginx-1.15.8/src/http/ngx_http.c ++++ b/nginx-1.15.8/src/http/ngx_http.c +@@ -1203,6 +1203,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + #if (NGX_HTTP_V2) + ngx_uint_t http2; + #endif ++#if (NGX_HTTP_SPDY) ++ ngx_uint_t spdy; ++#endif + + /* + * we cannot compare whole sockaddr struct's as kernel +@@ -1238,6 +1241,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + #if (NGX_HTTP_V2) + http2 = lsopt->http2 || addr[i].opt.http2; + #endif ++#if (NGX_HTTP_SPDY) ++ spdy = lsopt->spdy || addr[i].opt.spdy; ++#endif + + if (lsopt->set) { + +@@ -1272,6 +1278,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + #if (NGX_HTTP_V2) + addr[i].opt.http2 = http2; + #endif ++#if (NGX_HTTP_SPDY) ++ addr[i].opt.spdy = spdy; ++#endif + + return NGX_OK; + } +@@ -1313,6 +1322,18 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + lsopt->addr); + } + ++#endif ++ ++#if (NGX_HTTP_SPDY && NGX_HTTP_SSL \ ++ && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \ ++ && !defined TLSEXT_TYPE_next_proto_neg) ++ if (lsopt->spdy && lsopt->ssl) { ++ ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ++ "nginx was built with OpenSSL that lacks ALPN " ++ "and NPN support, SPDY is not enabled for %s", ++ lsopt->addr); ++ } ++ + #endif + + addr = ngx_array_push(&port->addrs); +@@ -1803,6 +1824,9 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport, + #endif + #if (NGX_HTTP_V2) + addrs[i].conf.http2 = addr[i].opt.http2; ++#endif ++#if (NGX_HTTP_SPDY) ++ addrs[i].conf.spdy = addr[i].opt.spdy; + #endif + addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; + +@@ -1868,6 +1892,9 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, + #endif + #if (NGX_HTTP_V2) + addrs6[i].conf.http2 = addr[i].opt.http2; ++#endif ++#if (NGX_HTTP_SPDY) ++ addrs6[i].conf.spdy = addr[i].opt.spdy; + #endif + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; + +diff --git a/nginx-1.15.8/src/http/ngx_http.h b/nginx-1.15.8/src/http/ngx_http.h +index afab4f6..d3855f6 100644 +--- a/nginx-1.15.8/src/http/ngx_http.h ++++ b/nginx-1.15.8/src/http/ngx_http.h +@@ -19,6 +19,9 @@ typedef struct ngx_http_cache_s ngx_http_cache_t; + typedef struct ngx_http_file_cache_s ngx_http_file_cache_t; + typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t; + typedef struct ngx_http_chunked_s ngx_http_chunked_t; ++#if (NGX_HTTP_SPDY) ++typedef struct ngx_http_spdy_stream_s ngx_http_spdy_stream_t; ++#endif + typedef struct ngx_http_v2_stream_s ngx_http_v2_stream_t; + + typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r, +@@ -38,6 +41,9 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r, + #if (NGX_HTTP_V2) + #include + #endif ++#if (NGX_HTTP_SPDY) ++#include ++#endif + #if (NGX_HTTP_CACHE) + #include + #endif +diff --git a/nginx-1.15.8/src/http/ngx_http_core_module.c b/nginx-1.15.8/src/http/ngx_http_core_module.c +index 81314a3..f91062c 100644 +--- a/nginx-1.15.8/src/http/ngx_http_core_module.c ++++ b/nginx-1.15.8/src/http/ngx_http_core_module.c +@@ -1952,6 +1952,13 @@ ngx_http_gzip_ok(ngx_http_request_t *r) + return NGX_DECLINED; + } + ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ r->gzip_ok = 1; ++ return NGX_OK; ++ } ++#endif ++ + ae = r->headers_in.accept_encoding; + if (ae == NULL) { + return NGX_DECLINED; +@@ -2311,6 +2318,9 @@ ngx_http_subrequest(ngx_http_request_t *r, + #if (NGX_HTTP_V2) + sr->stream = r->stream; + #endif ++#if (NGX_HTTP_SPDY) ++ sr->spdy_stream = r->spdy_stream; ++#endif + + sr->method = NGX_HTTP_GET; + sr->http_version = r->http_version; +@@ -4012,11 +4022,15 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) + } + + if (ngx_strcmp(value[n].data, "spdy") == 0) { +- ngx_conf_log_error(NGX_LOG_WARN, cf, 0, +- "invalid parameter \"spdy\": " +- "ngx_http_spdy_module was superseded " +- "by ngx_http_v2_module"); ++#if (NGX_HTTP_SPDY) ++ lsopt.spdy = 1; + continue; ++#else ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ++ "the \"spdy\" parameter requires " ++ "ngx_http_spdy_module"); ++ return NGX_CONF_ERROR; ++#endif + } + + if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) { +diff --git a/nginx-1.15.8/src/http/ngx_http_core_module.h b/nginx-1.15.8/src/http/ngx_http_core_module.h +index 4c6da7c..b21cc07 100644 +--- a/nginx-1.15.8/src/http/ngx_http_core_module.h ++++ b/nginx-1.15.8/src/http/ngx_http_core_module.h +@@ -74,6 +74,9 @@ typedef struct { + unsigned wildcard:1; + unsigned ssl:1; + unsigned http2:1; ++#if (NGX_HTTP_SPDY) ++ unsigned spdy:1; ++#endif + #if (NGX_HAVE_INET6) + unsigned ipv6only:1; + #endif +@@ -238,6 +241,9 @@ struct ngx_http_addr_conf_s { + + unsigned ssl:1; + unsigned http2:1; ++#if (NGX_HTTP_SPDY) ++ unsigned spdy:1; ++#endif + unsigned proxy_protocol:1; + }; + +diff --git a/nginx-1.15.8/src/http/ngx_http_request.c b/nginx-1.15.8/src/http/ngx_http_request.c +index 236ac16..57d3db7 100644 +--- a/nginx-1.15.8/src/http/ngx_http_request.c ++++ b/nginx-1.15.8/src/http/ngx_http_request.c +@@ -324,6 +324,11 @@ ngx_http_init_connection(ngx_connection_t *c) + rev->handler = ngx_http_wait_request_handler; + c->write->handler = ngx_http_empty_handler; + ++#if (NGX_HTTP_SPDY) ++ if (hc->addr_conf->spdy) { ++ rev->handler = ngx_http_spdy_init; ++ } ++#endif + #if (NGX_HTTP_V2) + if (hc->addr_conf->http2) { + rev->handler = ngx_http_v2_init; +@@ -815,6 +820,34 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) + } + #endif + ++#if (NGX_HTTP_SPDY \ ++ && (defined TLSEXT_TYPE_application_layer_protocol_negotiation \ ++ || defined TLSEXT_TYPE_next_proto_neg)) ++ { ++ unsigned int len; ++ const unsigned char *data; ++ static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED); ++ ++#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation ++ SSL_get0_alpn_selected(c->ssl->connection, &data, &len); ++ ++#ifdef TLSEXT_TYPE_next_proto_neg ++ if (len == 0) { ++ SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); ++ } ++#endif ++ ++#else /* TLSEXT_TYPE_next_proto_neg */ ++ SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); ++#endif ++ ++ if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) { ++ ngx_http_spdy_init(c->read); ++ return; ++ } ++ } ++#endif ++ + c->log->action = "waiting for request"; + + c->read->handler = ngx_http_wait_request_handler; +@@ -2599,6 +2632,12 @@ ngx_http_finalize_connection(ngx_http_request_t *r) + return; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ ngx_http_close_request(r, 0); ++ return; ++ } ++#endif + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + +@@ -2807,6 +2846,18 @@ ngx_http_test_reading(ngx_http_request_t *r) + return; + } + ++#endif ++#if (NGX_HTTP_SPDY) ++ ++ if (r->spdy_stream) { ++ if (c->error) { ++ err = 0; ++ goto closed; ++ } ++ ++ return; ++ } ++ + #endif + + #if (NGX_HAVE_KQUEUE) +@@ -3475,6 +3526,12 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) + return; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ ngx_http_spdy_close_stream(r->spdy_stream, rc); ++ return; ++ } ++#endif + + ngx_http_free_request(r, rc); + ngx_http_close_connection(c); +diff --git a/nginx-1.15.8/src/http/ngx_http_request.h b/nginx-1.15.8/src/http/ngx_http_request.h +index fce70ef..d960168 100644 +--- a/nginx-1.15.8/src/http/ngx_http_request.h ++++ b/nginx-1.15.8/src/http/ngx_http_request.h +@@ -432,6 +432,9 @@ struct ngx_http_request_s { + int *captures; + u_char *captures_data; + #endif ++#if (NGX_HTTP_SPDY) ++ ngx_http_spdy_stream_t *spdy_stream; ++#endif + + size_t limit_rate; + size_t limit_rate_after; +diff --git a/nginx-1.15.8/src/http/ngx_http_request_body.c b/nginx-1.15.8/src/http/ngx_http_request_body.c +index 67a8cbf..7aa7c89 100644 +--- a/nginx-1.15.8/src/http/ngx_http_request_body.c ++++ b/nginx-1.15.8/src/http/ngx_http_request_body.c +@@ -85,6 +85,12 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, + goto done; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ rc = ngx_http_spdy_read_request_body(r, post_handler); ++ goto done; ++ } ++#endif + + preread = r->header_in->last - r->header_in->pos; + +@@ -527,6 +533,12 @@ ngx_http_discard_request_body(ngx_http_request_t *r) + return NGX_OK; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ r->spdy_stream->skip_data = 1; ++ return NGX_OK; ++ } ++#endif + + if (ngx_http_test_expect(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; +diff --git a/nginx-1.15.8/src/http/ngx_http_spdy.c b/nginx-1.15.8/src/http/ngx_http_spdy.c +new file mode 100644 +index 0000000..21c5217 +--- /dev/null ++++ b/nginx-1.15.8/src/http/ngx_http_spdy.c +@@ -0,0 +1,3701 @@ ++ ++/* ++ * Copyright (C) Nginx, Inc. ++ * Copyright (C) Valentin V. Bartenev ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) ++ ++#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ ++ *(uint32_t *) m == (c3 << 24 | c2 << 16 | c1 << 8 | c0) \ ++ && m[4] == c4 ++ ++#else ++ ++#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ ++ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4 ++ ++#endif ++ ++ ++#if (NGX_HAVE_NONALIGNED) ++ ++#define ngx_spdy_frame_parse_uint16(p) ntohs(*(uint16_t *) (p)) ++#define ngx_spdy_frame_parse_uint32(p) ntohl(*(uint32_t *) (p)) ++ ++#else ++ ++#define ngx_spdy_frame_parse_uint16(p) ((p)[0] << 8 | (p)[1]) ++#define ngx_spdy_frame_parse_uint32(p) \ ++ ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) ++ ++#endif ++ ++#define ngx_spdy_frame_parse_sid(p) \ ++ (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) ++#define ngx_spdy_frame_parse_delta(p) \ ++ (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) ++ ++ ++#define ngx_spdy_ctl_frame_check(h) \ ++ (((h) & 0xffff0000) == ngx_spdy_ctl_frame_head(0)) ++#define ngx_spdy_data_frame_check(h) \ ++ (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31)) ++ ++#define ngx_spdy_ctl_frame_type(h) ((h) & 0x0000ffff) ++#define ngx_spdy_frame_flags(p) ((p) >> 24) ++#define ngx_spdy_frame_length(p) ((p) & 0x00ffffff) ++#define ngx_spdy_frame_id(p) ((p) & 0x00ffffff) ++ ++ ++#define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096 ++#define NGX_SPDY_CTL_FRAME_BUFFER_SIZE 16 ++ ++#define NGX_SPDY_PROTOCOL_ERROR 1 ++#define NGX_SPDY_INVALID_STREAM 2 ++#define NGX_SPDY_REFUSED_STREAM 3 ++#define NGX_SPDY_UNSUPPORTED_VERSION 4 ++#define NGX_SPDY_CANCEL 5 ++#define NGX_SPDY_INTERNAL_ERROR 6 ++#define NGX_SPDY_FLOW_CONTROL_ERROR 7 ++#define NGX_SPDY_STREAM_IN_USE 8 ++#define NGX_SPDY_STREAM_ALREADY_CLOSED 9 ++/* deprecated 10 */ ++#define NGX_SPDY_FRAME_TOO_LARGE 11 ++ ++#define NGX_SPDY_SETTINGS_MAX_STREAMS 4 ++#define NGX_SPDY_SETTINGS_INIT_WINDOW 7 ++ ++#define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01 ++#define NGX_SPDY_SETTINGS_FLAG_PERSISTED 0x02 ++ ++#define NGX_SPDY_MAX_WINDOW NGX_MAX_INT32_VALUE ++#define NGX_SPDY_CONNECTION_WINDOW 65536 ++#define NGX_SPDY_INIT_STREAM_WINDOW 65536 ++#define NGX_SPDY_STREAM_WINDOW NGX_SPDY_MAX_WINDOW ++ ++typedef struct { ++ ngx_uint_t hash; ++ u_char len; ++ u_char header[7]; ++ ngx_int_t (*handler)(ngx_http_request_t *r); ++} ngx_http_spdy_request_header_t; ++ ++ ++static void ngx_http_spdy_read_handler(ngx_event_t *rev); ++static void ngx_http_spdy_write_handler(ngx_event_t *wev); ++static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc); ++ ++static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler); ++ ++static u_char *ngx_http_spdy_state_inflate_error( ++ ngx_http_spdy_connection_t *sc, int rc); ++static u_char *ngx_http_spdy_state_protocol_error( ++ ngx_http_spdy_connection_t *sc); ++static u_char *ngx_http_spdy_state_internal_error( ++ ngx_http_spdy_connection_t *sc); ++ ++static ngx_int_t ngx_http_spdy_send_window_update( ++ ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ngx_uint_t delta); ++static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ++ ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority); ++static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc); ++static ngx_int_t ngx_http_spdy_settings_frame_handler( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); ++static ngx_http_spdy_out_frame_t *ngx_http_spdy_get_ctl_frame( ++ ngx_http_spdy_connection_t *sc, size_t size, ngx_uint_t priority); ++static ngx_int_t ngx_http_spdy_ctl_frame_handler( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); ++ ++static ngx_http_spdy_stream_t *ngx_http_spdy_create_stream( ++ ngx_http_spdy_connection_t *sc, ngx_uint_t id, ngx_uint_t priority); ++static ngx_http_spdy_stream_t *ngx_http_spdy_get_stream_by_id( ++ ngx_http_spdy_connection_t *sc, ngx_uint_t sid); ++#define ngx_http_spdy_streams_index_size(sscf) (sscf->streams_index_mask + 1) ++#define ngx_http_spdy_stream_index(sscf, sid) \ ++ ((sid >> 1) & sscf->streams_index_mask) ++ ++static ngx_int_t ngx_http_spdy_parse_header(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r); ++ ++static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_parse_host(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_parse_path(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r); ++ ++static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r); ++static void ngx_http_spdy_run_request(ngx_http_request_t *r); ++static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r); ++ ++static ngx_int_t ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream, ngx_uint_t status); ++ ++static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev); ++ ++static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev); ++static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev); ++static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, ++ ngx_int_t rc); ++ ++static ngx_int_t ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ++ ssize_t delta); ++ ++static void ngx_http_spdy_pool_cleanup(void *data); ++ ++static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size); ++static void ngx_http_spdy_zfree(void *opaque, void *address); ++ ++ ++static const u_char ngx_http_spdy_dict[] = { ++ 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, /* - - - - o p t i */ ++ 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, /* o n s - - - - h */ ++ 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, /* e a d - - - - p */ ++ 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, /* o s t - - - - p */ ++ 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, /* u t - - - - d e */ ++ 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, /* l e t e - - - - */ ++ 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, /* t r a c e - - - */ ++ 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, /* - a c c e p t - */ ++ 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */ ++ 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* t - c h a r s e */ ++ 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, /* t - - - - a c c */ ++ 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e p t - e n c o */ ++ 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, /* d i n g - - - - */ ++ 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, /* a c c e p t - l */ ++ 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, /* a n g u a g e - */ ++ 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */ ++ 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, /* t - r a n g e s */ ++ 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, /* - - - - a g e - */ ++ 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, /* - - - a l l o w */ ++ 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, /* - - - - a u t h */ ++ 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, /* o r i z a t i o */ ++ 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, /* n - - - - c a c */ ++ 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, /* h e - c o n t r */ ++ 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, /* o l - - - - c o */ ++ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, /* n n e c t i o n */ ++ 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ ++ 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, /* e n t - b a s e */ ++ 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ ++ 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e n t - e n c o */ ++ 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, /* d i n g - - - - */ ++ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, /* c o n t e n t - */ ++ 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, /* l a n g u a g e */ ++ 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ ++ 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, /* e n t - l e n g */ ++ 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, /* t h - - - - c o */ ++ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, /* n t e n t - l o */ ++ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* c a t i o n - - */ ++ 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */ ++ 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, /* t - m d 5 - - - */ ++ 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, /* - c o n t e n t */ ++ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, /* - r a n g e - - */ ++ 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */ ++ 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, /* t - t y p e - - */ ++ 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, /* - - d a t e - - */ ++ 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, /* - - e t a g - - */ ++ 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, /* - - e x p e c t */ ++ 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, /* - - - - e x p i */ ++ 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, /* r e s - - - - f */ ++ 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, /* r o m - - - - h */ ++ 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, /* o s t - - - - i */ ++ 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, /* f - m a t c h - */ ++ 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, /* - - - i f - m o */ ++ 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, /* d i f i e d - s */ ++ 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, /* i n c e - - - - */ ++ 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, /* i f - n o n e - */ ++ 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, /* m a t c h - - - */ ++ 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, /* - i f - r a n g */ ++ 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, /* e - - - - i f - */ ++ 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, /* u n m o d i f i */ ++ 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, /* e d - s i n c e */ ++ 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, /* - - - - l a s t */ ++ 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, /* - m o d i f i e */ ++ 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, /* d - - - - l o c */ ++ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, /* a t i o n - - - */ ++ 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, /* - m a x - f o r */ ++ 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, /* w a r d s - - - */ ++ 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, /* - p r a g m a - */ ++ 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, /* - - - p r o x y */ ++ 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, /* - a u t h e n t */ ++ 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, /* i c a t e - - - */ ++ 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, /* - p r o x y - a */ ++ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, /* u t h o r i z a */ ++ 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, /* t i o n - - - - */ ++ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, /* r a n g e - - - */ ++ 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, /* - r e f e r e r */ ++ 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, /* - - - - r e t r */ ++ 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, /* y - a f t e r - */ ++ 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, /* - - - s e r v e */ ++ 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, /* r - - - - t e - */ ++ 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, /* - - - t r a i l */ ++ 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, /* e r - - - - t r */ ++ 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, /* a n s f e r - e */ ++ 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, /* n c o d i n g - */ ++ 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, /* - - - u p g r a */ ++ 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, /* d e - - - - u s */ ++ 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, /* e r - a g e n t */ ++ 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, /* - - - - v a r y */ ++ 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, /* - - - - v i a - */ ++ 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, /* - - - w a r n i */ ++ 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, /* n g - - - - w w */ ++ 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, /* w - a u t h e n */ ++ 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, /* t i c a t e - - */ ++ 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, /* - - m e t h o d */ ++ 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, /* - - - - g e t - */ ++ 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, /* - - - s t a t u */ ++ 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, /* s - - - - 2 0 0 */ ++ 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, /* - O K - - - - v */ ++ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* e r s i o n - - */ ++ 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, /* - - H T T P - 1 */ ++ 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, /* - 1 - - - - u r */ ++ 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, /* l - - - - p u b */ ++ 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, /* l i c - - - - s */ ++ 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, /* e t - c o o k i */ ++ 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, /* e - - - - k e e */ ++ 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, /* p - a l i v e - */ ++ 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, /* - - - o r i g i */ ++ 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, /* n 1 0 0 1 0 1 2 */ ++ 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, /* 0 1 2 0 2 2 0 5 */ ++ 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, /* 2 0 6 3 0 0 3 0 */ ++ 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, /* 2 3 0 3 3 0 4 3 */ ++ 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, /* 0 5 3 0 6 3 0 7 */ ++ 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, /* 4 0 2 4 0 5 4 0 */ ++ 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, /* 6 4 0 7 4 0 8 4 */ ++ 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, /* 0 9 4 1 0 4 1 1 */ ++ 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, /* 4 1 2 4 1 3 4 1 */ ++ 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, /* 4 4 1 5 4 1 6 4 */ ++ 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, /* 1 7 5 0 2 5 0 4 */ ++ 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, /* 5 0 5 2 0 3 - N */ ++ 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, /* o n - A u t h o */ ++ 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, /* r i t a t i v e */ ++ 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, /* - I n f o r m a */ ++ 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, /* t i o n 2 0 4 - */ ++ 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, /* N o - C o n t e */ ++ 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, /* n t 3 0 1 - M o */ ++ 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, /* v e d - P e r m */ ++ 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, /* a n e n t l y 4 */ ++ 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, /* 0 0 - B a d - R */ ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, /* e q u e s t 4 0 */ ++ 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, /* 1 - U n a u t h */ ++ 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, /* o r i z e d 4 0 */ ++ 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, /* 3 - F o r b i d */ ++ 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, /* d e n 4 0 4 - N */ ++ 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, /* o t - F o u n d */ ++ 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, /* 5 0 0 - I n t e */ ++ 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, /* r n a l - S e r */ ++ 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, /* v e r - E r r o */ ++ 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, /* r 5 0 1 - N o t */ ++ 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, /* - I m p l e m e */ ++ 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, /* n t e d 5 0 3 - */ ++ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, /* S e r v i c e - */ ++ 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, /* U n a v a i l a */ ++ 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, /* b l e J a n - F */ ++ 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, /* e b - M a r - A */ ++ 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, /* p r - M a y - J */ ++ 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, /* u n - J u l - A */ ++ 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, /* u g - S e p t - */ ++ 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, /* O c t - N o v - */ ++ 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, /* D e c - 0 0 - 0 */ ++ 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, /* 0 - 0 0 - M o n */ ++ 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, /* - - T u e - - W */ ++ 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, /* e d - - T h u - */ ++ 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, /* - F r i - - S a */ ++ 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, /* t - - S u n - - */ ++ 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, /* G M T c h u n k */ ++ 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, /* e d - t e x t - */ ++ 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, /* h t m l - i m a */ ++ 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, /* g e - p n g - i */ ++ 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, /* m a g e - j p g */ ++ 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, /* - i m a g e - g */ ++ 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* i f - a p p l i */ ++ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */ ++ 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* m l - a p p l i */ ++ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */ ++ 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, /* h t m l - x m l */ ++ 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, /* - t e x t - p l */ ++ 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, /* a i n - t e x t */ ++ 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, /* - j a v a s c r */ ++ 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, /* i p t - p u b l */ ++ 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, /* i c p r i v a t */ ++ 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, /* e m a x - a g e */ ++ 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, /* - g z i p - d e */ ++ 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, /* f l a t e - s d */ ++ 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* c h c h a r s e */ ++ 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, /* t - u t f - 8 c */ ++ 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, /* h a r s e t - i */ ++ 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, /* s o - 8 8 5 9 - */ ++ 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, /* 1 - u t f - - - */ ++ 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e /* - e n q - 0 - */ ++}; ++ ++ ++static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = { ++ { 0, 6, "method", ngx_http_spdy_parse_method }, ++ { 0, 6, "scheme", ngx_http_spdy_parse_scheme }, ++ { 0, 4, "host", ngx_http_spdy_parse_host }, ++ { 0, 4, "path", ngx_http_spdy_parse_path }, ++ { 0, 7, "version", ngx_http_spdy_parse_version }, ++}; ++ ++#define NGX_SPDY_REQUEST_HEADERS \ ++ (sizeof(ngx_http_spdy_request_headers) \ ++ / sizeof(ngx_http_spdy_request_header_t)) ++ ++ ++void ++ngx_http_spdy_init(ngx_event_t *rev) ++{ ++ int rc; ++ ngx_connection_t *c; ++ ngx_pool_cleanup_t *cln; ++ ngx_http_connection_t *hc; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ngx_http_spdy_main_conf_t *smcf; ++ ngx_http_spdy_connection_t *sc; ++ ++ c = rev->data; ++ hc = c->data; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "init spdy request"); ++ ++ c->log->action = "processing SPDY"; ++ ++ smcf = ngx_http_get_module_main_conf(hc->conf_ctx, ngx_http_spdy_module); ++ ++ if (smcf->recv_buffer == NULL) { ++ smcf->recv_buffer = ngx_palloc(ngx_cycle->pool, smcf->recv_buffer_size); ++ if (smcf->recv_buffer == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ } ++ ++ sc = ngx_pcalloc(c->pool, sizeof(ngx_http_spdy_connection_t)); ++ if (sc == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ sc->connection = c; ++ sc->http_connection = hc; ++ ++ sc->send_window = NGX_SPDY_CONNECTION_WINDOW; ++ sc->recv_window = NGX_SPDY_CONNECTION_WINDOW; ++ ++ sc->init_window = NGX_SPDY_INIT_STREAM_WINDOW; ++ ++ sc->handler = hc->proxy_protocol ? ngx_http_spdy_proxy_protocol ++ : ngx_http_spdy_state_head; ++ ++ sc->zstream_in.zalloc = ngx_http_spdy_zalloc; ++ sc->zstream_in.zfree = ngx_http_spdy_zfree; ++ sc->zstream_in.opaque = sc; ++ ++ rc = inflateInit(&sc->zstream_in); ++ if (rc != Z_OK) { ++ ngx_log_error(NGX_LOG_ALERT, c->log, 0, ++ "inflateInit() failed: %d", rc); ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ sc->zstream_out.zalloc = ngx_http_spdy_zalloc; ++ sc->zstream_out.zfree = ngx_http_spdy_zfree; ++ sc->zstream_out.opaque = sc; ++ ++ sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_spdy_module); ++ ++ rc = deflateInit2(&sc->zstream_out, (int) sscf->headers_comp, ++ Z_DEFLATED, 11, 4, Z_DEFAULT_STRATEGY); ++ ++ if (rc != Z_OK) { ++ ngx_log_error(NGX_LOG_ALERT, c->log, 0, ++ "deflateInit2() failed: %d", rc); ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ rc = deflateSetDictionary(&sc->zstream_out, ngx_http_spdy_dict, ++ sizeof(ngx_http_spdy_dict)); ++ if (rc != Z_OK) { ++ ngx_log_error(NGX_LOG_ALERT, c->log, 0, ++ "deflateSetDictionary() failed: %d", rc); ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ sc->pool = ngx_create_pool(sscf->pool_size, sc->connection->log); ++ if (sc->pool == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_pool_cleanup_file_t)); ++ if (cln == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ cln->handler = ngx_http_spdy_pool_cleanup; ++ cln->data = sc; ++ ++ sc->streams_index = ngx_pcalloc(sc->pool, ++ ngx_http_spdy_streams_index_size(sscf) ++ * sizeof(ngx_http_spdy_stream_t *)); ++ if (sc->streams_index == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ if (ngx_http_spdy_send_window_update(sc, 0, NGX_SPDY_MAX_WINDOW ++ - sc->recv_window) ++ == NGX_ERROR) ++ { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ sc->recv_window = NGX_SPDY_MAX_WINDOW; ++ ++ ngx_queue_init(&sc->waiting); ++ ngx_queue_init(&sc->posted); ++ ++ c->data = sc; ++ ++ rev->handler = ngx_http_spdy_read_handler; ++ c->write->handler = ngx_http_spdy_write_handler; ++ ++ ngx_http_spdy_read_handler(rev); ++} ++ ++ ++static void ++ngx_http_spdy_read_handler(ngx_event_t *rev) ++{ ++ u_char *p, *end; ++ size_t available; ++ ssize_t n; ++ ngx_connection_t *c; ++ ngx_http_spdy_main_conf_t *smcf; ++ ngx_http_spdy_connection_t *sc; ++ ++ c = rev->data; ++ sc = c->data; ++ ++ if (rev->timedout) { ++ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_REQUEST_TIME_OUT); ++ return; ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy read handler"); ++ ++ sc->blocked = 1; ++ ++ smcf = ngx_http_get_module_main_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ available = smcf->recv_buffer_size - 2 * NGX_SPDY_STATE_BUFFER_SIZE; ++ ++ do { ++ p = smcf->recv_buffer; ++ ++ ngx_memcpy(p, sc->buffer, NGX_SPDY_STATE_BUFFER_SIZE); ++ end = p + sc->buffer_used; ++ ++ n = c->recv(c, end, available); ++ ++ if (n == NGX_AGAIN) { ++ break; ++ } ++ ++ if (n == 0 && (sc->incomplete || sc->processing)) { ++ ngx_log_error(NGX_LOG_INFO, c->log, 0, ++ "client prematurely closed connection"); ++ } ++ ++ if (n == 0 || n == NGX_ERROR) { ++ ngx_http_spdy_finalize_connection(sc, ++ NGX_HTTP_CLIENT_CLOSED_REQUEST); ++ return; ++ } ++ ++ end += n; ++ ++ sc->buffer_used = 0; ++ sc->incomplete = 0; ++ ++ do { ++ p = sc->handler(sc, p, end); ++ ++ if (p == NULL) { ++ return; ++ } ++ ++ } while (p != end); ++ ++ } while (rev->ready); ++ ++ if (ngx_handle_read_event(rev, 0) != NGX_OK) { ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return; ++ } ++ ++ if (sc->last_out && ngx_http_spdy_send_output_queue(sc) == NGX_ERROR) { ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); ++ return; ++ } ++ ++ sc->blocked = 0; ++ ++ if (sc->processing) { ++ if (rev->timer_set) { ++ ngx_del_timer(rev); ++ } ++ return; ++ } ++ ++ ngx_http_spdy_handle_connection(sc); ++} ++ ++ ++static void ++ngx_http_spdy_write_handler(ngx_event_t *wev) ++{ ++ ngx_int_t rc; ++ ngx_queue_t *q; ++ ngx_connection_t *c; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_connection_t *sc; ++ ++ c = wev->data; ++ sc = c->data; ++ ++ if (wev->timedout) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "spdy write event timed out"); ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); ++ return; ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy write handler"); ++ ++ sc->blocked = 1; ++ ++ rc = ngx_http_spdy_send_output_queue(sc); ++ ++ if (rc == NGX_ERROR) { ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); ++ return; ++ } ++ ++ while (!ngx_queue_empty(&sc->posted)) { ++ q = ngx_queue_head(&sc->posted); ++ ++ ngx_queue_remove(q); ++ ++ stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); ++ ++ stream->handled = 0; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "run spdy stream %ui", stream->id); ++ ++ wev = stream->request->connection->write; ++ wev->handler(wev); ++ } ++ ++ sc->blocked = 0; ++ ++ if (rc == NGX_AGAIN) { ++ return; ++ } ++ ++ ngx_http_spdy_handle_connection(sc); ++} ++ ++ ++ngx_int_t ++ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc) ++{ ++ int tcp_nodelay; ++ ngx_chain_t *cl; ++ ngx_event_t *wev; ++ ngx_connection_t *c; ++ ngx_http_core_loc_conf_t *clcf; ++ ngx_http_spdy_out_frame_t *out, *frame, *fn; ++ ++ c = sc->connection; ++ ++ if (c->error) { ++ return NGX_ERROR; ++ } ++ ++ wev = c->write; ++ ++ if (!wev->ready) { ++ return NGX_OK; ++ } ++ ++ cl = NULL; ++ out = NULL; ++ ++ for (frame = sc->last_out; frame; frame = fn) { ++ frame->last->next = cl; ++ cl = frame->first; ++ ++ fn = frame->next; ++ frame->next = out; ++ out = frame; ++ ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "spdy frame out: %p sid:%ui prio:%ui bl:%d len:%uz", ++ out, out->stream ? out->stream->id : 0, out->priority, ++ out->blocked, out->length); ++ } ++ ++ cl = c->send_chain(c, cl, 0); ++ ++ if (cl == NGX_CHAIN_ERROR) { ++ goto error; ++ } ++ ++ clcf = ngx_http_get_module_loc_conf(sc->http_connection->conf_ctx, ++ ngx_http_core_module); ++ ++ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { ++ goto error; ++ } ++ ++ if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { ++ if (ngx_tcp_push(c->fd) == -1) { ++ ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed"); ++ goto error; ++ } ++ ++ c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; ++ tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; ++ ++ } else { ++ tcp_nodelay = 1; ++ } ++ ++ if (tcp_nodelay ++ && clcf->tcp_nodelay ++ && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) ++ { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); ++ ++ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, ++ (const void *) &tcp_nodelay, sizeof(int)) ++ == -1) ++ { ++#if (NGX_SOLARIS) ++ /* Solaris returns EINVAL if a socket has been shut down */ ++ c->log_error = NGX_ERROR_IGNORE_EINVAL; ++#endif ++ ++ ngx_connection_error(c, ngx_socket_errno, ++ "setsockopt(TCP_NODELAY) failed"); ++ ++ c->log_error = NGX_ERROR_INFO; ++ goto error; ++ } ++ ++ c->tcp_nodelay = NGX_TCP_NODELAY_SET; ++ } ++ ++ if (cl) { ++ ngx_add_timer(wev, clcf->send_timeout); ++ ++ } else { ++ if (wev->timer_set) { ++ ngx_del_timer(wev); ++ } ++ } ++ ++ for ( /* void */ ; out; out = fn) { ++ fn = out->next; ++ ++ if (out->handler(sc, out) != NGX_OK) { ++ out->blocked = 1; ++ out->priority = NGX_SPDY_HIGHEST_PRIORITY; ++ break; ++ } ++ ++ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "spdy frame sent: %p sid:%ui bl:%d len:%uz", ++ out, out->stream ? out->stream->id : 0, ++ out->blocked, out->length); ++ } ++ ++ frame = NULL; ++ ++ for ( /* void */ ; out; out = fn) { ++ fn = out->next; ++ out->next = frame; ++ frame = out; ++ } ++ ++ sc->last_out = frame; ++ ++ return NGX_OK; ++ ++error: ++ ++ c->error = 1; ++ ++ if (!sc->blocked) { ++ ngx_post_event(wev, &ngx_posted_events); ++ } ++ ++ return NGX_ERROR; ++} ++ ++ ++static void ++ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc) ++{ ++ ngx_connection_t *c; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ if (sc->last_out || sc->processing) { ++ return; ++ } ++ ++ c = sc->connection; ++ ++ if (c->error) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ if (c->buffered) { ++ return; ++ } ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ if (sc->incomplete) { ++ ngx_add_timer(c->read, sscf->recv_timeout); ++ return; ++ } ++ ++ if (ngx_terminate || ngx_exiting) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ ngx_destroy_pool(sc->pool); ++ ++ sc->pool = NULL; ++ sc->free_ctl_frames = NULL; ++ sc->free_fake_connections = NULL; ++ ++#if (NGX_HTTP_SSL) ++ if (c->ssl) { ++ ngx_ssl_free_buffer(c); ++ } ++#endif ++ ++ c->destroyed = 1; ++ c->idle = 1; ++ ngx_reusable_connection(c, 1); ++ ++ c->write->handler = ngx_http_empty_handler; ++ c->read->handler = ngx_http_spdy_keepalive_handler; ++ ++ if (c->write->timer_set) { ++ ngx_del_timer(c->write); ++ } ++ ++ ngx_add_timer(c->read, sscf->keepalive_timeout); ++} ++ ++ ++static u_char * ++ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_log_t *log; ++ ++ log = sc->connection->log; ++ log->action = "reading PROXY protocol"; ++ ++ pos = ngx_proxy_protocol_read(sc->connection, pos, end); ++ ++ log->action = "processing SPDY"; ++ ++ if (pos == NULL) { ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ uint32_t head, flen; ++ ngx_uint_t type; ++ ++ if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_head); ++ } ++ ++ head = ngx_spdy_frame_parse_uint32(pos); ++ ++ pos += sizeof(uint32_t); ++ ++ flen = ngx_spdy_frame_parse_uint32(pos); ++ ++ sc->flags = ngx_spdy_frame_flags(flen); ++ sc->length = ngx_spdy_frame_length(flen); ++ ++ pos += sizeof(uint32_t); ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "process spdy frame head:%08XD f:%Xd l:%uz", ++ head, sc->flags, sc->length); ++ ++ if (ngx_spdy_ctl_frame_check(head)) { ++ type = ngx_spdy_ctl_frame_type(head); ++ ++ switch (type) { ++ ++ case NGX_SPDY_SYN_STREAM: ++ return ngx_http_spdy_state_syn_stream(sc, pos, end); ++ ++ case NGX_SPDY_SYN_REPLY: ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent unexpected SYN_REPLY frame"); ++ return ngx_http_spdy_state_protocol_error(sc); ++ ++ case NGX_SPDY_RST_STREAM: ++ return ngx_http_spdy_state_rst_stream(sc, pos, end); ++ ++ case NGX_SPDY_SETTINGS: ++ return ngx_http_spdy_state_settings(sc, pos, end); ++ ++ case NGX_SPDY_PING: ++ return ngx_http_spdy_state_ping(sc, pos, end); ++ ++ case NGX_SPDY_GOAWAY: ++ return ngx_http_spdy_state_skip(sc, pos, end); /* TODO */ ++ ++ case NGX_SPDY_HEADERS: ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent unexpected HEADERS frame"); ++ return ngx_http_spdy_state_protocol_error(sc); ++ ++ case NGX_SPDY_WINDOW_UPDATE: ++ return ngx_http_spdy_state_window_update(sc, pos, end); ++ ++ default: ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy control frame with unknown type %ui", type); ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ } ++ ++ if (ngx_spdy_data_frame_check(head)) { ++ sc->stream = ngx_http_spdy_get_stream_by_id(sc, head); ++ return ngx_http_spdy_state_data(sc, pos, end); ++ } ++ ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent invalid frame"); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_uint_t sid, prio; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ if (end - pos < NGX_SPDY_SYN_STREAM_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_syn_stream); ++ } ++ ++ if (sc->length <= NGX_SPDY_SYN_STREAM_SIZE) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SYN_STREAM frame with incorrect length %uz", ++ sc->length); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ sc->length -= NGX_SPDY_SYN_STREAM_SIZE; ++ ++ sid = ngx_spdy_frame_parse_sid(pos); ++ prio = pos[8] >> 5; ++ ++ pos += NGX_SPDY_SYN_STREAM_SIZE; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy SYN_STREAM frame sid:%ui prio:%ui", sid, prio); ++ ++ if (sid % 2 == 0 || sid <= sc->last_sid) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SYN_STREAM frame " ++ "with invalid Stream-ID %ui", sid); ++ ++ stream = ngx_http_spdy_get_stream_by_id(sc, sid); ++ ++ if (stream) { ++ if (ngx_http_spdy_terminate_stream(sc, stream, ++ NGX_SPDY_PROTOCOL_ERROR) ++ != NGX_OK) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ } ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ sc->last_sid = sid; ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ if (sc->processing >= sscf->concurrent_streams) { ++ ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "concurrent streams exceeded %ui", sc->processing); ++ ++ if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_REFUSED_STREAM, ++ prio) ++ != NGX_OK) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ ++ stream = ngx_http_spdy_create_stream(sc, sid, prio); ++ if (stream == NULL) { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ stream->in_closed = (sc->flags & NGX_SPDY_FLAG_FIN) ? 1 : 0; ++ ++ stream->request->request_length = NGX_SPDY_FRAME_HEADER_SIZE ++ + NGX_SPDY_SYN_STREAM_SIZE ++ + sc->length; ++ ++ sc->stream = stream; ++ ++ return ngx_http_spdy_state_headers(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ int z; ++ size_t size; ++ ngx_buf_t *buf; ++ ngx_int_t rc; ++ ngx_http_request_t *r; ++ ++ size = end - pos; ++ ++ if (size == 0) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers); ++ } ++ ++ if (size > sc->length) { ++ size = sc->length; ++ } ++ ++ r = sc->stream->request; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "process spdy header block %uz of %uz", size, sc->length); ++ ++ buf = r->header_in; ++ ++ sc->zstream_in.next_in = pos; ++ sc->zstream_in.avail_in = size; ++ sc->zstream_in.next_out = buf->last; ++ ++ /* one byte is reserved for null-termination of the last header value */ ++ sc->zstream_in.avail_out = buf->end - buf->last - 1; ++ ++ z = inflate(&sc->zstream_in, Z_NO_FLUSH); ++ ++ if (z == Z_NEED_DICT) { ++ z = inflateSetDictionary(&sc->zstream_in, ngx_http_spdy_dict, ++ sizeof(ngx_http_spdy_dict)); ++ ++ if (z != Z_OK) { ++ if (z == Z_DATA_ERROR) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent SYN_STREAM frame with header " ++ "block encoded using wrong dictionary: %ul", ++ (u_long) sc->zstream_in.adler); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "inflateSetDictionary() failed: %d", z); ++ ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy inflateSetDictionary(): %d", z); ++ ++ z = sc->zstream_in.avail_in ? inflate(&sc->zstream_in, Z_NO_FLUSH) ++ : Z_OK; ++ } ++ ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", ++ sc->zstream_in.next_in, sc->zstream_in.next_out, ++ sc->zstream_in.avail_in, sc->zstream_in.avail_out, ++ z); ++ ++ if (z != Z_OK) { ++ return ngx_http_spdy_state_inflate_error(sc, z); ++ } ++ ++ sc->length -= sc->zstream_in.next_in - pos; ++ pos = sc->zstream_in.next_in; ++ ++ buf->last = sc->zstream_in.next_out; ++ ++ if (r->headers_in.headers.part.elts == NULL) { ++ ++ if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) { ++ ++ if (sc->length == 0) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "premature end of spdy header block"); ++ ++ return ngx_http_spdy_state_headers_error(sc, pos, end); ++ } ++ ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers); ++ } ++ ++ sc->entries = ngx_spdy_frame_parse_uint32(buf->pos); ++ ++ buf->pos += NGX_SPDY_NV_NUM_SIZE; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy header block has %ui entries", ++ sc->entries); ++ ++ if (ngx_list_init(&r->headers_in.headers, r->pool, 20, ++ sizeof(ngx_table_elt_t)) ++ != NGX_OK) ++ { ++ ngx_http_spdy_close_stream(sc->stream, ++ NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ ++ if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, ++ sizeof(ngx_table_elt_t *)) ++ != NGX_OK) ++ { ++ ngx_http_spdy_close_stream(sc->stream, ++ NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ } ++ ++ while (sc->entries) { ++ ++ rc = ngx_http_spdy_parse_header(r); ++ ++ switch (rc) { ++ ++ case NGX_DONE: ++ sc->entries--; ++ ++ case NGX_OK: ++ break; ++ ++ case NGX_AGAIN: ++ ++ if (sc->zstream_in.avail_in) { ++ ++ rc = ngx_http_spdy_alloc_large_header_buffer(r); ++ ++ if (rc == NGX_DECLINED) { ++ ngx_http_finalize_request(r, ++ NGX_HTTP_REQUEST_HEADER_TOO_LARGE); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ ++ if (rc != NGX_OK) { ++ ngx_http_spdy_close_stream(sc->stream, ++ NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ ++ /* null-terminate the last processed header name or value */ ++ *buf->pos = '\0'; ++ ++ buf = r->header_in; ++ ++ sc->zstream_in.next_out = buf->last; ++ ++ /* one byte is reserved for null-termination */ ++ sc->zstream_in.avail_out = buf->end - buf->last - 1; ++ ++ z = inflate(&sc->zstream_in, Z_NO_FLUSH); ++ ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", ++ sc->zstream_in.next_in, sc->zstream_in.next_out, ++ sc->zstream_in.avail_in, sc->zstream_in.avail_out, ++ z); ++ ++ if (z != Z_OK) { ++ return ngx_http_spdy_state_inflate_error(sc, z); ++ } ++ ++ sc->length -= sc->zstream_in.next_in - pos; ++ pos = sc->zstream_in.next_in; ++ ++ buf->last = sc->zstream_in.next_out; ++ ++ continue; ++ } ++ ++ if (sc->length == 0) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "premature end of spdy header block"); ++ ++ return ngx_http_spdy_state_headers_error(sc, pos, end); ++ } ++ ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers); ++ ++ case NGX_HTTP_PARSE_INVALID_HEADER: ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ ++ default: /* NGX_ERROR */ ++ return ngx_http_spdy_state_headers_error(sc, pos, end); ++ } ++ ++ /* a header line has been parsed successfully */ ++ ++ rc = ngx_http_spdy_handle_request_header(r); ++ ++ if (rc != NGX_OK) { ++ if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ ++ if (rc != NGX_ABORT) { ++ ngx_http_spdy_close_stream(sc->stream, ++ NGX_HTTP_INTERNAL_SERVER_ERROR); ++ } ++ ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++ } ++ } ++ ++ if (buf->pos != buf->last || sc->zstream_in.avail_in) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "incorrect number of spdy header block entries"); ++ ++ return ngx_http_spdy_state_headers_error(sc, pos, end); ++ } ++ ++ if (sc->length) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers); ++ } ++ ++ /* null-terminate the last header value */ ++ *buf->pos = '\0'; ++ ++ ngx_http_spdy_run_request(r); ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ int n; ++ size_t size; ++ u_char buffer[NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE]; ++ ++ if (sc->length == 0) { ++ return ngx_http_spdy_state_complete(sc, pos, end); ++ } ++ ++ size = end - pos; ++ ++ if (size == 0) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers_skip); ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy header block skip %uz of %uz", size, sc->length); ++ ++ sc->zstream_in.next_in = pos; ++ sc->zstream_in.avail_in = (size < sc->length) ? size : sc->length; ++ ++ while (sc->zstream_in.avail_in) { ++ sc->zstream_in.next_out = buffer; ++ sc->zstream_in.avail_out = NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE; ++ ++ n = inflate(&sc->zstream_in, Z_NO_FLUSH); ++ ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", ++ sc->zstream_in.next_in, sc->zstream_in.next_out, ++ sc->zstream_in.avail_in, sc->zstream_in.avail_out, ++ n); ++ ++ if (n != Z_OK) { ++ return ngx_http_spdy_state_inflate_error(sc, n); ++ } ++ } ++ ++ pos = sc->zstream_in.next_in; ++ ++ if (size < sc->length) { ++ sc->length -= size; ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_headers_skip); ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_http_spdy_stream_t *stream; ++ ++ stream = sc->stream; ++ ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SYN_STREAM frame for stream %ui " ++ "with invalid header block", stream->id); ++ ++ if (ngx_http_spdy_send_rst_stream(sc, stream->id, NGX_SPDY_PROTOCOL_ERROR, ++ stream->priority) ++ != NGX_OK) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ stream->out_closed = 1; ++ ++ ngx_http_spdy_close_stream(stream, NGX_HTTP_BAD_REQUEST); ++ ++ return ngx_http_spdy_state_headers_skip(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ size_t delta; ++ ngx_uint_t sid; ++ ngx_event_t *wev; ++ ngx_queue_t *q; ++ ngx_http_spdy_stream_t *stream; ++ ++ if (end - pos < NGX_SPDY_WINDOW_UPDATE_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_window_update); ++ } ++ ++ if (sc->length != NGX_SPDY_WINDOW_UPDATE_SIZE) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent WINDOW_UPDATE frame " ++ "with incorrect length %uz", sc->length); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ sid = ngx_spdy_frame_parse_sid(pos); ++ ++ pos += NGX_SPDY_SID_SIZE; ++ ++ delta = ngx_spdy_frame_parse_delta(pos); ++ ++ pos += NGX_SPDY_DELTA_SIZE; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy WINDOW_UPDATE sid:%ui delta:%uz", sid, delta); ++ ++ if (sid) { ++ stream = ngx_http_spdy_get_stream_by_id(sc, sid); ++ ++ if (stream == NULL) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "unknown spdy stream"); ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++ } ++ ++ if (stream->send_window > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) { ++ ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client violated flow control for stream %ui: " ++ "received WINDOW_UPDATE frame with delta %uz " ++ "not allowed for window %z", ++ sid, delta, stream->send_window); ++ ++ if (ngx_http_spdy_terminate_stream(sc, stream, ++ NGX_SPDY_FLOW_CONTROL_ERROR) ++ == NGX_ERROR) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++ } ++ ++ stream->send_window += delta; ++ ++ if (stream->exhausted) { ++ stream->exhausted = 0; ++ ++ wev = stream->request->connection->write; ++ ++ if (!wev->timer_set) { ++ wev->delayed = 0; ++ wev->handler(wev); ++ } ++ } ++ ++ } else { ++ sc->send_window += delta; ++ ++ if (sc->send_window > NGX_SPDY_MAX_WINDOW) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client violated connection flow control: " ++ "received WINDOW_UPDATE frame with delta %uz " ++ "not allowed for window %uz", ++ delta, sc->send_window); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ while (!ngx_queue_empty(&sc->waiting)) { ++ q = ngx_queue_head(&sc->waiting); ++ ++ ngx_queue_remove(q); ++ ++ stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); ++ ++ stream->handled = 0; ++ ++ wev = stream->request->connection->write; ++ ++ if (!wev->timer_set) { ++ wev->delayed = 0; ++ wev->handler(wev); ++ ++ if (sc->send_window == 0) { ++ break; ++ } ++ } ++ } ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_http_spdy_stream_t *stream; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy DATA frame"); ++ ++ if (sc->length > sc->recv_window) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client violated connection flow control: " ++ "received DATA frame length %uz, available window %uz", ++ sc->length, sc->recv_window); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ sc->recv_window -= sc->length; ++ ++ if (sc->recv_window < NGX_SPDY_MAX_WINDOW / 4) { ++ ++ if (ngx_http_spdy_send_window_update(sc, 0, ++ NGX_SPDY_MAX_WINDOW ++ - sc->recv_window) ++ == NGX_ERROR) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ sc->recv_window = NGX_SPDY_MAX_WINDOW; ++ } ++ ++ stream = sc->stream; ++ ++ if (stream == NULL) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "unknown spdy stream"); ++ ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ if (sc->length > stream->recv_window) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client violated flow control for stream %ui: " ++ "received DATA frame length %uz, available window %uz", ++ stream->id, sc->length, stream->recv_window); ++ ++ if (ngx_http_spdy_terminate_stream(sc, stream, ++ NGX_SPDY_FLOW_CONTROL_ERROR) ++ == NGX_ERROR) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ stream->recv_window -= sc->length; ++ ++ if (stream->recv_window < NGX_SPDY_STREAM_WINDOW / 4) { ++ ++ if (ngx_http_spdy_send_window_update(sc, stream->id, ++ NGX_SPDY_STREAM_WINDOW ++ - stream->recv_window) ++ == NGX_ERROR) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ stream->recv_window = NGX_SPDY_STREAM_WINDOW; ++ } ++ ++ if (stream->in_closed) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent DATA frame for half-closed stream %ui", ++ stream->id); ++ ++ if (ngx_http_spdy_terminate_stream(sc, stream, ++ NGX_SPDY_STREAM_ALREADY_CLOSED) ++ == NGX_ERROR) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ return ngx_http_spdy_state_read_data(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ size_t size; ++ ssize_t n; ++ ngx_buf_t *buf; ++ ngx_int_t rc; ++ ngx_temp_file_t *tf; ++ ngx_http_request_t *r; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_request_body_t *rb; ++ ngx_http_core_loc_conf_t *clcf; ++ ++ stream = sc->stream; ++ ++ if (stream == NULL) { ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ if (stream->skip_data) { ++ ++ if (sc->flags & NGX_SPDY_FLAG_FIN) { ++ stream->in_closed = 1; ++ } ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "skipping spdy DATA frame, reason: %d", ++ stream->skip_data); ++ ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ size = end - pos; ++ ++ if (size > sc->length) { ++ size = sc->length; ++ } ++ ++ r = stream->request; ++ ++ if (r->request_body == NULL ++ && ngx_http_spdy_init_request_body(r) != NGX_OK) ++ { ++ stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; ++ return ngx_http_spdy_state_skip(sc, pos, end); ++ } ++ ++ rb = r->request_body; ++ tf = rb->temp_file; ++ buf = rb->buf; ++ ++ if (size) { ++ rb->rest += size; ++ ++ if (r->headers_in.content_length_n != -1 ++ && r->headers_in.content_length_n < rb->rest) ++ { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client intended to send body data " ++ "larger than declared"); ++ ++ stream->skip_data = NGX_SPDY_DATA_ERROR; ++ goto error; ++ ++ } else { ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ ++ if (clcf->client_max_body_size ++ && clcf->client_max_body_size < rb->rest) ++ { ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "client intended to send " ++ "too large chunked body: %O bytes", rb->rest); ++ ++ stream->skip_data = NGX_SPDY_DATA_ERROR; ++ goto error; ++ } ++ } ++ ++ sc->length -= size; ++ ++ if (tf) { ++ buf->start = pos; ++ buf->pos = pos; ++ ++ pos += size; ++ ++ buf->end = pos; ++ buf->last = pos; ++ ++ n = ngx_write_chain_to_temp_file(tf, rb->bufs); ++ ++ /* TODO: n == 0 or not complete and level event */ ++ ++ if (n == NGX_ERROR) { ++ stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; ++ goto error; ++ } ++ ++ tf->offset += n; ++ ++ } else { ++ buf->last = ngx_cpymem(buf->last, pos, size); ++ pos += size; ++ } ++ ++ r->request_length += size; ++ } ++ ++ if (sc->length) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_read_data); ++ } ++ ++ if (sc->flags & NGX_SPDY_FLAG_FIN) { ++ ++ stream->in_closed = 1; ++ ++ if (r->headers_in.content_length_n < 0) { ++ r->headers_in.content_length_n = rb->rest; ++ ++ } else if (r->headers_in.content_length_n != rb->rest) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client prematurely closed stream: " ++ "only %O out of %O bytes of request body received", ++ rb->rest, r->headers_in.content_length_n); ++ ++ stream->skip_data = NGX_SPDY_DATA_ERROR; ++ goto error; ++ } ++ ++ if (tf) { ++ ngx_memzero(buf, sizeof(ngx_buf_t)); ++ ++ buf->in_file = 1; ++ buf->file_last = tf->file.offset; ++ buf->file = &tf->file; ++ ++ rb->buf = NULL; ++ } ++ ++ if (rb->post_handler) { ++ r->read_event_handler = ngx_http_block_reading; ++ rb->post_handler(r); ++ } ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++ ++error: ++ ++ if (rb->post_handler) { ++ ++ if (stream->skip_data == NGX_SPDY_DATA_ERROR) { ++ rc = (r->headers_in.content_length_n == -1) ++ ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE ++ : NGX_HTTP_BAD_REQUEST; ++ ++ } else { ++ rc = NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ ngx_http_finalize_request(r, rc); ++ } ++ ++ return ngx_http_spdy_state_skip(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_uint_t sid, status; ++ ngx_event_t *ev; ++ ngx_connection_t *fc; ++ ngx_http_spdy_stream_t *stream; ++ ++ if (end - pos < NGX_SPDY_RST_STREAM_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_rst_stream); ++ } ++ ++ if (sc->length != NGX_SPDY_RST_STREAM_SIZE) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent RST_STREAM frame with incorrect length %uz", ++ sc->length); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ sid = ngx_spdy_frame_parse_sid(pos); ++ ++ pos += NGX_SPDY_SID_SIZE; ++ ++ status = ngx_spdy_frame_parse_uint32(pos); ++ ++ pos += sizeof(uint32_t); ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy RST_STREAM sid:%ui st:%ui", sid, status); ++ ++ stream = ngx_http_spdy_get_stream_by_id(sc, sid); ++ ++ if (stream == NULL) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "unknown spdy stream"); ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++ } ++ ++ stream->in_closed = 1; ++ stream->out_closed = 1; ++ ++ fc = stream->request->connection; ++ fc->error = 1; ++ ++ switch (status) { ++ ++ case NGX_SPDY_CANCEL: ++ ngx_log_error(NGX_LOG_INFO, fc->log, 0, ++ "client canceled stream %ui", sid); ++ break; ++ ++ case NGX_SPDY_INTERNAL_ERROR: ++ ngx_log_error(NGX_LOG_INFO, fc->log, 0, ++ "client terminated stream %ui due to internal error", ++ sid); ++ break; ++ ++ default: ++ ngx_log_error(NGX_LOG_INFO, fc->log, 0, ++ "client terminated stream %ui with status %ui", ++ sid, status); ++ break; ++ } ++ ++ ev = fc->read; ++ ev->handler(ev); ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ if (end - pos < NGX_SPDY_PING_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_ping); ++ } ++ ++ if (sc->length != NGX_SPDY_PING_SIZE) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent PING frame with incorrect length %uz", ++ sc->length); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy PING frame"); ++ ++ frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_PING_SIZE, ++ NGX_SPDY_HIGHEST_PRIORITY); ++ if (frame == NULL) { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ buf = frame->first->buf; ++ ++ p = buf->pos; ++ ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_PING); ++ p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_PING_SIZE); ++ ++ p = ngx_cpymem(p, pos, NGX_SPDY_PING_SIZE); ++ ++ buf->last = p; ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ pos += NGX_SPDY_PING_SIZE; ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ size_t size; ++ ++ size = end - pos; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy frame skip %uz of %uz", size, sc->length); ++ ++ if (size < sc->length) { ++ sc->length -= size; ++ return ngx_http_spdy_state_save(sc, end, end, ++ ngx_http_spdy_state_skip); ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos + sc->length, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_uint_t fid, val; ++ ++ if (sc->entries == 0) { ++ ++ if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_settings); ++ } ++ ++ sc->entries = ngx_spdy_frame_parse_uint32(pos); ++ ++ pos += NGX_SPDY_SETTINGS_NUM_SIZE; ++ sc->length -= NGX_SPDY_SETTINGS_NUM_SIZE; ++ ++ if (sc->length < sc->entries * NGX_SPDY_SETTINGS_PAIR_SIZE) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SETTINGS frame with incorrect " ++ "length %uz or number of entries %ui", ++ sc->length, sc->entries); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy SETTINGS frame has %ui entries", sc->entries); ++ } ++ ++ while (sc->entries) { ++ if (end - pos < NGX_SPDY_SETTINGS_PAIR_SIZE) { ++ return ngx_http_spdy_state_save(sc, pos, end, ++ ngx_http_spdy_state_settings); ++ } ++ ++ sc->entries--; ++ sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE; ++ ++ fid = ngx_spdy_frame_parse_uint32(pos); ++ ++ pos += NGX_SPDY_SETTINGS_FID_SIZE; ++ ++ val = ngx_spdy_frame_parse_uint32(pos); ++ ++ pos += NGX_SPDY_SETTINGS_VAL_SIZE; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy SETTINGS entry fl:%ui id:%ui val:%ui", ++ ngx_spdy_frame_flags(fid), ngx_spdy_frame_id(fid), val); ++ ++ if (ngx_spdy_frame_flags(fid) == NGX_SPDY_SETTINGS_FLAG_PERSISTED) { ++ continue; ++ } ++ ++ switch (ngx_spdy_frame_id(fid)) { ++ ++ case NGX_SPDY_SETTINGS_INIT_WINDOW: ++ ++ if (val > NGX_SPDY_MAX_WINDOW) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SETTINGS frame with " ++ "incorrect INIT_WINDOW value: %ui", val); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ if (ngx_http_spdy_adjust_windows(sc, val - sc->init_window) ++ != NGX_OK) ++ { ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ sc->init_window = val; ++ ++ continue; ++ } ++ } ++ ++ return ngx_http_spdy_state_complete(sc, pos, end); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, u_char *pos, ++ u_char *end) ++{ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy frame complete pos:%p end:%p", pos, end); ++ ++ if (pos > end) { ++ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, ++ "receive buffer overrun"); ++ ++ ngx_debug_point(); ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ sc->handler = ngx_http_spdy_state_head; ++ sc->stream = NULL; ++ ++ return pos; ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler) ++{ ++ size_t size; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy frame state save pos:%p end:%p handler:%p", ++ pos, end, handler); ++ ++ size = end - pos; ++ ++ if (size > NGX_SPDY_STATE_BUFFER_SIZE) { ++ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, ++ "state buffer overflow: %uz bytes required", size); ++ ++ ngx_debug_point(); ++ return ngx_http_spdy_state_internal_error(sc); ++ } ++ ++ ngx_memcpy(sc->buffer, pos, NGX_SPDY_STATE_BUFFER_SIZE); ++ ++ sc->buffer_used = size; ++ sc->handler = handler; ++ sc->incomplete = 1; ++ ++ return end; ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_inflate_error(ngx_http_spdy_connection_t *sc, int rc) ++{ ++ if (rc == Z_DATA_ERROR || rc == Z_STREAM_END) { ++ ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, ++ "client sent SYN_STREAM frame with " ++ "corrupted header block, inflate() failed: %d", rc); ++ ++ return ngx_http_spdy_state_protocol_error(sc); ++ } ++ ++ ngx_log_error(NGX_LOG_ERR, sc->connection->log, 0, ++ "inflate() failed: %d", rc); ++ ++ return ngx_http_spdy_state_internal_error(sc); ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_protocol_error(ngx_http_spdy_connection_t *sc) ++{ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy state protocol error"); ++ ++ if (sc->stream) { ++ sc->stream->out_closed = 1; ++ ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST); ++ } ++ ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); ++ ++ return NULL; ++} ++ ++ ++static u_char * ++ngx_http_spdy_state_internal_error(ngx_http_spdy_connection_t *sc) ++{ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy state internal error"); ++ ++ if (sc->stream) { ++ sc->stream->out_closed = 1; ++ ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ } ++ ++ ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ ++ return NULL; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_send_window_update(ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ++ ngx_uint_t delta) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy send WINDOW_UPDATE sid:%ui delta:%ui", sid, delta); ++ ++ frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_WINDOW_UPDATE_SIZE, ++ NGX_SPDY_HIGHEST_PRIORITY); ++ if (frame == NULL) { ++ return NGX_ERROR; ++ } ++ ++ buf = frame->first->buf; ++ ++ p = buf->pos; ++ ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_WINDOW_UPDATE); ++ p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_WINDOW_UPDATE_SIZE); ++ ++ p = ngx_spdy_frame_write_sid(p, sid); ++ p = ngx_spdy_frame_aligned_write_uint32(p, delta); ++ ++ buf->last = p; ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ++ ngx_uint_t status, ngx_uint_t priority) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ if (sc->connection->error) { ++ return NGX_OK; ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy send RST_STREAM sid:%ui st:%ui", sid, status); ++ ++ frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_RST_STREAM_SIZE, ++ priority); ++ if (frame == NULL) { ++ return NGX_ERROR; ++ } ++ ++ buf = frame->first->buf; ++ ++ p = buf->pos; ++ ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_RST_STREAM); ++ p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_RST_STREAM_SIZE); ++ ++ p = ngx_spdy_frame_write_sid(p, sid); ++ p = ngx_spdy_frame_aligned_write_uint32(p, status); ++ ++ buf->last = p; ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ return NGX_OK; ++} ++ ++ ++#if 0 ++static ngx_int_t ++ngx_http_spdy_send_goaway(ngx_http_spdy_connection_t *sc) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy send GOAWAY sid:%ui", sc->last_sid); ++ ++ frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_GOAWAY_SIZE, ++ NGX_SPDY_HIGHEST_PRIORITY); ++ if (frame == NULL) { ++ return NGX_ERROR; ++ } ++ ++ buf = frame->first->buf; ++ ++ p = buf->pos; ++ ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_GOAWAY); ++ p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_GOAWAY_SIZE); ++ ++ p = ngx_spdy_frame_write_sid(p, sc->last_sid); ++ ++ buf->last = p; ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ return NGX_OK; ++} ++#endif ++ ++ ++static ngx_int_t ++ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_chain_t *cl; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy send SETTINGS frame"); ++ ++ frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t)); ++ if (frame == NULL) { ++ return NGX_ERROR; ++ } ++ ++ cl = ngx_alloc_chain_link(sc->pool); ++ if (cl == NULL) { ++ return NGX_ERROR; ++ } ++ ++ buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE ++ + NGX_SPDY_SETTINGS_NUM_SIZE ++ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE); ++ if (buf == NULL) { ++ return NGX_ERROR; ++ } ++ ++ buf->last_buf = 1; ++ ++ cl->buf = buf; ++ cl->next = NULL; ++ ++ frame->first = cl; ++ frame->last = cl; ++ frame->handler = ngx_http_spdy_settings_frame_handler; ++ frame->stream = NULL; ++#if (NGX_DEBUG) ++ frame->length = NGX_SPDY_SETTINGS_NUM_SIZE ++ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE; ++#endif ++ frame->priority = NGX_SPDY_HIGHEST_PRIORITY; ++ frame->blocked = 0; ++ ++ p = buf->pos; ++ ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS); ++ p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS, ++ NGX_SPDY_SETTINGS_NUM_SIZE ++ + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE); ++ ++ p = ngx_spdy_frame_aligned_write_uint32(p, 2); ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_MAX_STREAMS); ++ p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams); ++ ++ p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_INIT_WINDOW); ++ p = ngx_spdy_frame_aligned_write_uint32(p, NGX_SPDY_STREAM_WINDOW); ++ ++ buf->last = p; ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ return NGX_OK; ++} ++ ++ ++ngx_int_t ++ngx_http_spdy_settings_frame_handler(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_buf_t *buf; ++ ++ buf = frame->first->buf; ++ ++ if (buf->pos != buf->last) { ++ return NGX_AGAIN; ++ } ++ ++ ngx_free_chain(sc->pool, frame->first); ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_http_spdy_out_frame_t * ++ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t length, ++ ngx_uint_t priority) ++{ ++ ngx_chain_t *cl; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ frame = sc->free_ctl_frames; ++ ++ if (frame) { ++ sc->free_ctl_frames = frame->next; ++ ++ cl = frame->first; ++ cl->buf->pos = cl->buf->start; ++ ++ } else { ++ frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t)); ++ if (frame == NULL) { ++ return NULL; ++ } ++ ++ cl = ngx_alloc_chain_link(sc->pool); ++ if (cl == NULL) { ++ return NULL; ++ } ++ ++ cl->buf = ngx_create_temp_buf(sc->pool, ++ NGX_SPDY_CTL_FRAME_BUFFER_SIZE); ++ if (cl->buf == NULL) { ++ return NULL; ++ } ++ ++ cl->buf->last_buf = 1; ++ ++ frame->first = cl; ++ frame->last = cl; ++ frame->handler = ngx_http_spdy_ctl_frame_handler; ++ frame->stream = NULL; ++ } ++ ++#if (NGX_DEBUG) ++ if (length > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) { ++ ngx_log_error(NGX_LOG_ALERT, sc->pool->log, 0, ++ "requested control frame is too large: %uz", length); ++ return NULL; ++ } ++ ++ frame->length = length; ++#endif ++ ++ frame->priority = priority; ++ frame->blocked = 0; ++ ++ return frame; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_ctl_frame_handler(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_buf_t *buf; ++ ++ buf = frame->first->buf; ++ ++ if (buf->pos != buf->last) { ++ return NGX_AGAIN; ++ } ++ ++ frame->next = sc->free_ctl_frames; ++ sc->free_ctl_frames = frame; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_http_spdy_stream_t * ++ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id, ++ ngx_uint_t priority) ++{ ++ ngx_log_t *log; ++ ngx_uint_t index; ++ ngx_event_t *rev, *wev; ++ ngx_connection_t *fc; ++ ngx_http_log_ctx_t *ctx; ++ ngx_http_request_t *r; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_core_srv_conf_t *cscf; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ fc = sc->free_fake_connections; ++ ++ if (fc) { ++ sc->free_fake_connections = fc->data; ++ ++ rev = fc->read; ++ wev = fc->write; ++ log = fc->log; ++ ctx = log->data; ++ ++ } else { ++ fc = ngx_palloc(sc->pool, sizeof(ngx_connection_t)); ++ if (fc == NULL) { ++ return NULL; ++ } ++ ++ rev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); ++ if (rev == NULL) { ++ return NULL; ++ } ++ ++ wev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); ++ if (wev == NULL) { ++ return NULL; ++ } ++ ++ log = ngx_palloc(sc->pool, sizeof(ngx_log_t)); ++ if (log == NULL) { ++ return NULL; ++ } ++ ++ ctx = ngx_palloc(sc->pool, sizeof(ngx_http_log_ctx_t)); ++ if (ctx == NULL) { ++ return NULL; ++ } ++ ++ ctx->connection = fc; ++ ctx->request = NULL; ++ } ++ ++ ngx_memcpy(log, sc->connection->log, sizeof(ngx_log_t)); ++ ++ log->data = ctx; ++ ++ ngx_memzero(rev, sizeof(ngx_event_t)); ++ ++ rev->data = fc; ++ rev->ready = 1; ++ rev->handler = ngx_http_spdy_close_stream_handler; ++ rev->log = log; ++ ++ ngx_memcpy(wev, rev, sizeof(ngx_event_t)); ++ ++ wev->write = 1; ++ ++ ngx_memcpy(fc, sc->connection, sizeof(ngx_connection_t)); ++ ++ fc->data = sc->http_connection; ++ fc->read = rev; ++ fc->write = wev; ++ fc->sent = 0; ++ fc->log = log; ++ fc->buffered = 0; ++ fc->sndlowat = 1; ++ fc->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; ++ ++ r = ngx_http_create_request(fc); ++ if (r == NULL) { ++ return NULL; ++ } ++ ++ r->valid_location = 1; ++ ++ fc->data = r; ++ sc->connection->requests++; ++ ++ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ++ ++ r->header_in = ngx_create_temp_buf(r->pool, ++ cscf->client_header_buffer_size); ++ if (r->header_in == NULL) { ++ ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return NULL; ++ } ++ ++ r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; ++ ++ stream = ngx_pcalloc(r->pool, sizeof(ngx_http_spdy_stream_t)); ++ if (stream == NULL) { ++ ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return NULL; ++ } ++ ++ r->spdy_stream = stream; ++ ++ stream->id = id; ++ stream->request = r; ++ stream->connection = sc; ++ ++ stream->send_window = sc->init_window; ++ stream->recv_window = NGX_SPDY_STREAM_WINDOW; ++ ++ stream->priority = priority; ++ ++ sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module); ++ ++ index = ngx_http_spdy_stream_index(sscf, id); ++ ++ stream->index = sc->streams_index[index]; ++ sc->streams_index[index] = stream; ++ ++ sc->processing++; ++ ++ return stream; ++} ++ ++ ++static ngx_http_spdy_stream_t * ++ngx_http_spdy_get_stream_by_id(ngx_http_spdy_connection_t *sc, ++ ngx_uint_t sid) ++{ ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ stream = sc->streams_index[ngx_http_spdy_stream_index(sscf, sid)]; ++ ++ while (stream) { ++ if (stream->id == sid) { ++ return stream; ++ } ++ ++ stream = stream->index; ++ } ++ ++ return NULL; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_header(ngx_http_request_t *r) ++{ ++ u_char *p, *end, ch; ++ ngx_uint_t hash; ++ ngx_http_core_srv_conf_t *cscf; ++ ++ enum { ++ sw_name_len = 0, ++ sw_name, ++ sw_value_len, ++ sw_value ++ } state; ++ ++ state = r->state; ++ ++ p = r->header_in->pos; ++ end = r->header_in->last; ++ ++ switch (state) { ++ ++ case sw_name_len: ++ ++ if (end - p < NGX_SPDY_NV_NLEN_SIZE) { ++ return NGX_AGAIN; ++ } ++ ++ r->lowcase_index = ngx_spdy_frame_parse_uint32(p); ++ ++ if (r->lowcase_index == 0) { ++ return NGX_ERROR; ++ } ++ ++ /* null-terminate the previous header value */ ++ *p = '\0'; ++ ++ p += NGX_SPDY_NV_NLEN_SIZE; ++ ++ r->invalid_header = 0; ++ ++ state = sw_name; ++ ++ /* fall through */ ++ ++ case sw_name: ++ ++ if ((ngx_uint_t) (end - p) < r->lowcase_index) { ++ break; ++ } ++ ++ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ++ ++ r->header_name_start = p; ++ r->header_name_end = p + r->lowcase_index; ++ ++ if (p[0] == ':') { ++ p++; ++ } ++ ++ hash = 0; ++ ++ for ( /* void */ ; p != r->header_name_end; p++) { ++ ++ ch = *p; ++ ++ hash = ngx_hash(hash, ch); ++ ++ if ((ch >= 'a' && ch <= 'z') ++ || (ch == '-') ++ || (ch >= '0' && ch <= '9') ++ || (ch == '_' && cscf->underscores_in_headers)) ++ { ++ continue; ++ } ++ ++ switch (ch) { ++ case '\0': ++ case LF: ++ case CR: ++ case ':': ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid header name: \"%*s\"", ++ r->lowcase_index, r->header_name_start); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ if (ch >= 'A' && ch <= 'Z') { ++ return NGX_ERROR; ++ } ++ ++ r->invalid_header = 1; ++ } ++ ++ r->header_hash = hash; ++ ++ state = sw_value_len; ++ ++ /* fall through */ ++ ++ case sw_value_len: ++ ++ if (end - p < NGX_SPDY_NV_VLEN_SIZE) { ++ break; ++ } ++ ++ r->lowcase_index = ngx_spdy_frame_parse_uint32(p); ++ ++ /* null-terminate header name */ ++ *p = '\0'; ++ ++ p += NGX_SPDY_NV_VLEN_SIZE; ++ ++ state = sw_value; ++ ++ /* fall through */ ++ ++ case sw_value: ++ ++ if ((ngx_uint_t) (end - p) < r->lowcase_index) { ++ break; ++ } ++ ++ r->header_start = p; ++ ++ while (r->lowcase_index--) { ++ ch = *p; ++ ++ if (ch == '\0') { ++ ++ if (p == r->header_start) { ++ return NGX_ERROR; ++ } ++ ++ r->header_end = p; ++ r->header_in->pos = p + 1; ++ ++ r->state = sw_value; ++ ++ return NGX_OK; ++ } ++ ++ if (ch == CR || ch == LF) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent header \"%*s\" with " ++ "invalid value: \"%*s\\%c...\"", ++ r->header_name_end - r->header_name_start, ++ r->header_name_start, ++ p - r->header_start, ++ r->header_start, ++ ch == CR ? 'r' : 'n'); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ p++; ++ } ++ ++ r->header_end = p; ++ r->header_in->pos = p; ++ ++ r->state = 0; ++ ++ return NGX_DONE; ++ } ++ ++ r->header_in->pos = p; ++ r->state = state; ++ ++ return NGX_AGAIN; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r) ++{ ++ u_char *old, *new, *p; ++ size_t rest; ++ ngx_buf_t *buf; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_core_srv_conf_t *cscf; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy alloc large header buffer"); ++ ++ stream = r->spdy_stream; ++ ++ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ++ ++ if (stream->header_buffers ++ == (ngx_uint_t) cscf->large_client_header_buffers.num) ++ { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent too large request"); ++ ++ return NGX_DECLINED; ++ } ++ ++ rest = r->header_in->last - r->header_in->pos; ++ ++ /* ++ * One more byte is needed for null-termination ++ * and another one for further progress. ++ */ ++ if (rest > cscf->large_client_header_buffers.size - 2) { ++ p = r->header_in->pos; ++ ++ if (rest > NGX_MAX_ERROR_STR - 300) { ++ rest = NGX_MAX_ERROR_STR - 300; ++ } ++ ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent too long header name or value: \"%*s...\"", ++ rest, p); ++ ++ return NGX_DECLINED; ++ } ++ ++ buf = ngx_create_temp_buf(r->pool, cscf->large_client_header_buffers.size); ++ if (buf == NULL) { ++ return NGX_ERROR; ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy large header alloc: %p %uz", ++ buf->pos, buf->end - buf->last); ++ ++ old = r->header_in->pos; ++ new = buf->pos; ++ ++ if (rest) { ++ buf->last = ngx_cpymem(new, old, rest); ++ } ++ ++ r->header_in = buf; ++ ++ stream->header_buffers++; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_handle_request_header(ngx_http_request_t *r) ++{ ++ ngx_uint_t i; ++ ngx_table_elt_t *h; ++ ngx_http_core_srv_conf_t *cscf; ++ ngx_http_spdy_request_header_t *sh; ++ ++ if (r->invalid_header) { ++ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ++ ++ if (cscf->ignore_invalid_headers) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid header: \"%*s\"", ++ r->header_end - r->header_name_start, ++ r->header_name_start); ++ return NGX_OK; ++ } ++ ++ } ++ ++ if (r->header_name_start[0] == ':') { ++ r->header_name_start++; ++ ++ for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) { ++ sh = &ngx_http_spdy_request_headers[i]; ++ ++ if (sh->hash != r->header_hash ++ || sh->len != r->header_name_end - r->header_name_start ++ || ngx_strncmp(sh->header, r->header_name_start, sh->len) != 0) ++ { ++ continue; ++ } ++ ++ return sh->handler(r); ++ } ++ ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid header name: \":%*s\"", ++ r->header_end - r->header_name_start, ++ r->header_name_start); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ h = ngx_list_push(&r->headers_in.headers); ++ if (h == NULL) { ++ return NGX_ERROR; ++ } ++ ++ h->hash = r->header_hash; ++ ++ h->key.len = r->header_name_end - r->header_name_start; ++ h->key.data = r->header_name_start; ++ ++ h->value.len = r->header_end - r->header_start; ++ h->value.data = r->header_start; ++ ++ h->lowcase_key = h->key.data; ++ ++ return NGX_OK; ++} ++ ++ ++void ++ngx_http_spdy_request_headers_init(void) ++{ ++ ngx_uint_t i; ++ ngx_http_spdy_request_header_t *h; ++ ++ for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) { ++ h = &ngx_http_spdy_request_headers[i]; ++ h->hash = ngx_hash_key(h->header, h->len); ++ } ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_method(ngx_http_request_t *r) ++{ ++ size_t k, len; ++ ngx_uint_t n; ++ const u_char *p, *m; ++ ++ /* ++ * This array takes less than 256 sequential bytes, ++ * and if typical CPU cache line size is 64 bytes, ++ * it is prefetched for 4 load operations. ++ */ ++ static const struct { ++ u_char len; ++ const u_char method[11]; ++ uint32_t value; ++ } tests[] = { ++ { 3, "GET", NGX_HTTP_GET }, ++ { 4, "POST", NGX_HTTP_POST }, ++ { 4, "HEAD", NGX_HTTP_HEAD }, ++ { 7, "OPTIONS", NGX_HTTP_OPTIONS }, ++ { 8, "PROPFIND", NGX_HTTP_PROPFIND }, ++ { 3, "PUT", NGX_HTTP_PUT }, ++ { 5, "MKCOL", NGX_HTTP_MKCOL }, ++ { 6, "DELETE", NGX_HTTP_DELETE }, ++ { 4, "COPY", NGX_HTTP_COPY }, ++ { 4, "MOVE", NGX_HTTP_MOVE }, ++ { 9, "PROPPATCH", NGX_HTTP_PROPPATCH }, ++ { 4, "LOCK", NGX_HTTP_LOCK }, ++ { 6, "UNLOCK", NGX_HTTP_UNLOCK }, ++ { 5, "PATCH", NGX_HTTP_PATCH }, ++ { 5, "TRACE", NGX_HTTP_TRACE } ++ }, *test; ++ ++ if (r->method_name.len) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent duplicate :method header"); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ len = r->header_end - r->header_start; ++ ++ r->method_name.len = len; ++ r->method_name.data = r->header_start; ++ ++ test = tests; ++ n = sizeof(tests) / sizeof(tests[0]); ++ ++ do { ++ if (len == test->len) { ++ p = r->method_name.data; ++ m = test->method; ++ k = len; ++ ++ do { ++ if (*p++ != *m++) { ++ goto next; ++ } ++ } while (--k); ++ ++ r->method = test->value; ++ return NGX_OK; ++ } ++ ++ next: ++ test++; ++ ++ } while (--n); ++ ++ p = r->method_name.data; ++ ++ do { ++ if ((*p < 'A' || *p > 'Z') && *p != '_') { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid method: \"%V\"", ++ &r->method_name); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ p++; ++ ++ } while (--len); ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_scheme(ngx_http_request_t *r) ++{ ++ if (r->schema_start) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent duplicate :schema header"); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ r->schema_start = r->header_start; ++ r->schema_end = r->header_end; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_host(ngx_http_request_t *r) ++{ ++ ngx_table_elt_t *h; ++ ++ if (r->headers_in.host) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent duplicate :host header"); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ h = ngx_list_push(&r->headers_in.headers); ++ if (h == NULL) { ++ return NGX_ERROR; ++ } ++ ++ r->headers_in.host = h; ++ ++ h->hash = r->header_hash; ++ ++ h->key.len = r->header_name_end - r->header_name_start; ++ h->key.data = r->header_name_start; ++ ++ h->value.len = r->header_end - r->header_start; ++ h->value.data = r->header_start; ++ ++ h->lowcase_key = h->key.data; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_path(ngx_http_request_t *r) ++{ ++ if (r->unparsed_uri.len) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent duplicate :path header"); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ r->uri_start = r->header_start; ++ r->uri_end = r->header_end; ++ ++ if (ngx_http_parse_uri(r) != NGX_OK) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid URI: \"%*s\"", ++ r->uri_end - r->uri_start, r->uri_start); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ if (ngx_http_process_request_uri(r) != NGX_OK) { ++ /* ++ * request has been finalized already ++ * in ngx_http_process_request_uri() ++ */ ++ return NGX_ABORT; ++ } ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_parse_version(ngx_http_request_t *r) ++{ ++ u_char *p, ch; ++ ++ if (r->http_protocol.len) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent duplicate :version header"); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++ } ++ ++ p = r->header_start; ++ ++ if (r->header_end - p < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) { ++ goto invalid; ++ } ++ ++ ch = *(p + 5); ++ ++ if (ch < '1' || ch > '9') { ++ goto invalid; ++ } ++ ++ r->http_major = ch - '0'; ++ ++ for (p += 6; p != r->header_end - 2; p++) { ++ ++ ch = *p; ++ ++ if (ch == '.') { ++ break; ++ } ++ ++ if (ch < '0' || ch > '9') { ++ goto invalid; ++ } ++ ++ r->http_major = r->http_major * 10 + ch - '0'; ++ } ++ ++ if (*p != '.') { ++ goto invalid; ++ } ++ ++ ch = *(p + 1); ++ ++ if (ch < '0' || ch > '9') { ++ goto invalid; ++ } ++ ++ r->http_minor = ch - '0'; ++ ++ for (p += 2; p != r->header_end; p++) { ++ ++ ch = *p; ++ ++ if (ch < '0' || ch > '9') { ++ goto invalid; ++ } ++ ++ r->http_minor = r->http_minor * 10 + ch - '0'; ++ } ++ ++ r->http_protocol.len = r->header_end - r->header_start; ++ r->http_protocol.data = r->header_start; ++ r->http_version = r->http_major * 1000 + r->http_minor; ++ ++ return NGX_OK; ++ ++invalid: ++ ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent invalid http version: \"%*s\"", ++ r->header_end - r->header_start, r->header_start); ++ ++ return NGX_HTTP_PARSE_INVALID_HEADER; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_construct_request_line(ngx_http_request_t *r) ++{ ++ u_char *p; ++ ++ if (r->method_name.len == 0 ++ || r->unparsed_uri.len == 0 ++ || r->http_protocol.len == 0) ++ { ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return NGX_ERROR; ++ } ++ ++ r->request_line.len = r->method_name.len + 1 ++ + r->unparsed_uri.len + 1 ++ + r->http_protocol.len; ++ ++ p = ngx_pnalloc(r->pool, r->request_line.len + 1); ++ if (p == NULL) { ++ ngx_http_spdy_close_stream(r->spdy_stream, ++ NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return NGX_ERROR; ++ } ++ ++ r->request_line.data = p; ++ ++ p = ngx_cpymem(p, r->method_name.data, r->method_name.len); ++ ++ *p++ = ' '; ++ ++ p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len); ++ ++ *p++ = ' '; ++ ++ ngx_memcpy(p, r->http_protocol.data, r->http_protocol.len + 1); ++ ++ /* some modules expect the space character after method name */ ++ r->method_name.data = r->request_line.data; ++ ++ return NGX_OK; ++} ++ ++ ++static void ++ngx_http_spdy_run_request(ngx_http_request_t *r) ++{ ++ ngx_uint_t i; ++ ngx_list_part_t *part; ++ ngx_table_elt_t *h; ++ ngx_http_header_t *hh; ++ ngx_http_core_main_conf_t *cmcf; ++ ++ if (ngx_http_spdy_construct_request_line(r) != NGX_OK) { ++ return; ++ } ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy http request line: \"%V\"", &r->request_line); ++ ++ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ++ ++ part = &r->headers_in.headers.part; ++ h = part->elts; ++ ++ for (i = 0 ;; i++) { ++ ++ if (i >= part->nelts) { ++ if (part->next == NULL) { ++ break; ++ } ++ ++ part = part->next; ++ h = part->elts; ++ i = 0; ++ } ++ ++ hh = ngx_hash_find(&cmcf->headers_in_hash, h[i].hash, ++ h[i].lowcase_key, h[i].key.len); ++ ++ if (hh && hh->handler(r, &h[i], hh->offset) != NGX_OK) { ++ return; ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy http header: \"%V: %V\"", &h[i].key, &h[i].value); ++ } ++ ++ r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; ++ ++ if (ngx_http_process_request_header(r) != NGX_OK) { ++ return; ++ } ++ ++ if (r->headers_in.content_length_n > 0 && r->spdy_stream->in_closed) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client prematurely closed stream"); ++ ++ r->spdy_stream->skip_data = NGX_SPDY_DATA_ERROR; ++ ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return; ++ } ++ ++ ngx_http_process_request(r); ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_init_request_body(ngx_http_request_t *r) ++{ ++ ngx_buf_t *buf; ++ ngx_temp_file_t *tf; ++ ngx_http_request_body_t *rb; ++ ngx_http_core_loc_conf_t *clcf; ++ ++ rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); ++ if (rb == NULL) { ++ return NGX_ERROR; ++ } ++ ++ r->request_body = rb; ++ ++ if (r->spdy_stream->in_closed) { ++ return NGX_OK; ++ } ++ ++ rb->rest = r->headers_in.content_length_n; ++ ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ ++ if (r->request_body_in_file_only ++ || rb->rest > (off_t) clcf->client_body_buffer_size ++ || rb->rest < 0) ++ { ++ tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); ++ if (tf == NULL) { ++ return NGX_ERROR; ++ } ++ ++ tf->file.fd = NGX_INVALID_FILE; ++ tf->file.log = r->connection->log; ++ tf->path = clcf->client_body_temp_path; ++ tf->pool = r->pool; ++ tf->warn = "a client request body is buffered to a temporary file"; ++ tf->log_level = r->request_body_file_log_level; ++ tf->persistent = r->request_body_in_persistent_file; ++ tf->clean = r->request_body_in_clean_file; ++ ++ if (r->request_body_file_group_access) { ++ tf->access = 0660; ++ } ++ ++ rb->temp_file = tf; ++ ++ if (r->spdy_stream->in_closed ++ && ngx_create_temp_file(&tf->file, tf->path, tf->pool, ++ tf->persistent, tf->clean, tf->access) ++ != NGX_OK) ++ { ++ return NGX_ERROR; ++ } ++ ++ buf = ngx_calloc_buf(r->pool); ++ if (buf == NULL) { ++ return NGX_ERROR; ++ } ++ ++ } else { ++ ++ if (rb->rest == 0) { ++ return NGX_OK; ++ } ++ ++ buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest); ++ if (buf == NULL) { ++ return NGX_ERROR; ++ } ++ } ++ ++ rb->buf = buf; ++ ++ rb->bufs = ngx_alloc_chain_link(r->pool); ++ if (rb->bufs == NULL) { ++ return NGX_ERROR; ++ } ++ ++ rb->bufs->buf = buf; ++ rb->bufs->next = NULL; ++ ++ rb->rest = 0; ++ ++ return NGX_OK; ++} ++ ++ ++ngx_int_t ++ngx_http_spdy_read_request_body(ngx_http_request_t *r, ++ ngx_http_client_body_handler_pt post_handler) ++{ ++ ngx_http_spdy_stream_t *stream; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy read request body"); ++ ++ stream = r->spdy_stream; ++ ++ switch (stream->skip_data) { ++ ++ case NGX_SPDY_DATA_DISCARD: ++ post_handler(r); ++ return NGX_OK; ++ ++ case NGX_SPDY_DATA_ERROR: ++ if (r->headers_in.content_length_n == -1) { ++ return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; ++ } else { ++ return NGX_HTTP_BAD_REQUEST; ++ } ++ ++ case NGX_SPDY_DATA_INTERNAL_ERROR: ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ if (!r->request_body && ngx_http_spdy_init_request_body(r) != NGX_OK) { ++ stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ if (stream->in_closed) { ++ post_handler(r); ++ return NGX_OK; ++ } ++ ++ r->request_body->post_handler = post_handler; ++ ++ r->read_event_handler = ngx_http_test_reading; ++ r->write_event_handler = ngx_http_request_empty_handler; ++ ++ return NGX_AGAIN; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream, ngx_uint_t status) ++{ ++ ngx_event_t *rev; ++ ngx_connection_t *fc; ++ ++ if (ngx_http_spdy_send_rst_stream(sc, stream->id, status, ++ NGX_SPDY_HIGHEST_PRIORITY) ++ == NGX_ERROR) ++ { ++ return NGX_ERROR; ++ } ++ ++ stream->out_closed = 1; ++ ++ fc = stream->request->connection; ++ fc->error = 1; ++ ++ rev = fc->read; ++ rev->handler(rev); ++ ++ return NGX_OK; ++} ++ ++ ++static void ++ngx_http_spdy_close_stream_handler(ngx_event_t *ev) ++{ ++ ngx_connection_t *fc; ++ ngx_http_request_t *r; ++ ++ fc = ev->data; ++ r = fc->data; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy close stream handler"); ++ ++ ngx_http_spdy_close_stream(r->spdy_stream, 0); ++} ++ ++ ++void ++ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) ++{ ++ ngx_event_t *ev; ++ ngx_connection_t *fc; ++ ngx_http_spdy_stream_t **index, *s; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ngx_http_spdy_connection_t *sc; ++ ++ sc = stream->connection; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy close stream %ui, queued %ui, processing %ui", ++ stream->id, stream->queued, sc->processing); ++ ++ fc = stream->request->connection; ++ ++ if (stream->queued) { ++ fc->write->handler = ngx_http_spdy_close_stream_handler; ++ return; ++ } ++ ++ if (!stream->out_closed) { ++ if (ngx_http_spdy_send_rst_stream(sc, stream->id, ++ NGX_SPDY_INTERNAL_ERROR, ++ stream->priority) ++ != NGX_OK) ++ { ++ sc->connection->error = 1; ++ } ++ } ++ ++ if (sc->stream == stream) { ++ sc->stream = NULL; ++ } ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ index = sc->streams_index + ngx_http_spdy_stream_index(sscf, stream->id); ++ ++ for ( ;; ) { ++ s = *index; ++ ++ if (s == NULL) { ++ break; ++ } ++ ++ if (s == stream) { ++ *index = s->index; ++ break; ++ } ++ ++ index = &s->index; ++ } ++ ++ ngx_http_free_request(stream->request, rc); ++ ++ ev = fc->read; ++ ++ if (ev->active || ev->disabled) { ++ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, ++ "fake read event was activated"); ++ } ++ ++ if (ev->timer_set) { ++ ngx_del_timer(ev); ++ } ++ ++ if (ev->posted) { ++ ngx_delete_posted_event(ev); ++ } ++ ++ ev = fc->write; ++ ++ if (ev->active || ev->disabled) { ++ ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, ++ "fake write event was activated"); ++ } ++ ++ if (ev->timer_set) { ++ ngx_del_timer(ev); ++ } ++ ++ if (ev->posted) { ++ ngx_delete_posted_event(ev); ++ } ++ ++ fc->data = sc->free_fake_connections; ++ sc->free_fake_connections = fc; ++ ++ sc->processing--; ++ ++ if (sc->processing || sc->blocked) { ++ return; ++ } ++ ++ ev = sc->connection->read; ++ ++ ev->handler = ngx_http_spdy_handle_connection_handler; ++ ngx_post_event(ev, &ngx_posted_events); ++} ++ ++ ++static void ++ngx_http_spdy_handle_connection_handler(ngx_event_t *rev) ++{ ++ ngx_connection_t *c; ++ ++ rev->handler = ngx_http_spdy_read_handler; ++ ++ if (rev->ready) { ++ ngx_http_spdy_read_handler(rev); ++ return; ++ } ++ ++ c = rev->data; ++ ++ ngx_http_spdy_handle_connection(c->data); ++} ++ ++ ++static void ++ngx_http_spdy_keepalive_handler(ngx_event_t *rev) ++{ ++ ngx_connection_t *c; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ngx_http_spdy_connection_t *sc; ++ ++ c = rev->data; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy keepalive handler"); ++ ++ if (rev->timedout || c->close) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++#if (NGX_HAVE_KQUEUE) ++ ++ if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { ++ if (rev->pending_eof) { ++ c->log->handler = NULL; ++ ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, ++ "kevent() reported that client %V closed " ++ "keepalive connection", &c->addr_text); ++#if (NGX_HTTP_SSL) ++ if (c->ssl) { ++ c->ssl->no_send_shutdown = 1; ++ } ++#endif ++ ngx_http_close_connection(c); ++ return; ++ } ++ } ++ ++#endif ++ ++ c->destroyed = 0; ++ c->idle = 0; ++ ngx_reusable_connection(c, 0); ++ ++ sc = c->data; ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ sc->pool = ngx_create_pool(sscf->pool_size, sc->connection->log); ++ if (sc->pool == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ sc->streams_index = ngx_pcalloc(sc->pool, ++ ngx_http_spdy_streams_index_size(sscf) ++ * sizeof(ngx_http_spdy_stream_t *)); ++ if (sc->streams_index == NULL) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ c->write->handler = ngx_http_spdy_write_handler; ++ ++ rev->handler = ngx_http_spdy_read_handler; ++ ngx_http_spdy_read_handler(rev); ++} ++ ++ ++static void ++ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, ++ ngx_int_t rc) ++{ ++ ngx_uint_t i, size; ++ ngx_event_t *ev; ++ ngx_connection_t *c, *fc; ++ ngx_http_request_t *r; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ c = sc->connection; ++ ++ if (!sc->processing) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ c->error = 1; ++ c->read->handler = ngx_http_empty_handler; ++ c->write->handler = ngx_http_empty_handler; ++ ++ sc->last_out = NULL; ++ ++ sc->blocked = 1; ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ size = ngx_http_spdy_streams_index_size(sscf); ++ ++ for (i = 0; i < size; i++) { ++ stream = sc->streams_index[i]; ++ ++ while (stream) { ++ stream->handled = 0; ++ ++ r = stream->request; ++ fc = r->connection; ++ ++ fc->error = 1; ++ ++ if (stream->queued) { ++ stream->queued = 0; ++ ++ ev = fc->write; ++ ev->delayed = 0; ++ ++ } else { ++ ev = fc->read; ++ } ++ ++ stream = stream->index; ++ ++ ev->eof = 1; ++ ev->handler(ev); ++ } ++ } ++ ++ sc->blocked = 0; ++ ++ if (sc->processing) { ++ return; ++ } ++ ++ ngx_http_close_connection(c); ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ssize_t delta) ++{ ++ ngx_uint_t i, size; ++ ngx_event_t *wev; ++ ngx_http_spdy_stream_t *stream, *sn; ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, ++ ngx_http_spdy_module); ++ ++ size = ngx_http_spdy_streams_index_size(sscf); ++ ++ for (i = 0; i < size; i++) { ++ ++ for (stream = sc->streams_index[i]; stream; stream = sn) { ++ sn = stream->index; ++ ++ if (delta > 0 ++ && stream->send_window ++ > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) ++ { ++ if (ngx_http_spdy_terminate_stream(sc, stream, ++ NGX_SPDY_FLOW_CONTROL_ERROR) ++ == NGX_ERROR) ++ { ++ return NGX_ERROR; ++ } ++ ++ continue; ++ } ++ ++ stream->send_window += delta; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy:%ui adjust window:%z", ++ stream->id, stream->send_window); ++ ++ if (stream->send_window > 0 && stream->exhausted) { ++ stream->exhausted = 0; ++ ++ wev = stream->request->connection->write; ++ ++ if (!wev->timer_set) { ++ wev->delayed = 0; ++ wev->handler(wev); ++ } ++ } ++ } ++ } ++ ++ return NGX_OK; ++} ++ ++ ++static void ++ngx_http_spdy_pool_cleanup(void *data) ++{ ++ ngx_http_spdy_connection_t *sc = data; ++ ++ if (sc->pool) { ++ ngx_destroy_pool(sc->pool); ++ } ++} ++ ++ ++static void * ++ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size) ++{ ++ ngx_http_spdy_connection_t *sc = opaque; ++ ++ return ngx_palloc(sc->connection->pool, items * size); ++} ++ ++ ++static void ++ngx_http_spdy_zfree(void *opaque, void *address) ++{ ++#if 0 ++ ngx_http_spdy_connection_t *sc = opaque; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy zfree: %p", address); ++#endif ++} +diff --git a/nginx-1.15.8/src/http/ngx_http_spdy.h b/nginx-1.15.8/src/http/ngx_http_spdy.h +new file mode 100644 +index 0000000..df24495 +--- /dev/null ++++ b/nginx-1.15.8/src/http/ngx_http_spdy.h +@@ -0,0 +1,261 @@ ++/* ++ * Copyright (C) Nginx, Inc. ++ * Copyright (C) Valentin V. Bartenev ++ */ ++ ++ ++#ifndef _NGX_HTTP_SPDY_H_INCLUDED_ ++#define _NGX_HTTP_SPDY_H_INCLUDED_ ++ ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++#define NGX_SPDY_VERSION 3 ++ ++#define NGX_SPDY_NPN_ADVERTISE "\x08spdy/3.1" ++#define NGX_SPDY_NPN_NEGOTIATED "spdy/3.1" ++ ++#define NGX_SPDY_STATE_BUFFER_SIZE 16 ++ ++#define NGX_SPDY_CTL_BIT 1 ++ ++#define NGX_SPDY_SYN_STREAM 1 ++#define NGX_SPDY_SYN_REPLY 2 ++#define NGX_SPDY_RST_STREAM 3 ++#define NGX_SPDY_SETTINGS 4 ++#define NGX_SPDY_PING 6 ++#define NGX_SPDY_GOAWAY 7 ++#define NGX_SPDY_HEADERS 8 ++#define NGX_SPDY_WINDOW_UPDATE 9 ++ ++#define NGX_SPDY_FRAME_HEADER_SIZE 8 ++ ++#define NGX_SPDY_SID_SIZE 4 ++#define NGX_SPDY_DELTA_SIZE 4 ++ ++#define NGX_SPDY_SYN_STREAM_SIZE 10 ++#define NGX_SPDY_SYN_REPLY_SIZE 4 ++#define NGX_SPDY_RST_STREAM_SIZE 8 ++#define NGX_SPDY_PING_SIZE 4 ++#define NGX_SPDY_GOAWAY_SIZE 8 ++#define NGX_SPDY_WINDOW_UPDATE_SIZE 8 ++#define NGX_SPDY_NV_NUM_SIZE 4 ++#define NGX_SPDY_NV_NLEN_SIZE 4 ++#define NGX_SPDY_NV_VLEN_SIZE 4 ++#define NGX_SPDY_SETTINGS_NUM_SIZE 4 ++#define NGX_SPDY_SETTINGS_FID_SIZE 4 ++#define NGX_SPDY_SETTINGS_VAL_SIZE 4 ++ ++#define NGX_SPDY_SETTINGS_PAIR_SIZE \ ++ (NGX_SPDY_SETTINGS_FID_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE) ++ ++#define NGX_SPDY_HIGHEST_PRIORITY 0 ++#define NGX_SPDY_LOWEST_PRIORITY 7 ++ ++#define NGX_SPDY_FLAG_FIN 0x01 ++#define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02 ++#define NGX_SPDY_FLAG_CLEAR_SETTINGS 0x01 ++ ++#define NGX_SPDY_MAX_FRAME_SIZE ((1 << 24) - 1) ++ ++#define NGX_SPDY_DATA_DISCARD 1 ++#define NGX_SPDY_DATA_ERROR 2 ++#define NGX_SPDY_DATA_INTERNAL_ERROR 3 ++ ++ ++typedef struct ngx_http_spdy_connection_s ngx_http_spdy_connection_t; ++typedef struct ngx_http_spdy_out_frame_s ngx_http_spdy_out_frame_t; ++ ++ ++typedef u_char *(*ngx_http_spdy_handler_pt) (ngx_http_spdy_connection_t *sc, ++ u_char *pos, u_char *end); ++ ++struct ngx_http_spdy_connection_s { ++ ngx_connection_t *connection; ++ ngx_http_connection_t *http_connection; ++ ++ ngx_uint_t processing; ++ ++ size_t send_window; ++ size_t recv_window; ++ size_t init_window; ++ ++ ngx_queue_t waiting; ++ ++ u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE]; ++ size_t buffer_used; ++ ngx_http_spdy_handler_pt handler; ++ ++ z_stream zstream_in; ++ z_stream zstream_out; ++ ++ ngx_pool_t *pool; ++ ++ ngx_http_spdy_out_frame_t *free_ctl_frames; ++ ngx_connection_t *free_fake_connections; ++ ++ ngx_http_spdy_stream_t **streams_index; ++ ++ ngx_http_spdy_out_frame_t *last_out; ++ ++ ngx_queue_t posted; ++ ++ ngx_http_spdy_stream_t *stream; ++ ++ ngx_uint_t entries; ++ size_t length; ++ u_char flags; ++ ++ ngx_uint_t last_sid; ++ ++ unsigned blocked:1; ++ unsigned incomplete:1; ++}; ++ ++ ++struct ngx_http_spdy_stream_s { ++ ngx_uint_t id; ++ ngx_http_request_t *request; ++ ngx_http_spdy_connection_t *connection; ++ ngx_http_spdy_stream_t *index; ++ ++ ngx_uint_t header_buffers; ++ ngx_uint_t queued; ++ ++ /* ++ * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the ++ * send_window to become negative, hence it's signed. ++ */ ++ ssize_t send_window; ++ size_t recv_window; ++ ++ ngx_http_spdy_out_frame_t *free_frames; ++ ngx_chain_t *free_data_headers; ++ ngx_chain_t *free_bufs; ++ ++ ngx_queue_t queue; ++ ++ unsigned priority:3; ++ unsigned handled:1; ++ unsigned blocked:1; ++ unsigned exhausted:1; ++ unsigned in_closed:1; ++ unsigned out_closed:1; ++ unsigned skip_data:2; ++}; ++ ++ ++struct ngx_http_spdy_out_frame_s { ++ ngx_http_spdy_out_frame_t *next; ++ ngx_chain_t *first; ++ ngx_chain_t *last; ++ ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame); ++ ++ ngx_http_spdy_stream_t *stream; ++ size_t length; ++ ++ ngx_uint_t priority; ++ unsigned blocked:1; ++ unsigned fin:1; ++}; ++ ++ ++static ngx_inline void ++ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_http_spdy_out_frame_t **out; ++ ++ for (out = &sc->last_out; *out; out = &(*out)->next) ++ { ++ /* ++ * NB: higher values represent lower priorities. ++ */ ++ if (frame->priority >= (*out)->priority) { ++ break; ++ } ++ } ++ ++ frame->next = *out; ++ *out = frame; ++} ++ ++ ++static ngx_inline void ++ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_http_spdy_out_frame_t **out; ++ ++ for (out = &sc->last_out; *out; out = &(*out)->next) ++ { ++ if ((*out)->blocked) { ++ break; ++ } ++ } ++ ++ frame->next = *out; ++ *out = frame; ++} ++ ++ ++void ngx_http_spdy_init(ngx_event_t *rev); ++void ngx_http_spdy_request_headers_init(void); ++ ++ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r, ++ ngx_http_client_body_handler_pt post_handler); ++ ++void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc); ++ ++ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc); ++ ++ ++#define ngx_spdy_frame_aligned_write_uint16(p, s) \ ++ (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) ++ ++#define ngx_spdy_frame_aligned_write_uint32(p, s) \ ++ (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) ++ ++#if (NGX_HAVE_NONALIGNED) ++ ++#define ngx_spdy_frame_write_uint16 ngx_spdy_frame_aligned_write_uint16 ++#define ngx_spdy_frame_write_uint32 ngx_spdy_frame_aligned_write_uint32 ++ ++#else ++ ++#define ngx_spdy_frame_write_uint16(p, s) \ ++ ((p)[0] = (u_char) ((s) >> 8), \ ++ (p)[1] = (u_char) (s), \ ++ (p) + sizeof(uint16_t)) ++ ++#define ngx_spdy_frame_write_uint32(p, s) \ ++ ((p)[0] = (u_char) ((s) >> 24), \ ++ (p)[1] = (u_char) ((s) >> 16), \ ++ (p)[2] = (u_char) ((s) >> 8), \ ++ (p)[3] = (u_char) (s), \ ++ (p) + sizeof(uint32_t)) ++ ++#endif ++ ++ ++#define ngx_spdy_ctl_frame_head(t) \ ++ ((uint32_t) NGX_SPDY_CTL_BIT << 31 | NGX_SPDY_VERSION << 16 | (t)) ++ ++#define ngx_spdy_frame_write_head(p, t) \ ++ ngx_spdy_frame_aligned_write_uint32(p, ngx_spdy_ctl_frame_head(t)) ++ ++#define ngx_spdy_frame_write_flags_and_len(p, f, l) \ ++ ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l)) ++#define ngx_spdy_frame_write_flags_and_id(p, f, i) \ ++ ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (i)) ++ ++#define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32 ++#define ngx_spdy_frame_write_window ngx_spdy_frame_aligned_write_uint32 ++ ++#endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */ +diff --git a/nginx-1.15.8/src/http/ngx_http_spdy_filter_module.c b/nginx-1.15.8/src/http/ngx_http_spdy_filter_module.c +new file mode 100644 +index 0000000..377e935 +--- /dev/null ++++ b/nginx-1.15.8/src/http/ngx_http_spdy_filter_module.c +@@ -0,0 +1,1222 @@ ++ ++/* ++ * Copyright (C) Nginx, Inc. ++ * Copyright (C) Valentin V. Bartenev ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1) ++#define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1) ++ ++#define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint32 ++#define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint32 ++#define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint32 ++ ++#define ngx_http_spdy_nv_write_name(p, h) \ ++ ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1) ++ ++#define ngx_http_spdy_nv_write_val(p, h) \ ++ ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1) ++ ++ ++static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc, ++ ngx_chain_t *in, off_t limit); ++ ++static ngx_inline ngx_int_t ngx_http_spdy_filter_send( ++ ngx_connection_t *fc, ngx_http_spdy_stream_t *stream); ++static ngx_inline ngx_int_t ngx_http_spdy_flow_control( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream); ++static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream); ++ ++static ngx_chain_t *ngx_http_spdy_filter_get_shadow( ++ ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size); ++static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame( ++ ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first, ++ ngx_chain_t *last); ++ ++static ngx_int_t ngx_http_spdy_syn_frame_handler( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); ++static ngx_int_t ngx_http_spdy_data_frame_handler( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); ++static ngx_inline void ngx_http_spdy_handle_frame( ++ ngx_http_spdy_stream_t *stream, ngx_http_spdy_out_frame_t *frame); ++static ngx_inline void ngx_http_spdy_handle_stream( ++ ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream); ++ ++static void ngx_http_spdy_filter_cleanup(void *data); ++ ++static ngx_int_t ngx_http_spdy_filter_init(ngx_conf_t *cf); ++ ++ ++static ngx_http_module_t ngx_http_spdy_filter_module_ctx = { ++ NULL, /* preconfiguration */ ++ ngx_http_spdy_filter_init, /* postconfiguration */ ++ ++ NULL, /* create main configuration */ ++ NULL, /* init main configuration */ ++ ++ NULL, /* create server configuration */ ++ NULL, /* merge server configuration */ ++ ++ NULL, /* create location configuration */ ++ NULL /* merge location configuration */ ++}; ++ ++ ++ngx_module_t ngx_http_spdy_filter_module = { ++ NGX_MODULE_V1, ++ &ngx_http_spdy_filter_module_ctx, /* module context */ ++ NULL, /* module directives */ ++ NGX_HTTP_MODULE, /* module type */ ++ NULL, /* init master */ ++ NULL, /* init module */ ++ NULL, /* init process */ ++ NULL, /* init thread */ ++ NULL, /* exit thread */ ++ NULL, /* exit process */ ++ NULL, /* exit master */ ++ NGX_MODULE_V1_PADDING ++}; ++ ++ ++static ngx_http_output_header_filter_pt ngx_http_next_header_filter; ++ ++ ++static ngx_int_t ++ngx_http_spdy_header_filter(ngx_http_request_t *r) ++{ ++ int rc; ++ size_t len; ++ u_char *p, *buf, *last; ++ ngx_buf_t *b; ++ ngx_str_t host; ++ ngx_uint_t i, j, count, port; ++ ngx_chain_t *cl; ++ ngx_list_part_t *part, *pt; ++ ngx_table_elt_t *header, *h; ++ ngx_connection_t *c; ++ ngx_http_cleanup_t *cln; ++ ngx_http_core_loc_conf_t *clcf; ++ ngx_http_core_srv_conf_t *cscf; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_out_frame_t *frame; ++ ngx_http_spdy_connection_t *sc; ++ struct sockaddr_in *sin; ++#if (NGX_HAVE_INET6) ++ struct sockaddr_in6 *sin6; ++#endif ++ u_char addr[NGX_SOCKADDR_STRLEN]; ++ ++ if (!r->spdy_stream) { ++ return ngx_http_next_header_filter(r); ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "spdy header filter"); ++ ++ if (r->header_sent) { ++ return NGX_OK; ++ } ++ ++ r->header_sent = 1; ++ ++ if (r != r->main) { ++ return NGX_OK; ++ } ++ ++ c = r->connection; ++ ++ if (r->method == NGX_HTTP_HEAD) { ++ r->header_only = 1; ++ } ++ ++ switch (r->headers_out.status) { ++ ++ case NGX_HTTP_OK: ++ case NGX_HTTP_PARTIAL_CONTENT: ++ break; ++ ++ case NGX_HTTP_NOT_MODIFIED: ++ r->header_only = 1; ++ break; ++ ++ case NGX_HTTP_NO_CONTENT: ++ r->header_only = 1; ++ ++ ngx_str_null(&r->headers_out.content_type); ++ ++ r->headers_out.content_length = NULL; ++ r->headers_out.content_length_n = -1; ++ ++ /* fall through */ ++ ++ default: ++ r->headers_out.last_modified_time = -1; ++ r->headers_out.last_modified = NULL; ++ } ++ ++ len = NGX_SPDY_NV_NUM_SIZE ++ + ngx_http_spdy_nv_nsize(":version") ++ + ngx_http_spdy_nv_vsize("HTTP/1.1") ++ + ngx_http_spdy_nv_nsize(":status") ++ + (r->headers_out.status_line.len ++ ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len ++ : ngx_http_spdy_nv_vsize("418")); ++ ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ ++ if (r->headers_out.server == NULL) { ++ len += ngx_http_spdy_nv_nsize("server"); ++ len += clcf->server_tokens ? ngx_http_spdy_nv_vsize(NGINX_VER) ++ : ngx_http_spdy_nv_vsize("nginx"); ++ } ++ ++ if (r->headers_out.date == NULL) { ++ len += ngx_http_spdy_nv_nsize("date") ++ + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); ++ } ++ ++ if (r->headers_out.content_type.len) { ++ len += ngx_http_spdy_nv_nsize("content-type") ++ + NGX_SPDY_NV_VLEN_SIZE + r->headers_out.content_type.len; ++ ++ if (r->headers_out.content_type_len == r->headers_out.content_type.len ++ && r->headers_out.charset.len) ++ { ++ len += sizeof("; charset=") - 1 + r->headers_out.charset.len; ++ } ++ } ++ ++ if (r->headers_out.content_length == NULL ++ && r->headers_out.content_length_n >= 0) ++ { ++ len += ngx_http_spdy_nv_nsize("content-length") ++ + NGX_SPDY_NV_VLEN_SIZE + NGX_OFF_T_LEN; ++ } ++ ++ if (r->headers_out.last_modified == NULL ++ && r->headers_out.last_modified_time != -1) ++ { ++ len += ngx_http_spdy_nv_nsize("last-modified") ++ + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); ++ } ++ ++ if (r->headers_out.location ++ && r->headers_out.location->value.len ++ && r->headers_out.location->value.data[0] == '/') ++ { ++ r->headers_out.location->hash = 0; ++ ++ if (clcf->server_name_in_redirect) { ++ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ++ host = cscf->server_name; ++ ++ } else if (r->headers_in.server.len) { ++ host = r->headers_in.server; ++ ++ } else { ++ host.len = NGX_SOCKADDR_STRLEN; ++ host.data = addr; ++ ++ if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) { ++ return NGX_ERROR; ++ } ++ } ++ ++ switch (c->local_sockaddr->sa_family) { ++ ++#if (NGX_HAVE_INET6) ++ case AF_INET6: ++ sin6 = (struct sockaddr_in6 *) c->local_sockaddr; ++ port = ntohs(sin6->sin6_port); ++ break; ++#endif ++#if (NGX_HAVE_UNIX_DOMAIN) ++ case AF_UNIX: ++ port = 0; ++ break; ++#endif ++ default: /* AF_INET */ ++ sin = (struct sockaddr_in *) c->local_sockaddr; ++ port = ntohs(sin->sin_port); ++ break; ++ } ++ ++ len += ngx_http_spdy_nv_nsize("location") ++ + ngx_http_spdy_nv_vsize("https://") ++ + host.len ++ + r->headers_out.location->value.len; ++ ++ if (clcf->port_in_redirect) { ++ ++#if (NGX_HTTP_SSL) ++ if (c->ssl) ++ port = (port == 443) ? 0 : port; ++ else ++#endif ++ port = (port == 80) ? 0 : port; ++ ++ } else { ++ port = 0; ++ } ++ ++ if (port) { ++ len += sizeof(":65535") - 1; ++ } ++ ++ } else { ++ ngx_str_null(&host); ++ port = 0; ++ } ++ ++ part = &r->headers_out.headers.part; ++ header = part->elts; ++ ++ for (i = 0; /* void */; i++) { ++ ++ if (i >= part->nelts) { ++ if (part->next == NULL) { ++ break; ++ } ++ ++ part = part->next; ++ header = part->elts; ++ i = 0; ++ } ++ ++ if (header[i].hash == 0) { ++ continue; ++ } ++ ++ len += NGX_SPDY_NV_NLEN_SIZE + header[i].key.len ++ + NGX_SPDY_NV_VLEN_SIZE + header[i].value.len; ++ } ++ ++ buf = ngx_alloc(len, r->pool->log); ++ if (buf == NULL) { ++ return NGX_ERROR; ++ } ++ ++ last = buf + NGX_SPDY_NV_NUM_SIZE; ++ ++ last = ngx_http_spdy_nv_write_name(last, ":version"); ++ last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1"); ++ ++ last = ngx_http_spdy_nv_write_name(last, ":status"); ++ ++ if (r->headers_out.status_line.len) { ++ last = ngx_http_spdy_nv_write_vlen(last, ++ r->headers_out.status_line.len); ++ last = ngx_cpymem(last, r->headers_out.status_line.data, ++ r->headers_out.status_line.len); ++ } else { ++ last = ngx_http_spdy_nv_write_vlen(last, 3); ++ last = ngx_sprintf(last, "%03ui", r->headers_out.status); ++ } ++ ++ count = 2; ++ ++ if (r->headers_out.server == NULL) { ++ last = ngx_http_spdy_nv_write_name(last, "server"); ++ last = clcf->server_tokens ++ ? ngx_http_spdy_nv_write_val(last, NGINX_VER) ++ : ngx_http_spdy_nv_write_val(last, "nginx"); ++ ++ count++; ++ } ++ ++ if (r->headers_out.date == NULL) { ++ last = ngx_http_spdy_nv_write_name(last, "date"); ++ ++ last = ngx_http_spdy_nv_write_vlen(last, ngx_cached_http_time.len); ++ ++ last = ngx_cpymem(last, ngx_cached_http_time.data, ++ ngx_cached_http_time.len); ++ ++ count++; ++ } ++ ++ if (r->headers_out.content_type.len) { ++ ++ last = ngx_http_spdy_nv_write_name(last, "content-type"); ++ ++ p = last + NGX_SPDY_NV_VLEN_SIZE; ++ ++ last = ngx_cpymem(p, r->headers_out.content_type.data, ++ r->headers_out.content_type.len); ++ ++ if (r->headers_out.content_type_len == r->headers_out.content_type.len ++ && r->headers_out.charset.len) ++ { ++ last = ngx_cpymem(last, "; charset=", sizeof("; charset=") - 1); ++ ++ last = ngx_cpymem(last, r->headers_out.charset.data, ++ r->headers_out.charset.len); ++ ++ /* update r->headers_out.content_type for possible logging */ ++ ++ r->headers_out.content_type.len = last - p; ++ r->headers_out.content_type.data = p; ++ } ++ ++ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, ++ r->headers_out.content_type.len); ++ ++ count++; ++ } ++ ++ if (r->headers_out.content_length == NULL ++ && r->headers_out.content_length_n >= 0) ++ { ++ last = ngx_http_spdy_nv_write_name(last, "content-length"); ++ ++ p = last + NGX_SPDY_NV_VLEN_SIZE; ++ ++ last = ngx_sprintf(p, "%O", r->headers_out.content_length_n); ++ ++ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, ++ last - p); ++ ++ count++; ++ } ++ ++ if (r->headers_out.last_modified == NULL ++ && r->headers_out.last_modified_time != -1) ++ { ++ last = ngx_http_spdy_nv_write_name(last, "last-modified"); ++ ++ p = last + NGX_SPDY_NV_VLEN_SIZE; ++ ++ last = ngx_http_time(p, r->headers_out.last_modified_time); ++ ++ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, ++ last - p); ++ ++ count++; ++ } ++ ++ if (host.data) { ++ ++ last = ngx_http_spdy_nv_write_name(last, "location"); ++ ++ p = last + NGX_SPDY_NV_VLEN_SIZE; ++ ++ last = ngx_cpymem(p, "http", sizeof("http") - 1); ++ ++#if (NGX_HTTP_SSL) ++ if (c->ssl) { ++ *last++ ='s'; ++ } ++#endif ++ ++ *last++ = ':'; *last++ = '/'; *last++ = '/'; ++ ++ last = ngx_cpymem(last, host.data, host.len); ++ ++ if (port) { ++ last = ngx_sprintf(last, ":%ui", port); ++ } ++ ++ last = ngx_cpymem(last, r->headers_out.location->value.data, ++ r->headers_out.location->value.len); ++ ++ /* update r->headers_out.location->value for possible logging */ ++ ++ r->headers_out.location->value.len = last - p; ++ r->headers_out.location->value.data = p; ++ ngx_str_set(&r->headers_out.location->key, "location"); ++ ++ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, ++ r->headers_out.location->value.len); ++ ++ count++; ++ } ++ ++ part = &r->headers_out.headers.part; ++ header = part->elts; ++ ++ for (i = 0; /* void */; i++) { ++ ++ if (i >= part->nelts) { ++ if (part->next == NULL) { ++ break; ++ } ++ ++ part = part->next; ++ header = part->elts; ++ i = 0; ++ } ++ ++ if (header[i].hash == 0 || header[i].hash == 2) { ++ continue; ++ } ++ ++ last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len); ++ ++ ngx_strlow(last, header[i].key.data, header[i].key.len); ++ last += header[i].key.len; ++ ++ p = last + NGX_SPDY_NV_VLEN_SIZE; ++ ++ last = ngx_cpymem(p, header[i].value.data, header[i].value.len); ++ ++ pt = part; ++ h = header; ++ ++ for (j = i + 1; /* void */; j++) { ++ ++ if (j >= pt->nelts) { ++ if (pt->next == NULL) { ++ break; ++ } ++ ++ pt = pt->next; ++ h = pt->elts; ++ j = 0; ++ } ++ ++ if (h[j].hash == 0 || h[j].hash == 2 ++ || h[j].key.len != header[i].key.len ++ || ngx_strncasecmp(header[i].key.data, h[j].key.data, ++ header[i].key.len)) ++ { ++ continue; ++ } ++ ++ if (h[j].value.len) { ++ if (last != p) { ++ *last++ = '\0'; ++ } ++ ++ last = ngx_cpymem(last, h[j].value.data, h[j].value.len); ++ } ++ ++ h[j].hash = 2; ++ } ++ ++ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, ++ last - p); ++ ++ count++; ++ } ++ ++ (void) ngx_http_spdy_nv_write_num(buf, count); ++ ++ stream = r->spdy_stream; ++ sc = stream->connection; ++ ++ len = last - buf; ++ ++ b = ngx_create_temp_buf(r->pool, NGX_SPDY_FRAME_HEADER_SIZE ++ + NGX_SPDY_SYN_REPLY_SIZE ++ + deflateBound(&sc->zstream_out, len)); ++ if (b == NULL) { ++ ngx_free(buf); ++ return NGX_ERROR; ++ } ++ ++ b->last += NGX_SPDY_FRAME_HEADER_SIZE + NGX_SPDY_SYN_REPLY_SIZE; ++ ++ sc->zstream_out.next_in = buf; ++ sc->zstream_out.avail_in = len; ++ sc->zstream_out.next_out = b->last; ++ sc->zstream_out.avail_out = b->end - b->last; ++ ++ rc = deflate(&sc->zstream_out, Z_SYNC_FLUSH); ++ ++ ngx_free(buf); ++ ++ if (rc != Z_OK) { ++ ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflate() failed: %d", rc); ++ return NGX_ERROR; ++ } ++ ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "spdy deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", ++ sc->zstream_out.next_in, sc->zstream_out.next_out, ++ sc->zstream_out.avail_in, sc->zstream_out.avail_out, ++ rc); ++ ++ b->last = sc->zstream_out.next_out; ++ ++ p = b->pos; ++ p = ngx_spdy_frame_write_head(p, NGX_SPDY_SYN_REPLY); ++ ++ len = b->last - b->pos; ++ ++ r->header_size = len; ++ ++ len -= NGX_SPDY_FRAME_HEADER_SIZE; ++ ++ if (r->header_only) { ++ b->last_buf = 1; ++ p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN, len); ++ ++ } else { ++ p = ngx_spdy_frame_write_flags_and_len(p, 0, len); ++ } ++ ++ (void) ngx_spdy_frame_write_sid(p, stream->id); ++ ++ cl = ngx_alloc_chain_link(r->pool); ++ if (cl == NULL) { ++ return NGX_ERROR; ++ } ++ ++ cl->buf = b; ++ cl->next = NULL; ++ ++ frame = ngx_palloc(r->pool, sizeof(ngx_http_spdy_out_frame_t)); ++ if (frame == NULL) { ++ return NGX_ERROR; ++ } ++ ++ frame->first = cl; ++ frame->last = cl; ++ frame->handler = ngx_http_spdy_syn_frame_handler; ++ frame->stream = stream; ++ frame->length = len; ++ frame->priority = stream->priority; ++ frame->blocked = 1; ++ frame->fin = r->header_only; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, ++ "spdy:%ui create SYN_REPLY frame %p: len:%uz", ++ stream->id, frame, frame->length); ++ ++ ngx_http_spdy_queue_blocked_frame(sc, frame); ++ ++ cln = ngx_http_cleanup_add(r, 0); ++ if (cln == NULL) { ++ return NGX_ERROR; ++ } ++ ++ cln->handler = ngx_http_spdy_filter_cleanup; ++ cln->data = stream; ++ ++ stream->queued = 1; ++ ++ c->send_chain = ngx_http_spdy_send_chain; ++ c->need_last_buf = 1; ++ ++ return ngx_http_spdy_filter_send(c, stream); ++} ++ ++ ++static ngx_chain_t * ++ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) ++{ ++ off_t size, offset; ++ size_t rest, frame_size; ++ ngx_chain_t *cl, *out, **ln; ++ ngx_http_request_t *r; ++ ngx_http_spdy_stream_t *stream; ++ ngx_http_spdy_loc_conf_t *slcf; ++ ngx_http_spdy_out_frame_t *frame; ++ ngx_http_spdy_connection_t *sc; ++ ++ r = fc->data; ++ stream = r->spdy_stream; ++ ++#if (NGX_SUPPRESS_WARN) ++ size = 0; ++#endif ++ ++ while (in) { ++ size = ngx_buf_size(in->buf); ++ ++ if (size || in->buf->last_buf) { ++ break; ++ } ++ ++ in = in->next; ++ } ++ ++ if (in == NULL) { ++ ++ if (stream->queued) { ++ fc->write->delayed = 1; ++ } else { ++ fc->buffered &= ~NGX_SPDY_BUFFERED; ++ } ++ ++ return NULL; ++ } ++ ++ sc = stream->connection; ++ ++ if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) { ++ fc->write->delayed = 1; ++ return in; ++ } ++ ++ if (limit == 0 || limit > (off_t) sc->send_window) { ++ limit = sc->send_window; ++ } ++ ++ if (limit > stream->send_window) { ++ limit = (stream->send_window > 0) ? stream->send_window : 0; ++ } ++ ++ if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { ++ cl = ngx_alloc_chain_link(r->pool); ++ if (cl == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ cl->buf = in->buf; ++ in->buf = cl->buf->shadow; ++ ++ offset = ngx_buf_in_memory(in->buf) ++ ? (cl->buf->pos - in->buf->pos) ++ : (cl->buf->file_pos - in->buf->file_pos); ++ ++ cl->next = stream->free_bufs; ++ stream->free_bufs = cl; ++ ++ } else { ++ offset = 0; ++ } ++ ++#if (NGX_SUPPRESS_WARN) ++ cl = NULL; ++#endif ++ ++ slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module); ++ ++ frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit ++ : slcf->chunk_size; ++ ++ for ( ;; ) { ++ ln = &out; ++ rest = frame_size; ++ ++ while ((off_t) rest >= size) { ++ ++ if (offset) { ++ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, ++ offset, size); ++ if (cl == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ offset = 0; ++ ++ } else { ++ cl = ngx_alloc_chain_link(r->pool); ++ if (cl == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ cl->buf = in->buf; ++ } ++ ++ *ln = cl; ++ ln = &cl->next; ++ ++ rest -= (size_t) size; ++ in = in->next; ++ ++ if (in == NULL) { ++ frame_size -= rest; ++ rest = 0; ++ break; ++ } ++ ++ size = ngx_buf_size(in->buf); ++ } ++ ++ if (rest) { ++ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, ++ offset, rest); ++ if (cl == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ cl->buf->flush = 0; ++ cl->buf->last_buf = 0; ++ ++ *ln = cl; ++ ++ offset += rest; ++ size -= rest; ++ } ++ ++ frame = ngx_http_spdy_filter_get_data_frame(stream, frame_size, ++ out, cl); ++ if (frame == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ ngx_http_spdy_queue_frame(sc, frame); ++ ++ sc->send_window -= frame_size; ++ ++ stream->send_window -= frame_size; ++ stream->queued++; ++ ++ if (in == NULL) { ++ break; ++ } ++ ++ limit -= frame_size; ++ ++ if (limit == 0) { ++ break; ++ } ++ ++ if (limit < (off_t) slcf->chunk_size) { ++ frame_size = (size_t) limit; ++ } ++ } ++ ++ if (offset) { ++ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size); ++ if (cl == NULL) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ in->buf = cl->buf; ++ ngx_free_chain(r->pool, cl); ++ } ++ ++ if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) { ++ return NGX_CHAIN_ERROR; ++ } ++ ++ if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) { ++ fc->write->delayed = 1; ++ } ++ ++ return in; ++} ++ ++ ++static ngx_chain_t * ++ngx_http_spdy_filter_get_shadow(ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, ++ off_t offset, off_t size) ++{ ++ ngx_buf_t *chunk; ++ ngx_chain_t *cl; ++ ++ cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs); ++ if (cl == NULL) { ++ return NULL; ++ } ++ ++ chunk = cl->buf; ++ ++ ngx_memcpy(chunk, buf, sizeof(ngx_buf_t)); ++ ++ chunk->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow; ++ chunk->shadow = buf; ++ ++ if (ngx_buf_in_memory(chunk)) { ++ chunk->pos += offset; ++ chunk->last = chunk->pos + size; ++ } ++ ++ if (chunk->in_file) { ++ chunk->file_pos += offset; ++ chunk->file_last = chunk->file_pos + size; ++ } ++ ++ return cl; ++} ++ ++ ++static ngx_http_spdy_out_frame_t * ++ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream, ++ size_t len, ngx_chain_t *first, ngx_chain_t *last) ++{ ++ u_char *p; ++ ngx_buf_t *buf; ++ ngx_uint_t flags; ++ ngx_chain_t *cl; ++ ngx_http_spdy_out_frame_t *frame; ++ ++ ++ frame = stream->free_frames; ++ ++ if (frame) { ++ stream->free_frames = frame->next; ++ ++ } else { ++ frame = ngx_palloc(stream->request->pool, ++ sizeof(ngx_http_spdy_out_frame_t)); ++ if (frame == NULL) { ++ return NULL; ++ } ++ } ++ ++ flags = last->buf->last_buf ? NGX_SPDY_FLAG_FIN : 0; ++ ++ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, ++ "spdy:%ui create DATA frame %p: len:%uz flags:%ui", ++ stream->id, frame, len, flags); ++ ++ cl = ngx_chain_get_free_buf(stream->request->pool, ++ &stream->free_data_headers); ++ if (cl == NULL) { ++ return NULL; ++ } ++ ++ buf = cl->buf; ++ ++ if (buf->start) { ++ p = buf->start; ++ buf->pos = p; ++ ++ p += NGX_SPDY_SID_SIZE; ++ ++ (void) ngx_spdy_frame_write_flags_and_len(p, flags, len); ++ ++ } else { ++ p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE); ++ if (p == NULL) { ++ return NULL; ++ } ++ ++ buf->pos = p; ++ buf->start = p; ++ ++ p = ngx_spdy_frame_write_sid(p, stream->id); ++ p = ngx_spdy_frame_write_flags_and_len(p, flags, len); ++ ++ buf->last = p; ++ buf->end = p; ++ ++ buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame; ++ buf->memory = 1; ++ } ++ ++ cl->next = first; ++ first = cl; ++ ++ last->buf->flush = 1; ++ ++ frame->first = first; ++ frame->last = last; ++ frame->handler = ngx_http_spdy_data_frame_handler; ++ frame->stream = stream; ++ frame->length = len; ++ frame->priority = stream->priority; ++ frame->blocked = 0; ++ frame->fin = last->buf->last_buf; ++ ++ return frame; ++} ++ ++ ++static ngx_inline ngx_int_t ++ngx_http_spdy_filter_send(ngx_connection_t *fc, ngx_http_spdy_stream_t *stream) ++{ ++ stream->blocked = 1; ++ ++ if (ngx_http_spdy_send_output_queue(stream->connection) == NGX_ERROR) { ++ fc->error = 1; ++ return NGX_ERROR; ++ } ++ ++ stream->blocked = 0; ++ ++ if (stream->queued) { ++ fc->buffered |= NGX_SPDY_BUFFERED; ++ fc->write->delayed = 1; ++ return NGX_AGAIN; ++ } ++ ++ fc->buffered &= ~NGX_SPDY_BUFFERED; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_inline ngx_int_t ++ngx_http_spdy_flow_control(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream) ++{ ++ if (stream->send_window <= 0) { ++ stream->exhausted = 1; ++ return NGX_DECLINED; ++ } ++ ++ if (sc->send_window == 0) { ++ ngx_http_spdy_waiting_queue(sc, stream); ++ return NGX_DECLINED; ++ } ++ ++ return NGX_OK; ++} ++ ++ ++static void ++ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream) ++{ ++ ngx_queue_t *q; ++ ngx_http_spdy_stream_t *s; ++ ++ if (stream->handled) { ++ return; ++ } ++ ++ stream->handled = 1; ++ ++ for (q = ngx_queue_last(&sc->waiting); ++ q != ngx_queue_sentinel(&sc->waiting); ++ q = ngx_queue_prev(q)) ++ { ++ s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); ++ ++ /* ++ * NB: higher values represent lower priorities. ++ */ ++ if (stream->priority >= s->priority) { ++ break; ++ } ++ } ++ ++ ngx_queue_insert_after(q, &stream->queue); ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_buf_t *buf; ++ ngx_http_spdy_stream_t *stream; ++ ++ buf = frame->first->buf; ++ ++ if (buf->pos != buf->last) { ++ return NGX_AGAIN; ++ } ++ ++ stream = frame->stream; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy:%ui SYN_REPLY frame %p was sent", stream->id, frame); ++ ++ ngx_free_chain(stream->request->pool, frame->first); ++ ++ ngx_http_spdy_handle_frame(stream, frame); ++ ++ ngx_http_spdy_handle_stream(sc, stream); ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_buf_t *buf; ++ ngx_chain_t *cl, *ln; ++ ngx_http_spdy_stream_t *stream; ++ ++ stream = frame->stream; ++ ++ cl = frame->first; ++ ++ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame) { ++ ++ if (cl->buf->pos != cl->buf->last) { ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy:%ui DATA frame %p was sent partially", ++ stream->id, frame); ++ ++ return NGX_AGAIN; ++ } ++ ++ ln = cl->next; ++ ++ cl->next = stream->free_data_headers; ++ stream->free_data_headers = cl; ++ ++ if (cl == frame->last) { ++ goto done; ++ } ++ ++ cl = ln; ++ } ++ ++ for ( ;; ) { ++ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { ++ buf = cl->buf->shadow; ++ ++ if (ngx_buf_in_memory(buf)) { ++ buf->pos = cl->buf->pos; ++ } ++ ++ if (buf->in_file) { ++ buf->file_pos = cl->buf->file_pos; ++ } ++ } ++ ++ if (ngx_buf_size(cl->buf) != 0) { ++ ++ if (cl != frame->first) { ++ frame->first = cl; ++ ngx_http_spdy_handle_stream(sc, stream); ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy:%ui DATA frame %p was sent partially", ++ stream->id, frame); ++ ++ return NGX_AGAIN; ++ } ++ ++ ln = cl->next; ++ ++ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { ++ cl->next = stream->free_bufs; ++ stream->free_bufs = cl; ++ ++ } else { ++ ngx_free_chain(stream->request->pool, cl); ++ } ++ ++ if (cl == frame->last) { ++ goto done; ++ } ++ ++ cl = ln; ++ } ++ ++done: ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, ++ "spdy:%ui DATA frame %p was sent", stream->id, frame); ++ ++ stream->request->header_size += NGX_SPDY_FRAME_HEADER_SIZE; ++ ++ ngx_http_spdy_handle_frame(stream, frame); ++ ++ ngx_http_spdy_handle_stream(sc, stream); ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_inline void ++ngx_http_spdy_handle_frame(ngx_http_spdy_stream_t *stream, ++ ngx_http_spdy_out_frame_t *frame) ++{ ++ ngx_http_request_t *r; ++ ++ r = stream->request; ++ ++ r->connection->sent += NGX_SPDY_FRAME_HEADER_SIZE + frame->length; ++ ++ if (frame->fin) { ++ stream->out_closed = 1; ++ } ++ ++ frame->next = stream->free_frames; ++ stream->free_frames = frame; ++ ++ stream->queued--; ++} ++ ++ ++static ngx_inline void ++ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc, ++ ngx_http_spdy_stream_t *stream) ++{ ++ ngx_event_t *wev; ++ ++ if (stream->handled || stream->blocked || stream->exhausted) { ++ return; ++ } ++ ++ wev = stream->request->connection->write; ++ ++ /* ++ * This timer can only be set if the stream was delayed because of rate ++ * limit. In that case the event should be triggered by the timer. ++ */ ++ ++ if (!wev->timer_set) { ++ wev->delayed = 0; ++ ++ stream->handled = 1; ++ ngx_queue_insert_tail(&sc->posted, &stream->queue); ++ } ++} ++ ++ ++static void ++ngx_http_spdy_filter_cleanup(void *data) ++{ ++ ngx_http_spdy_stream_t *stream = data; ++ ++ size_t delta; ++ ngx_http_spdy_out_frame_t *frame, **fn; ++ ngx_http_spdy_connection_t *sc; ++ ++ if (stream->handled) { ++ stream->handled = 0; ++ ngx_queue_remove(&stream->queue); ++ } ++ ++ if (stream->queued == 0) { ++ return; ++ } ++ ++ delta = 0; ++ sc = stream->connection; ++ fn = &sc->last_out; ++ ++ for ( ;; ) { ++ frame = *fn; ++ ++ if (frame == NULL) { ++ break; ++ } ++ ++ if (frame->stream == stream && !frame->blocked) { ++ *fn = frame->next; ++ ++ delta += frame->length; ++ ++ if (--stream->queued == 0) { ++ break; ++ } ++ ++ continue; ++ } ++ ++ fn = &frame->next; ++ } ++ ++ if (sc->send_window == 0 && delta && !ngx_queue_empty(&sc->waiting)) { ++ ngx_queue_add(&sc->posted, &sc->waiting); ++ ngx_queue_init(&sc->waiting); ++ } ++ ++ sc->send_window += delta; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_filter_init(ngx_conf_t *cf) ++{ ++ ngx_http_next_header_filter = ngx_http_top_header_filter; ++ ngx_http_top_header_filter = ngx_http_spdy_header_filter; ++ ++ return NGX_OK; ++} +diff --git a/nginx-1.15.8/src/http/ngx_http_spdy_module.c b/nginx-1.15.8/src/http/ngx_http_spdy_module.c +new file mode 100644 +index 0000000..5178a36 +--- /dev/null ++++ b/nginx-1.15.8/src/http/ngx_http_spdy_module.c +@@ -0,0 +1,408 @@ ++ ++/* ++ * Copyright (C) Nginx, Inc. ++ * Copyright (C) Valentin V. Bartenev ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++ ++static ngx_int_t ngx_http_spdy_add_variables(ngx_conf_t *cf); ++ ++static ngx_int_t ngx_http_spdy_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data); ++static ngx_int_t ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data); ++ ++static ngx_int_t ngx_http_spdy_module_init(ngx_cycle_t *cycle); ++ ++static void *ngx_http_spdy_create_main_conf(ngx_conf_t *cf); ++static char *ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf); ++static void *ngx_http_spdy_create_srv_conf(ngx_conf_t *cf); ++static char *ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, ++ void *child); ++static void *ngx_http_spdy_create_loc_conf(ngx_conf_t *cf); ++static char *ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent, ++ void *child); ++ ++static char *ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, ++ void *data); ++static char *ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data); ++static char *ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, ++ void *data); ++static char *ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data); ++ ++ ++static ngx_conf_num_bounds_t ngx_http_spdy_headers_comp_bounds = { ++ ngx_conf_check_num_bounds, 0, 9 ++}; ++ ++static ngx_conf_post_t ngx_http_spdy_recv_buffer_size_post = ++ { ngx_http_spdy_recv_buffer_size }; ++static ngx_conf_post_t ngx_http_spdy_pool_size_post = ++ { ngx_http_spdy_pool_size }; ++static ngx_conf_post_t ngx_http_spdy_streams_index_mask_post = ++ { ngx_http_spdy_streams_index_mask }; ++static ngx_conf_post_t ngx_http_spdy_chunk_size_post = ++ { ngx_http_spdy_chunk_size }; ++ ++ ++static ngx_command_t ngx_http_spdy_commands[] = { ++ ++ { ngx_string("spdy_recv_buffer_size"), ++ NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_size_slot, ++ NGX_HTTP_MAIN_CONF_OFFSET, ++ offsetof(ngx_http_spdy_main_conf_t, recv_buffer_size), ++ &ngx_http_spdy_recv_buffer_size_post }, ++ ++ { ngx_string("spdy_pool_size"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_size_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, pool_size), ++ &ngx_http_spdy_pool_size_post }, ++ ++ { ngx_string("spdy_max_concurrent_streams"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_num_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, concurrent_streams), ++ NULL }, ++ ++ { ngx_string("spdy_streams_index_size"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_num_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, streams_index_mask), ++ &ngx_http_spdy_streams_index_mask_post }, ++ ++ { ngx_string("spdy_recv_timeout"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_msec_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, recv_timeout), ++ NULL }, ++ ++ { ngx_string("spdy_keepalive_timeout"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_msec_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, keepalive_timeout), ++ NULL }, ++ ++ { ngx_string("spdy_headers_comp"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_num_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_spdy_srv_conf_t, headers_comp), ++ &ngx_http_spdy_headers_comp_bounds }, ++ ++ { ngx_string("spdy_chunk_size"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ++ ngx_conf_set_size_slot, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ offsetof(ngx_http_spdy_loc_conf_t, chunk_size), ++ &ngx_http_spdy_chunk_size_post }, ++ ++ ngx_null_command ++}; ++ ++ ++static ngx_http_module_t ngx_http_spdy_module_ctx = { ++ ngx_http_spdy_add_variables, /* preconfiguration */ ++ NULL, /* postconfiguration */ ++ ++ ngx_http_spdy_create_main_conf, /* create main configuration */ ++ ngx_http_spdy_init_main_conf, /* init main configuration */ ++ ++ ngx_http_spdy_create_srv_conf, /* create server configuration */ ++ ngx_http_spdy_merge_srv_conf, /* merge server configuration */ ++ ++ ngx_http_spdy_create_loc_conf, /* create location configuration */ ++ ngx_http_spdy_merge_loc_conf /* merge location configuration */ ++}; ++ ++ ++ngx_module_t ngx_http_spdy_module = { ++ NGX_MODULE_V1, ++ &ngx_http_spdy_module_ctx, /* module context */ ++ ngx_http_spdy_commands, /* module directives */ ++ NGX_HTTP_MODULE, /* module type */ ++ NULL, /* init master */ ++ ngx_http_spdy_module_init, /* init module */ ++ NULL, /* init process */ ++ NULL, /* init thread */ ++ NULL, /* exit thread */ ++ NULL, /* exit process */ ++ NULL, /* exit master */ ++ NGX_MODULE_V1_PADDING ++}; ++ ++ ++static ngx_http_variable_t ngx_http_spdy_vars[] = { ++ ++ { ngx_string("spdy"), NULL, ++ ngx_http_spdy_variable, 0, 0, 0 }, ++ ++ { ngx_string("spdy_request_priority"), NULL, ++ ngx_http_spdy_request_priority_variable, 0, 0, 0 }, ++ ++ { ngx_null_string, NULL, NULL, 0, 0, 0 } ++}; ++ ++ ++static ngx_int_t ++ngx_http_spdy_add_variables(ngx_conf_t *cf) ++{ ++ ngx_http_variable_t *var, *v; ++ ++ for (v = ngx_http_spdy_vars; v->name.len; v++) { ++ var = ngx_http_add_variable(cf, &v->name, v->flags); ++ if (var == NULL) { ++ return NGX_ERROR; ++ } ++ ++ var->get_handler = v->get_handler; ++ var->data = v->data; ++ } ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data) ++{ ++ if (r->spdy_stream) { ++ v->len = sizeof("3.1") - 1; ++ v->valid = 1; ++ v->no_cacheable = 0; ++ v->not_found = 0; ++ v->data = (u_char *) "3.1"; ++ ++ return NGX_OK; ++ } ++ ++ *v = ngx_http_variable_null_value; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data) ++{ ++ if (r->spdy_stream) { ++ v->len = 1; ++ v->valid = 1; ++ v->no_cacheable = 0; ++ v->not_found = 0; ++ ++ v->data = ngx_pnalloc(r->pool, 1); ++ if (v->data == NULL) { ++ return NGX_ERROR; ++ } ++ ++ v->data[0] = '0' + (u_char) r->spdy_stream->priority; ++ ++ return NGX_OK; ++ } ++ ++ *v = ngx_http_variable_null_value; ++ ++ return NGX_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_spdy_module_init(ngx_cycle_t *cycle) ++{ ++ ngx_http_spdy_request_headers_init(); ++ ++ return NGX_OK; ++} ++ ++ ++static void * ++ngx_http_spdy_create_main_conf(ngx_conf_t *cf) ++{ ++ ngx_http_spdy_main_conf_t *smcf; ++ ++ smcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_main_conf_t)); ++ if (smcf == NULL) { ++ return NULL; ++ } ++ ++ smcf->recv_buffer_size = NGX_CONF_UNSET_SIZE; ++ ++ return smcf; ++} ++ ++ ++static char * ++ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf) ++{ ++ ngx_http_spdy_main_conf_t *smcf = conf; ++ ++ ngx_conf_init_size_value(smcf->recv_buffer_size, 256 * 1024); ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static void * ++ngx_http_spdy_create_srv_conf(ngx_conf_t *cf) ++{ ++ ngx_http_spdy_srv_conf_t *sscf; ++ ++ sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_srv_conf_t)); ++ if (sscf == NULL) { ++ return NULL; ++ } ++ ++ sscf->pool_size = NGX_CONF_UNSET_SIZE; ++ ++ sscf->concurrent_streams = NGX_CONF_UNSET_UINT; ++ sscf->streams_index_mask = NGX_CONF_UNSET_UINT; ++ ++ sscf->recv_timeout = NGX_CONF_UNSET_MSEC; ++ sscf->keepalive_timeout = NGX_CONF_UNSET_MSEC; ++ ++ sscf->headers_comp = NGX_CONF_UNSET; ++ ++ return sscf; ++} ++ ++ ++static char * ++ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ++{ ++ ngx_http_spdy_srv_conf_t *prev = parent; ++ ngx_http_spdy_srv_conf_t *conf = child; ++ ++ ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); ++ ++ ngx_conf_merge_uint_value(conf->concurrent_streams, ++ prev->concurrent_streams, 100); ++ ++ ngx_conf_merge_uint_value(conf->streams_index_mask, ++ prev->streams_index_mask, 32 - 1); ++ ++ ngx_conf_merge_msec_value(conf->recv_timeout, ++ prev->recv_timeout, 30000); ++ ngx_conf_merge_msec_value(conf->keepalive_timeout, ++ prev->keepalive_timeout, 180000); ++ ++ ngx_conf_merge_value(conf->headers_comp, prev->headers_comp, 0); ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static void * ++ngx_http_spdy_create_loc_conf(ngx_conf_t *cf) ++{ ++ ngx_http_spdy_loc_conf_t *slcf; ++ ++ slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_loc_conf_t)); ++ if (slcf == NULL) { ++ return NULL; ++ } ++ ++ slcf->chunk_size = NGX_CONF_UNSET_SIZE; ++ ++ return slcf; ++} ++ ++ ++static char * ++ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ++{ ++ ngx_http_spdy_loc_conf_t *prev = parent; ++ ngx_http_spdy_loc_conf_t *conf = child; ++ ++ ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static char * ++ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, void *data) ++{ ++ size_t *sp = data; ++ ++ if (*sp <= 2 * NGX_SPDY_STATE_BUFFER_SIZE) { ++ return "value is too small"; ++ } ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static char * ++ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data) ++{ ++ size_t *sp = data; ++ ++ if (*sp < NGX_MIN_POOL_SIZE) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ++ "the pool size must be no less than %uz", ++ NGX_MIN_POOL_SIZE); ++ return NGX_CONF_ERROR; ++ } ++ ++ if (*sp % NGX_POOL_ALIGNMENT) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ++ "the pool size must be a multiple of %uz", ++ NGX_POOL_ALIGNMENT); ++ return NGX_CONF_ERROR; ++ } ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static char * ++ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, void *data) ++{ ++ ngx_uint_t *np = data; ++ ++ ngx_uint_t mask; ++ ++ mask = *np - 1; ++ ++ if (*np == 0 || (*np & mask)) { ++ return "must be a power of two"; ++ } ++ ++ *np = mask; ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static char * ++ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data) ++{ ++ size_t *sp = data; ++ ++ if (*sp == 0) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ++ "the spdy chunk size cannot be zero"); ++ return NGX_CONF_ERROR; ++ } ++ ++ if (*sp > NGX_SPDY_MAX_FRAME_SIZE) { ++ *sp = NGX_SPDY_MAX_FRAME_SIZE; ++ } ++ ++ return NGX_CONF_OK; ++} +diff --git a/nginx-1.15.8/src/http/ngx_http_spdy_module.h b/nginx-1.15.8/src/http/ngx_http_spdy_module.h +new file mode 100644 +index 0000000..5242322 +--- /dev/null ++++ b/nginx-1.15.8/src/http/ngx_http_spdy_module.h +@@ -0,0 +1,41 @@ ++ ++/* ++ * Copyright (C) Nginx, Inc. ++ * Copyright (C) Valentin V. Bartenev ++ */ ++ ++ ++#ifndef _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ ++#define _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ ++ ++ ++#include ++#include ++#include ++ ++ ++typedef struct { ++ size_t recv_buffer_size; ++ u_char *recv_buffer; ++} ngx_http_spdy_main_conf_t; ++ ++ ++typedef struct { ++ size_t pool_size; ++ ngx_uint_t concurrent_streams; ++ ngx_uint_t streams_index_mask; ++ ngx_msec_t recv_timeout; ++ ngx_msec_t keepalive_timeout; ++ ngx_int_t headers_comp; ++} ngx_http_spdy_srv_conf_t; ++ ++ ++typedef struct { ++ size_t chunk_size; ++} ngx_http_spdy_loc_conf_t; ++ ++ ++extern ngx_module_t ngx_http_spdy_module; ++ ++ ++#endif /* _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ */ +diff --git a/nginx-1.15.8/src/http/ngx_http_upstream.c b/nginx-1.15.8/src/http/ngx_http_upstream.c +index efc6ba9..b104573 100644 +--- a/nginx-1.15.8/src/http/ngx_http_upstream.c ++++ b/nginx-1.15.8/src/http/ngx_http_upstream.c +@@ -532,6 +532,12 @@ ngx_http_upstream_init(ngx_http_request_t *r) + return; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ ngx_http_upstream_init_request(r); ++ return; ++ } ++#endif + + if (c->read->timer_set) { + ngx_del_timer(c->read); +@@ -1357,6 +1363,11 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, + return; + } + #endif ++#if (NGX_HTTP_SPDY) ++ if (r->spdy_stream) { ++ return; ++ } ++#endif + + #if (NGX_HAVE_KQUEUE) + +diff --git a/nginx-1.15.8/src/http/v2/ngx_http_v2_module.c b/nginx-1.15.8/src/http/v2/ngx_http_v2_module.c +index c54dc10..3be6bfa 100644 +--- a/nginx-1.15.8/src/http/v2/ngx_http_v2_module.c ++++ b/nginx-1.15.8/src/http/v2/ngx_http_v2_module.c +@@ -36,8 +36,6 @@ static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data); + static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, + void *data); + static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); +-static char *ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, +- void *conf); + + + static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = +@@ -152,62 +150,6 @@ static ngx_command_t ngx_http_v2_commands[] = { + 0, + NULL }, + +- { ngx_string("spdy_recv_buffer_size"), +- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_MAIN_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_pool_size"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_max_concurrent_streams"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_streams_index_size"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_recv_timeout"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_keepalive_timeout"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_headers_comp"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_SRV_CONF_OFFSET, +- 0, +- NULL }, +- +- { ngx_string("spdy_chunk_size"), +- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, +- ngx_http_v2_spdy_deprecated, +- NGX_HTTP_LOC_CONF_OFFSET, +- 0, +- NULL }, +- + ngx_null_command + }; + +@@ -597,14 +539,3 @@ ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data) + + return NGX_CONF_OK; + } +- +- +-static char * +-ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +-{ +- ngx_conf_log_error(NGX_LOG_WARN, cf, 0, +- "invalid directive \"%V\": ngx_http_spdy_module " +- "was superseded by ngx_http_v2_module", &cmd->name); +- +- return NGX_CONF_OK; +-} From eb213af7696e36a14501012087e28ff68597d26c Mon Sep 17 00:00:00 2001 From: DeveloperJim <190177081@qq.com> Date: Tue, 4 Aug 2020 21:38:28 +0800 Subject: [PATCH 2/3] chore: fix dependency for 1.18.x, issue #0 --- Makefile | 2 +- .../common/RegisterDiscover/zkregdiscv.go | 2 +- bcs-common/common/types/rc.go | 4 +- bcs-common/pkg/mesosdriver/client.go | 2 +- bcs-k8s/bcs-egress/go.sum | 28 +----- .../mesosdriver/backend/v4http/create.go | 4 +- .../src/manager/sched/offer/offerpool.go | 10 +- .../src/manager/sched/scheduler/daemonset.go | 6 +- .../src/manager/sched/scheduler/data_check.go | 2 +- .../src/manager/sched/scheduler/scheduler.go | 2 +- .../src/manager/sched/task/task.go | 6 +- .../src/manager/store/etcd/store.go | 30 +++--- .../src/manager/store/etcd/task.go | 6 +- .../src/manager/store/etcd/taskgroup.go | 6 +- .../src/manager/store/zk/store.go | 20 ++-- .../apis/monitor/v1/servicemonitor_types.go | 8 +- bcs-services/bcs-network-detection/app/app.go | 2 +- .../network-detection/network-detection.go | 2 +- .../app/options/options.go | 24 ++--- .../bcs-service-prometheus/config/config.go | 24 ++--- .../discovery/node-etcd-discovery.go | 6 +- .../discovery/service-monitor.go | 91 +++++++++---------- go.mod | 6 +- go.sum | 18 ++++ 24 files changed, 150 insertions(+), 161 deletions(-) diff --git a/Makefile b/Makefile index bcb0067e40..71507857ac 100644 --- a/Makefile +++ b/Makefile @@ -305,7 +305,7 @@ cc-agent:pre cp -R ./install/conf/bcs-k8s-master/bcs-cc-agent ${PACKAGEPATH}/bcs-k8s-master go build ${LDFLAG} -o ${PACKAGEPATH}/bcs-k8s-master/bcs-cc-agent/bcs-cc-agent ./bcs-k8s/bcs-cc-agent/main.go -bkcmdb-synchronizer: +bkcmdb-synchronizer:pre mkdir -p ${PACKAGEPATH}/bcs-services/bcs-bkcmdb-synchronizer go build ${LDFLAG} -o ${PACKAGEPATH}/bcs-services/bcs-bkcmdb-synchronizer/bcs-bkcmdb-synchronizer ./bcs-services/bcs-bkcmdb-synchronizer/main.go diff --git a/bcs-common/common/RegisterDiscover/zkregdiscv.go b/bcs-common/common/RegisterDiscover/zkregdiscv.go index f2af3d8cc9..bbbb8d1f55 100644 --- a/bcs-common/common/RegisterDiscover/zkregdiscv.go +++ b/bcs-common/common/RegisterDiscover/zkregdiscv.go @@ -249,4 +249,4 @@ func (zkRD *ZkRegDiscv) discoverNodes(path string, servNodes []string) (*Discove } return discvEnv, nil -} \ No newline at end of file +} diff --git a/bcs-common/common/types/rc.go b/bcs-common/common/types/rc.go index 0252ed0281..b65d4e860e 100644 --- a/bcs-common/common/types/rc.go +++ b/bcs-common/common/types/rc.go @@ -15,8 +15,8 @@ package types //EnvVar represents an environment variable present in a Container type EnvVar struct { - Name string `json:"name"` - Value string `json:"value,omitempty"` + Name string `json:"name"` + Value string `json:"value,omitempty"` ValueFrom *EnvVarSource `json:"valueFrom,omitempty"` } diff --git a/bcs-common/pkg/mesosdriver/client.go b/bcs-common/pkg/mesosdriver/client.go index e8da601ace..e24cfa4d7e 100644 --- a/bcs-common/pkg/mesosdriver/client.go +++ b/bcs-common/pkg/mesosdriver/client.go @@ -85,7 +85,7 @@ func (m *MesosDriverClient) getModuleAddr(clusterid string) (string, error) { } //update agent external resources -func (m *MesosDriverClient) UpdateAgentExtendedResources(clusterId string,er *commtypes.ExtendedResource) error { +func (m *MesosDriverClient) UpdateAgentExtendedResources(clusterId string, er *commtypes.ExtendedResource) error { by, _ := json.Marshal(er) _, err := m.requestMesosApiserver(clusterId, http.MethodPut, "agentsettings/extendedresource", by) if err != nil { diff --git a/bcs-k8s/bcs-egress/go.sum b/bcs-k8s/bcs-egress/go.sum index 79bbb5432d..7d6f63fde4 100644 --- a/bcs-k8s/bcs-egress/go.sum +++ b/bcs-k8s/bcs-egress/go.sum @@ -40,7 +40,6 @@ github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503/go github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -246,7 +245,6 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-logr/zapr v0.1.1 h1:qXBXPDdNncunGs7XeEpsJt8wCjYBygluzfdLO0G5baE= github.com/go-logr/zapr v0.1.1/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -389,7 +387,6 @@ github.com/gophercloud/gophercloud v0.2.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEo github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU= github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -485,7 +482,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jsonnet-bundler/jsonnet-bundler v0.2.0/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -497,11 +493,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= @@ -585,7 +579,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v0.0.0-20170117200651-66bb6560562f/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -599,7 +592,6 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -607,7 +599,6 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -632,7 +623,7 @@ github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-5 github.com/operator-framework/operator-registry v1.5.3/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= github.com/operator-framework/operator-registry v1.6.1/go.mod h1:sx4wWMiZtYhlUiaKscg3QQUPPM/c1bkrAs4n4KipDb4= github.com/operator-framework/operator-registry v1.6.2-0.20200330184612-11867930adb5/go.mod h1:SHff373z8asEkPo6aWpN0qId4Y/feQTjZxRF8PRhti8= -github.com/operator-framework/operator-sdk v0.17.1 h1:ESV2s2oQsZPQiQ8VfC8S5DzEnO/azXF82Fj++5qpAkw= +github.com/operator-framework/operator-sdk v0.17.1 h1:Y/QS7FrEQ0KrURc0NYsbD9n6JhR2B4REs2Ki39RBDno= github.com/operator-framework/operator-sdk v0.17.1/go.mod h1:wmYi08aoUmtgfoUamURmssI4dkdFGNtSI1Egj+ZfBnk= github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= @@ -655,7 +646,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -736,10 +726,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -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/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -771,7 +759,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -827,18 +814,14 @@ go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygL 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/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -878,14 +861,12 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1041,11 +1022,9 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200115044656-831fdb1e1868/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200327195553-82bb89366a1e h1:qCZ8SbsZMjT0OuDPCEBxgLZic4NMj8Gj4vNXiTVRAaA= golang.org/x/tools v0.0.0-20200327195553-82bb89366a1e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= @@ -1068,7 +1047,6 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1110,7 +1088,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1130,7 +1107,6 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24 gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.1.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1151,7 +1127,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= @@ -1172,7 +1147,6 @@ k8s.io/apiextensions-apiserver v0.17.0/go.mod h1:XiIFUakZywkUl54fVXa7QTEHcqQz9HG k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= k8s.io/apiextensions-apiserver v0.17.3/go.mod h1:CJbCyMfkKftAd/X/V6OTHYhVn7zXnDdnkUjS1h0GTeY= k8s.io/apiextensions-apiserver v0.17.4/go.mod h1:rCbbbaFS/s3Qau3/1HbPlHblrWpFivoaLYccCffvQGI= -k8s.io/apiextensions-apiserver v0.17.7 h1:CiSmZ39RFmwPTS4XEIxqGrIm9qcAv4wpiT2WRU4LG0M= k8s.io/apiextensions-apiserver v0.17.7/go.mod h1:EKjjclxeShy9HP7VxJrvC47dlLPOc7anjH4KOZZbld0= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8= diff --git a/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/create.go b/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/create.go index f85cb105c3..4fef5ff7f1 100644 --- a/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/create.go +++ b/bcs-mesos/bcs-mesos-driver/mesosdriver/backend/v4http/create.go @@ -279,7 +279,7 @@ func (s *Scheduler) setVersionWithPodSpec(version *types.Version, spec *bcstype. //env container.Docker.Env = make(map[string]string) for _, env := range c.Env { - if env.ValueFrom!=nil && env.ValueFrom.ResourceFieldRef!=nil && env.ValueFrom.ResourceFieldRef.Resource!="" { + if env.ValueFrom != nil && env.ValueFrom.ResourceFieldRef != nil && env.ValueFrom.ResourceFieldRef.Resource != "" { switch env.ValueFrom.ResourceFieldRef.Resource { case "requests.cpu": container.Docker.Env[env.Name] = fmt.Sprintf("%f", container.Resources.Cpus*1000) @@ -293,7 +293,7 @@ func (s *Scheduler) setVersionWithPodSpec(version *types.Version, spec *bcstype. blog.Errorf("Deployment(%s:%s) Env(%s) ValueFrom(%s) is invalid", version.ObjectMeta.NameSpace, version.ObjectMeta.Name, env.Name, env.ValueFrom.ResourceFieldRef.Resource) } - }else { + } else { container.Docker.Env[env.Name] = env.Value } } diff --git a/bcs-mesos/bcs-scheduler/src/manager/sched/offer/offerpool.go b/bcs-mesos/bcs-scheduler/src/manager/sched/offer/offerpool.go index 1cd7c123f3..48d30a5814 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/sched/offer/offerpool.go +++ b/bcs-mesos/bcs-scheduler/src/manager/sched/offer/offerpool.go @@ -109,7 +109,7 @@ type innerOffer struct { id int64 offerId string hostname string - offerIp string + offerIp string isValid bool createdTime int64 @@ -439,15 +439,15 @@ func (p *offerPool) addOffers(offers []*mesos.Offer) bool { } //calculate offer point //point, (cpu-allocated/cpu)+(mem-allocated/mem) - offerIp,_ := p.getOfferIp(o) + offerIp, _ := p.getOfferIp(o) var point float64 - agent,err := p.store.FetchAgent(offerIp) - if err!=nil { + agent, err := p.store.FetchAgent(offerIp) + if err != nil { blog.Errorf("Fetch Agent %s failed: %s, and decline offer", offerIp, err.Error()) p.scheduler.UpdateMesosAgents() p.declineOffer(o) continue - }else { + } else { agentinfo := agent.GetAgentInfo() point = cpu/agentinfo.CpuTotal + mem/agentinfo.MemTotal blog.Infof("offer %s point=Cpu(%f/%f)+Mem(%f/%f)=%f", offerIp, cpu, agentinfo.CpuTotal, mem, agentinfo.MemTotal, point) diff --git a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/daemonset.go b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/daemonset.go index 0d55a35241..299fc73fd3 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/daemonset.go +++ b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/daemonset.go @@ -360,8 +360,8 @@ func (s *Scheduler) deleteDaemonset(daemon *types.BcsDaemonset) { } else { blog.Info("delete daemonset(%s): taskGroup(%s) not end status(%s) at current", daemon.GetUuid(), taskgroup.ID, taskgroup.Status) } - }else { - blog.Infof("delete daemonset(%s): taskGroup(%s) in end status(%s)",daemon.GetUuid(), taskgroup.ID, taskgroup.Status) + } else { + blog.Infof("delete daemonset(%s): taskGroup(%s) in end status(%s)", daemon.GetUuid(), taskgroup.ID, taskgroup.Status) } } @@ -409,7 +409,7 @@ func (s *Scheduler) deleteDaemonset(daemon *types.BcsDaemonset) { // Delete a taskgroup: // the taskgroup will delete from DB, application and service -func (s *Scheduler) DeleteDaemonsetTaskGroup(daemon *types.BcsDaemonset, taskGroup *types.TaskGroup){ +func (s *Scheduler) DeleteDaemonsetTaskGroup(daemon *types.BcsDaemonset, taskGroup *types.TaskGroup) { //delete daemonset pods index delete(daemon.Pods, taskGroup.ID) s.deleteTaskGroup(taskGroup) diff --git a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/data_check.go b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/data_check.go index c7dc2d8a81..95588d706e 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/data_check.go +++ b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/data_check.go @@ -233,7 +233,7 @@ func (mgr *DataCheckMgr) checkTaskgroupWhetherLost(taskGroups []*types.TaskGroup switch taskGroup.Status { case types.TASKGROUP_STATUS_RUNNING, types.TASKGROUP_STATUS_STARTING: updateInterval = 4 * MAX_DATA_UPDATE_INTERVAL - /*case types.TASKGROUP_STATUS_STAGING: + /*case types.TASKGROUP_STATUS_STAGING: updateInterval = 4 * MAX_STAGING_UPDATE_INTERVAL*/ } diff --git a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/scheduler.go b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/scheduler.go index 53f27b54ef..c47e8fe2ba 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/scheduler.go +++ b/bcs-mesos/bcs-scheduler/src/manager/sched/scheduler/scheduler.go @@ -889,7 +889,7 @@ func stateFromMasters(masters []string) (*megos.State, error) { return mesosClient.GetStateFromCluster() } -func (s *Scheduler) UpdateMesosAgents(){ +func (s *Scheduler) UpdateMesosAgents() { s.oprMgr.UpdateMesosAgents() } diff --git a/bcs-mesos/bcs-scheduler/src/manager/sched/task/task.go b/bcs-mesos/bcs-scheduler/src/manager/sched/task/task.go index cdac91606f..9c7419ac7f 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/sched/task/task.go +++ b/bcs-mesos/bcs-scheduler/src/manager/sched/task/task.go @@ -223,7 +223,7 @@ func CreateTaskGroup(version *types.Version, ID string, appInstances uint64, app task.Command = container.Docker.Command task.Arguments = container.Docker.Arguments task.DataClass = container.DataClass - task.DataClass.Msgs = make([]*types.BcsMessage,0) + task.DataClass.Msgs = make([]*types.BcsMessage, 0) if err := createTaskConfigMaps(&task, container.ConfigMaps, store); err != nil { return nil, err } @@ -383,10 +383,10 @@ func createTaskConfigMaps(task *types.Task, configMaps []commtypes.ConfigMap, st blog.Warn("unkown configmap type:%s for task:%s", confItem.Type, task.ID) continue } - by,_ := json.Marshal(msg) + by, _ := json.Marshal(msg) blog.Info("add task %s configmap message: %s", task.ID, string(by)) task.DataClass.Msgs = append(task.DataClass.Msgs, msg) - by,_ = json.Marshal(task.DataClass) + by, _ = json.Marshal(task.DataClass) blog.Infof("task %s dataclass(%s)", task.ID, string(by)) } } diff --git a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/store.go b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/store.go index f762cffea8..4714f353ec 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/store.go +++ b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/store.go @@ -21,10 +21,10 @@ import ( "time" "github.com/Tencent/bk-bcs/bcs-common/common/blog" + typesplugin "github.com/Tencent/bk-bcs/bcs-common/common/plugin" "github.com/Tencent/bk-bcs/bcs-mesos/bcs-scheduler/src/manager/store" - "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/internalclientset" "github.com/Tencent/bk-bcs/bcs-mesos/bcs-scheduler/src/pluginManager" - typesplugin "github.com/Tencent/bk-bcs/bcs-common/common/plugin" + "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/internalclientset" bkbcsv2 "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/internalclientset/typed/bkbcs/v2" corev1 "k8s.io/api/core/v1" @@ -88,7 +88,7 @@ type managerStore struct { cancel context.CancelFunc //plugin manager, ip-resources - pm *pluginManager.PluginManager + pm *pluginManager.PluginManager clusterId string } @@ -162,7 +162,7 @@ func (s *managerStore) StopStoreMetrics() { s.cancel() time.Sleep(time.Second) -// s.wg.Wait() + // s.wg.Wait() } //store metrics report prometheus @@ -170,7 +170,7 @@ func (s *managerStore) StartStoreObjectMetrics() { s.ctx, s.cancel = context.WithCancel(context.Background()) for { time.Sleep(time.Minute) - if cacheMgr==nil || !cacheMgr.isOK { + if cacheMgr == nil || !cacheMgr.isOK { continue } blog.Infof("start produce metrics") @@ -251,8 +251,8 @@ func (s *managerStore) StartStoreObjectMetrics() { var ( clusterCpu float64 clusterMem float64 - remainCpu float64 - remainMem float64 + remainCpu float64 + remainMem float64 ) for _, agent := range agents { info := agent.GetAgentInfo() @@ -262,7 +262,7 @@ func (s *managerStore) StartStoreObjectMetrics() { } var ipValue float64 - if s.pm!=nil { + if s.pm != nil { //request netservice to node container ip para := &typesplugin.HostPluginParameter{ Ips: []string{info.IP}, @@ -285,9 +285,9 @@ func (s *managerStore) StartStoreObjectMetrics() { } //if ip-resources is zero, then ignore it - if s.pm==nil || ipValue>0{ - remainCpu += info.CpuTotal-info.CpuUsed - remainMem += info.MemTotal-info.MemUsed + if s.pm == nil || ipValue > 0 { + remainCpu += info.CpuTotal - info.CpuUsed + remainMem += info.MemTotal - info.MemUsed } clusterCpu += info.CpuTotal clusterMem += info.MemTotal @@ -334,8 +334,8 @@ func NewEtcdStore(kubeconfig string, pm *pluginManager.PluginManager, clusterId BkbcsClient: clientset.BkbcsV2(), k8sClient: k8sClientset, extensionClient: extensionClient, - pm: pm, - clusterId: clusterId, + pm: pm, + clusterId: clusterId, } //fetch application @@ -444,6 +444,6 @@ func (store *managerStore) filterSpecialLabels(oriLabels map[string]string) map[ return labels } -func (store *managerStore) ObjectNotLatestErr(err error)bool{ +func (store *managerStore) ObjectNotLatestErr(err error) bool { return strings.Contains(err.Error(), ObjectVersionNotLatestError) -} \ No newline at end of file +} diff --git a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/task.go b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/task.go index cac2d271f4..bb5e615557 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/task.go +++ b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/task.go @@ -69,9 +69,9 @@ func (store *managerStore) SaveTask(task *types.Task) error { return nil } -func (store *managerStore) syncTaskInCache(taskId string){ - task,err := store.FetchDBTask(taskId) - if err!=nil { +func (store *managerStore) syncTaskInCache(taskId string) { + task, err := store.FetchDBTask(taskId) + if err != nil { blog.Errorf("fetch task(%s) in kube-apiserver failed: %s", taskId, err.Error()) return } diff --git a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/taskgroup.go b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/taskgroup.go index 1e7a325e0c..5ed82e3a51 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/store/etcd/taskgroup.go +++ b/bcs-mesos/bcs-scheduler/src/manager/store/etcd/taskgroup.go @@ -86,9 +86,9 @@ func (store *managerStore) SaveTaskGroup(taskGroup *types.TaskGroup) error { return nil } -func (store *managerStore) syncTaskgroupInCache(taskgroupId string){ - taskgroup,err := store.FetchDBTaskGroup(taskgroupId) - if err!=nil { +func (store *managerStore) syncTaskgroupInCache(taskgroupId string) { + taskgroup, err := store.FetchDBTaskGroup(taskgroupId) + if err != nil { blog.Errorf("fetch taskgroup(%s) in kube-apiserver failed: %s", taskgroupId, err.Error()) return } diff --git a/bcs-mesos/bcs-scheduler/src/manager/store/zk/store.go b/bcs-mesos/bcs-scheduler/src/manager/store/zk/store.go index 39ad8cca39..8fb02174ca 100644 --- a/bcs-mesos/bcs-scheduler/src/manager/store/zk/store.go +++ b/bcs-mesos/bcs-scheduler/src/manager/store/zk/store.go @@ -31,15 +31,15 @@ type managerStore struct { cancel context.CancelFunc //plugin manager, ip-resources - pm *pluginManager.PluginManager + pm *pluginManager.PluginManager clusterId string } // Create a store manager by a db driver func NewManagerStore(dbDriver store.Dbdrvier, pm *pluginManager.PluginManager, clusterId string) store.Store { s := &managerStore{ - Db: dbDriver, - pm: pm, + Db: dbDriver, + pm: pm, clusterId: clusterId, } @@ -60,7 +60,7 @@ func (s *managerStore) StartStoreObjectMetrics() { for { time.Sleep(time.Minute) - if cacheMgr==nil { + if cacheMgr == nil { continue } blog.Infof("start produce metrics") @@ -136,8 +136,8 @@ func (s *managerStore) StartStoreObjectMetrics() { var ( clusterCpu float64 clusterMem float64 - remainCpu float64 - remainMem float64 + remainCpu float64 + remainMem float64 ) // handle agents metrics agents, err := s.ListAllAgents() @@ -152,7 +152,7 @@ func (s *managerStore) StartStoreObjectMetrics() { } var ipValue float64 - if s.pm!=nil { + if s.pm != nil { //request netservice to node container ip para := &typesplugin.HostPluginParameter{ Ips: []string{info.IP}, @@ -175,9 +175,9 @@ func (s *managerStore) StartStoreObjectMetrics() { } //if ip-resources is zero, then ignore it - if s.pm==nil || ipValue>0{ - clusterCpu += info.CpuTotal-info.CpuUsed - clusterMem += info.MemTotal-info.MemUsed + if s.pm == nil || ipValue > 0 { + clusterCpu += info.CpuTotal - info.CpuUsed + clusterMem += info.MemTotal - info.MemUsed } clusterCpu += info.CpuTotal clusterMem += info.MemTotal diff --git a/bcs-mesos/pkg/apis/monitor/v1/servicemonitor_types.go b/bcs-mesos/pkg/apis/monitor/v1/servicemonitor_types.go index 3f0cf7ed4b..69c5ad51f8 100644 --- a/bcs-mesos/pkg/apis/monitor/v1/servicemonitor_types.go +++ b/bcs-mesos/pkg/apis/monitor/v1/servicemonitor_types.go @@ -56,10 +56,10 @@ func (s *ServiceMonitor) GetSelector() labels.Requirements { return rms } -func (s *ServiceMonitor) Match(labels map[string]string)bool{ - for k,v :=range s.Spec.Selector.MatchLabels { - val,ok := labels[k] - if !ok || val!=v { +func (s *ServiceMonitor) Match(labels map[string]string) bool { + for k, v := range s.Spec.Selector.MatchLabels { + val, ok := labels[k] + if !ok || val != v { return false } } diff --git a/bcs-services/bcs-network-detection/app/app.go b/bcs-services/bcs-network-detection/app/app.go index dee0e95570..38d5d5ef8c 100644 --- a/bcs-services/bcs-network-detection/app/app.go +++ b/bcs-services/bcs-network-detection/app/app.go @@ -17,9 +17,9 @@ import ( "os" "github.com/Tencent/bk-bcs/bcs-common/common" - "github.com/Tencent/bk-bcs/bcs-common/common/types" "github.com/Tencent/bk-bcs/bcs-common/common/blog" "github.com/Tencent/bk-bcs/bcs-common/common/static" + "github.com/Tencent/bk-bcs/bcs-common/common/types" "github.com/Tencent/bk-bcs/bcs-services/bcs-network-detection/app/options" "github.com/Tencent/bk-bcs/bcs-services/bcs-network-detection/config" "github.com/Tencent/bk-bcs/bcs-services/bcs-network-detection/network-detection" diff --git a/bcs-services/bcs-network-detection/network-detection/network-detection.go b/bcs-services/bcs-network-detection/network-detection/network-detection.go index 7583fa2b7e..3aaae46e52 100644 --- a/bcs-services/bcs-network-detection/network-detection/network-detection.go +++ b/bcs-services/bcs-network-detection/network-detection/network-detection.go @@ -102,7 +102,7 @@ func (n *NetworkDetection) Start() error { } //new mesos platform conf := &mesosdriver.Config{ - ZkAddr: n.conf.BcsZk, + ZkAddr: n.conf.BcsZk, ClientCert: n.conf.ClientCert, } n.platform, err = mesosdriver.NewMesosDriverClient(conf) diff --git a/bcs-services/bcs-service-prometheus/app/options/options.go b/bcs-services/bcs-service-prometheus/app/options/options.go index b1af591a99..97a0dcf52e 100644 --- a/bcs-services/bcs-service-prometheus/app/options/options.go +++ b/bcs-services/bcs-service-prometheus/app/options/options.go @@ -28,18 +28,18 @@ type PrometheusControllerOption struct { conf.LogConfig conf.ProcessConfig - ClusterZk string `json:"cluster_zookeeper" value:"" usage:"mesos cluster zookeeper"` - CadvisorPort int `json:"cadvisor_port" value:"" usage:"node cadvisor port"` - NodeExporterPort int `json:"node_exporter_port" value:"" usage:"node exporter port"` - ClusterId string `json:"clusterid" value:"" usage:"mesos clusterid"` - PromFilePrefix string `json:"prom_file_prefix" value:"" usage:"prometheus service discovery file prefix"` - EnableMesos bool `json:"enable_mesos" value:"true" usage:"enable mesos prometheus service discovery"` - EnableService bool `json:"enable_service" value:"true" usage:"enable service prometheus service discovery"` - EnableNode bool `json:"enable_node" value:"true" usage:"enable node prometheus service discovery"` - EnableServiceMonitor bool `json:"enable_service_monitor" value:"true" usage:"enable service monitor discovery"` - Kubeconfig string `json:"kubeconfig" value:"" usage:"kubernetes kubeconfig"` - ServiceModules []string `json:"service_modules" value:"" usage:"service module list"` - ClusterModules []string `json:"cluster_modules" value:"" usage:"cluster module list"` + ClusterZk string `json:"cluster_zookeeper" value:"" usage:"mesos cluster zookeeper"` + CadvisorPort int `json:"cadvisor_port" value:"" usage:"node cadvisor port"` + NodeExporterPort int `json:"node_exporter_port" value:"" usage:"node exporter port"` + ClusterId string `json:"clusterid" value:"" usage:"mesos clusterid"` + PromFilePrefix string `json:"prom_file_prefix" value:"" usage:"prometheus service discovery file prefix"` + EnableMesos bool `json:"enable_mesos" value:"true" usage:"enable mesos prometheus service discovery"` + EnableService bool `json:"enable_service" value:"true" usage:"enable service prometheus service discovery"` + EnableNode bool `json:"enable_node" value:"true" usage:"enable node prometheus service discovery"` + EnableServiceMonitor bool `json:"enable_service_monitor" value:"true" usage:"enable service monitor discovery"` + Kubeconfig string `json:"kubeconfig" value:"" usage:"kubernetes kubeconfig"` + ServiceModules []string `json:"service_modules" value:"" usage:"service module list"` + ClusterModules []string `json:"cluster_modules" value:"" usage:"cluster module list"` } //NewPrometheusControllerOption create PrometheusControllerOption object diff --git a/bcs-services/bcs-service-prometheus/config/config.go b/bcs-services/bcs-service-prometheus/config/config.go index f28acf41a3..821abc81f0 100644 --- a/bcs-services/bcs-service-prometheus/config/config.go +++ b/bcs-services/bcs-service-prometheus/config/config.go @@ -15,17 +15,17 @@ package config // sd prometheus config type Config struct { - ClusterZk string - CadvisorPort int - NodeExportPort int - ClusterId string - PromFilePrefix string - ServiceZk string - EnableMesos bool - EnableService bool - EnableNode bool + ClusterZk string + CadvisorPort int + NodeExportPort int + ClusterId string + PromFilePrefix string + ServiceZk string + EnableMesos bool + EnableService bool + EnableNode bool EnableServiceMonitor bool - Kubeconfig string - ServiceModules []string - ClusterModules []string + Kubeconfig string + ServiceModules []string + ClusterModules []string } diff --git a/bcs-services/bcs-service-prometheus/discovery/node-etcd-discovery.go b/bcs-services/bcs-service-prometheus/discovery/node-etcd-discovery.go index fe6ff2e3ba..f6db7f72ce 100644 --- a/bcs-services/bcs-service-prometheus/discovery/node-etcd-discovery.go +++ b/bcs-services/bcs-service-prometheus/discovery/node-etcd-discovery.go @@ -19,13 +19,13 @@ import ( "sync" "github.com/Tencent/bk-bcs/bcs-common/common/blog" - "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/informers" apisbkbcsv2 "github.com/Tencent/bk-bcs/bcs-mesos/pkg/apis/bkbcs/v2" + "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/informers" "github.com/Tencent/bk-bcs/bcs-mesos/pkg/client/internalclientset" "github.com/Tencent/bk-bcs/bcs-services/bcs-service-prometheus/types" - "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/clientcmd" ) type nodeEtcdDiscovery struct { @@ -51,7 +51,7 @@ func NewNodeEtcdDiscovery(kubeconfig string, promFilePrefix, module string, cadv cadvisorPort: cadvisorPort, nodeExportPort: nodeExportPort, module: module, - nodes: make(map[string]struct{}), + nodes: make(map[string]struct{}), } switch module { case CadvisorModule: diff --git a/bcs-services/bcs-service-prometheus/discovery/service-monitor.go b/bcs-services/bcs-service-prometheus/discovery/service-monitor.go index 445a30c507..43763ee334 100644 --- a/bcs-services/bcs-service-prometheus/discovery/service-monitor.go +++ b/bcs-services/bcs-service-prometheus/discovery/service-monitor.go @@ -47,9 +47,9 @@ type serviceMonitor struct { module string promFilePrefix string - eventHandler EventHandleFunc + eventHandler EventHandleFunc //endpoints - endpointLister bkbcsv2.BcsEndpointLister + endpointLister bkbcsv2.BcsEndpointLister endpointInformer cache.SharedIndexInformer //service monitor //serviceMonitorLister monitorv1.ServiceMonitorLister @@ -62,24 +62,24 @@ type serviceMonitor struct { } type serviceEndpoint struct { - serviceM *apismonitorv1.ServiceMonitor + serviceM *apismonitorv1.ServiceMonitor endpoints map[string]*apisbkbcsv2.BcsEndpoint - cPorts map[string]apismonitorv1.Endpoint + cPorts map[string]apismonitorv1.Endpoint } -func (s *serviceEndpoint) getPrometheusConfigs()[]*types.PrometheusSdConfig{ - promConfigs := make([]*types.PrometheusSdConfig,0) +func (s *serviceEndpoint) getPrometheusConfigs() []*types.PrometheusSdConfig { + promConfigs := make([]*types.PrometheusSdConfig, 0) //traverse BcsEndpoints, corresponding to a separate BcsService - for _,bcsEndpoint :=range s.endpoints { + for _, bcsEndpoint := range s.endpoints { conf := &types.PrometheusSdConfig{ Targets: make([]string, 0), - Labels: make(map[string]string), + Labels: make(map[string]string), } - for k,v :=range bcsEndpoint.Labels { - r,_:=regexp.Compile("[a-zA-Z_][a-zA-Z0-9_]*") + for k, v := range bcsEndpoint.Labels { + r, _ := regexp.Compile("[a-zA-Z_][a-zA-Z0-9_]*") rk := r.FindAllString(k, 1) - if len(rk)!=1 || rk[0]!=k { - blog.Infof("BcsEndpoint(%s) Label(%s:%s) is invalid", bcsEndpoint.GetUuid(), k,v) + if len(rk) != 1 || rk[0] != k { + blog.Infof("BcsEndpoint(%s) Label(%s:%s) is invalid", bcsEndpoint.GetUuid(), k, v) continue } conf.Labels[k] = v @@ -93,18 +93,18 @@ func (s *serviceEndpoint) getPrometheusConfigs()[]*types.PrometheusSdConfig{ conf.Labels["namespace"] = bcsEndpoint.Namespace conf.Labels["job"] = fmt.Sprintf("%s/%s/0", bcsEndpoint.Namespace, s.serviceM.Name) conf.Labels["name"] = s.serviceM.Name - for _,endpoint :=range bcsEndpoint.Spec.Endpoints { - for _,cPort := range endpoint.Ports { - _,ok := s.cPorts[cPort.Name] + for _, endpoint := range bcsEndpoint.Spec.Endpoints { + for _, cPort := range endpoint.Ports { + _, ok := s.cPorts[cPort.Name] if !ok { blog.V(3).Infof("BcsEndpoint(%s) endpoint(%s) port(%s) don't matched, and continue", bcsEndpoint.GetUuid(), endpoint.ContainerIP, cPort.Name) continue } //if container network=Host - if endpoint.NetworkMode=="HOST" { + if endpoint.NetworkMode == "HOST" { conf.Targets = append(conf.Targets, fmt.Sprintf("%s:%d", endpoint.NodeIP, cPort.ContainerPort)) - }else { + } else { conf.Targets = append(conf.Targets, fmt.Sprintf("%s:%d", endpoint.ContainerIP, cPort.ContainerPort)) } } @@ -122,7 +122,7 @@ func NewServiceMonitor(kubeconfig string, promFilePrefix, module string) (Discov kubeconfig: kubeconfig, module: module, promFilePrefix: promFilePrefix, - svrMonitors: make(map[string]*serviceEndpoint), + svrMonitors: make(map[string]*serviceEndpoint), } return disc, nil @@ -224,7 +224,7 @@ func (disc *serviceMonitor) GetPrometheusSdConfig(key string) ([]*types.Promethe disc.Lock() defer disc.Unlock() - svrMonitor,ok := disc.svrMonitors[key] + svrMonitor, ok := disc.svrMonitors[key] if !ok { return nil, fmt.Errorf("ServiceMonitor(%s) Not Found", key) } @@ -246,18 +246,18 @@ func (disc *serviceMonitor) OnServiceMonitorAdd(obj interface{}) { blog.Errorf("cannot convert to *apismonitorv1.ServiceMonitor: %v", obj) return } - by,_ := json.Marshal(serviceM) + by, _ := json.Marshal(serviceM) blog.Infof("recieve ServiceMonitor(%s) Data(%s) Add event", serviceM.GetUuid(), string(by)) disc.handlerServiceMonitorChanged(serviceM) } -func (disc *serviceMonitor) validateServiceMonitor(serviceM *apismonitorv1.ServiceMonitor)bool{ - if len(serviceM.Spec.Endpoints)==0 { +func (disc *serviceMonitor) validateServiceMonitor(serviceM *apismonitorv1.ServiceMonitor) bool { + if len(serviceM.Spec.Endpoints) == 0 { blog.Errorf("ServiceMonitor(%s) len(Endpoints)==0, then ignore it", serviceM.GetUuid()) return false } - if len(serviceM.Spec.Selector.MatchLabels)==0 { + if len(serviceM.Spec.Selector.MatchLabels) == 0 { blog.Errorf("ServiceMonitor(%s) len(Selector.MatchLabels)==0, then ignore it", serviceM.GetUuid()) return false } @@ -272,35 +272,35 @@ func (disc *serviceMonitor) OnServiceMonitorUpdate(old, cur interface{}) { blog.Errorf("cannot convert to *apismonitorv1.ServiceMonitor: %v", cur) return } - by,_ := json.Marshal(serviceM) + by, _ := json.Marshal(serviceM) blog.Infof("recieve ServiceMonitor(%s) Data(%s) Update event", serviceM.GetUuid(), string(by)) disc.handlerServiceMonitorChanged(serviceM) } -func (disc *serviceMonitor) handlerServiceMonitorChanged(serviceM *apismonitorv1.ServiceMonitor){ +func (disc *serviceMonitor) handlerServiceMonitorChanged(serviceM *apismonitorv1.ServiceMonitor) { if !disc.validateServiceMonitor(serviceM) { return } o := &serviceEndpoint{ - serviceM: serviceM, + serviceM: serviceM, endpoints: make(map[string]*apisbkbcsv2.BcsEndpoint), - cPorts: make(map[string]apismonitorv1.Endpoint), + cPorts: make(map[string]apismonitorv1.Endpoint), } - for _,endpoint :=range serviceM.Spec.Endpoints { + for _, endpoint := range serviceM.Spec.Endpoints { o.cPorts[endpoint.Port] = endpoint - blog.Infof("ServiceMonitor(%s) have endpoint(%s:%s)",serviceM.GetUuid(), endpoint.Port, endpoint.Path) + blog.Infof("ServiceMonitor(%s) have endpoint(%s:%s)", serviceM.GetUuid(), endpoint.Port, endpoint.Path) } rms := labels.NewSelector() - for _,o :=range serviceM.GetSelector() { + for _, o := range serviceM.GetSelector() { rms.Add(o) } - endpoints,err := disc.endpointLister.BcsEndpoints(serviceM.Namespace).List(rms) - if err!=nil { + endpoints, err := disc.endpointLister.BcsEndpoints(serviceM.Namespace).List(rms) + if err != nil { blog.Errorf("ServiceMonitor(%s) get Endpoints failed: %s", serviceM.GetUuid(), err.Error()) return } - for _,v :=range endpoints { - if !serviceM.Match(v.Labels){ + for _, v := range endpoints { + if !serviceM.Match(v.Labels) { blog.Infof("ServiceMonitor(%s) don't match BcsEndpoint(%s), and continue", serviceM.GetUuid(), v.GetUuid()) continue } @@ -335,9 +335,9 @@ func (disc *serviceMonitor) OnEndpointsAdd(obj interface{}) { blog.Errorf("cannot convert to *apisbkbcsv2.BcsEndpoint: %v", obj) return } - by,_ := json.Marshal(endpoint) + by, _ := json.Marshal(endpoint) blog.Infof("recieve BcsEndpoint(%s) Data(%s) Add event", endpoint.GetUuid(), string(by)) - for _,sm :=range disc.svrMonitors { + for _, sm := range disc.svrMonitors { serviceM := sm.serviceM if !serviceM.Match(endpoint.Labels) { blog.V(3).Infof("ServiceMonitor(%s) don't match BcsEndpoint(%s), and continue", serviceM.GetUuid(), endpoint.GetUuid()) @@ -369,10 +369,10 @@ func (disc *serviceMonitor) OnEndpointsUpdate(old, cur interface{}) { blog.V(3).Infof("OnEndpointsUpdate BcsEndpoint(%s) don't change", oldEndpoint.GetUuid()) return } - by,_ := json.Marshal(curEndpoint) + by, _ := json.Marshal(curEndpoint) blog.Infof("recieve BcsEndpoint(%s) Data(%s) Update event", curEndpoint.GetUuid(), string(by)) - for _,sm :=range disc.svrMonitors { + for _, sm := range disc.svrMonitors { serviceM := sm.serviceM if !serviceM.Match(curEndpoint.Labels) { blog.V(3).Infof("ServiceMonitor(%s) don't match BcsEndpoint(%s), and continue", serviceM.GetUuid(), curEndpoint.GetUuid()) @@ -387,18 +387,18 @@ func (disc *serviceMonitor) OnEndpointsUpdate(old, cur interface{}) { } } -func checkEndpointsChanged(old, cur commtypes.BcsEndpoint)bool{ - if len(old.Endpoints)!=len(cur.Endpoints) { +func checkEndpointsChanged(old, cur commtypes.BcsEndpoint) bool { + if len(old.Endpoints) != len(cur.Endpoints) { return true } endpoints := make(map[string]bool) - for _,in := range old.Endpoints { + for _, in := range old.Endpoints { endpoints[in.ContainerIP] = false } - for _,in := range cur.Endpoints { + for _, in := range cur.Endpoints { endpoints[in.ContainerIP] = true } - for k,v :=range endpoints { + for k, v := range endpoints { if !v { blog.Infof("BcsEndpoint(%s) ContainerIP(%s) changed", k) return true @@ -415,7 +415,7 @@ func (disc *serviceMonitor) OnEndpointsDelete(obj interface{}) { return } blog.Infof("recieve BcsEndpoint(%s) Delete event", endpoint.GetUuid()) - for _,sm :=range disc.svrMonitors { + for _, sm := range disc.svrMonitors { serviceM := sm.serviceM if !serviceM.Match(endpoint.Labels) { blog.V(3).Infof("ServiceMonitor(%s) don't match BcsEndpoint(%s), and continue", serviceM.GetUuid(), endpoint.GetUuid()) @@ -429,6 +429,3 @@ func (disc *serviceMonitor) OnEndpointsDelete(obj interface{}) { go disc.eventHandler(DiscoveryInfo{Module: disc.module, Key: serviceM.GetUuid()}) } } - - - diff --git a/go.mod b/go.mod index d09a56b409..57c346f4f9 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( github.com/fsouza/go-dockerclient v1.3.1 github.com/garyburd/redigo v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 - github.com/go-logr/logr v0.2.0 // indirect + github.com/go-logr/logr v0.1.0 // indirect github.com/go-logr/zapr v0.1.1 // indirect github.com/go-openapi/analysis v0.19.6 // indirect github.com/go-openapi/jsonreference v0.19.3 // indirect @@ -75,7 +75,7 @@ require ( github.com/google/cadvisor v0.32.0 github.com/google/go-cmp v0.4.0 github.com/google/go-querystring v1.0.0 - github.com/googleapis/gnostic v0.4.2 // indirect + github.com/googleapis/gnostic v0.4.0 // indirect github.com/gorilla/mux v1.6.2 github.com/gorilla/websocket v1.4.0 github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect @@ -161,7 +161,7 @@ require ( k8s.io/apiextensions-apiserver v0.0.0-20181126155829-0cd23ebeb688 k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674 k8s.io/client-go v0.0.0-20181126152608-d082d5923d3c - k8s.io/kube-openapi v0.0.0-20200615155156-dffdd1682719 // indirect + k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31 // indirect k8s.io/kubernetes v1.14.10 k8s.io/utils v0.0.0-20190923111123-69764acb6e8e // indirect sigs.k8s.io/controller-runtime v0.1.9 diff --git a/go.sum b/go.sum index 4c0ec14bd3..7824e41915 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,7 @@ github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -228,6 +229,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -252,11 +254,15 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.4.0 h1:BXDUo8p/DaxC+4FJY/SSx3gvnx9C1VdHNgaUkiEL5mk= +github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.4.2 h1:uh5EXM/5/ki6d0p/FoUxuiN8KHpo1w572UXQdB2MnTg= github.com/googleapis/gnostic v0.4.2/go.mod h1:P0d+GwDcJO8XvMi7aihGGl/CkivFa9JX/V/FfjyYzI0= @@ -310,6 +316,7 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -372,6 +379,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= @@ -418,6 +426,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= @@ -465,6 +474,7 @@ github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= @@ -513,6 +523,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -536,6 +547,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -548,6 +560,7 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -624,10 +637,14 @@ k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674 h1:S3ImTLK1F6igG0/5Tx8hf0 k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/client-go v0.0.0-20181126152608-d082d5923d3c h1:Yfl89y6L9aMi54tA3TSQjkhjp0gGyb53qblgMqms4Gg= k8s.io/client-go v0.0.0-20181126152608-d082d5923d3c/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31 h1:PsbYeEz2x7ll6JYUzBEG+DT78910DDTlvn5Ma10F5/E= +k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200615155156-dffdd1682719 h1:n/ElZyI1dzFPXKS8nZMw8wozBUz7vEfL0Ja7jN2rSvA= k8s.io/kube-openapi v0.0.0-20200615155156-dffdd1682719/go.mod h1:bfCVj+qXcEaE5SCvzBaqpOySr6tuCcpPKqF6HD8nyCw= k8s.io/kubernetes v1.14.10 h1:P9qsSUUdx0MZKtJH9kvTHFTZamOH/lZjdcpmDhx0C9g= @@ -638,6 +655,7 @@ moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= sigs.k8s.io/controller-runtime v0.1.9 h1:ZcnTZfnCGynyToVwHsqV3bMoGXwViYlnUF8kfMgghK8= sigs.k8s.io/controller-runtime v0.1.9/go.mod h1:HFAYoOh6XMV+jKF1UjFwrknPbowfyHEHHRdJMf2jMX8= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs= sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U= From 64de1aadf1114b1ac098726d3dd2d72edce26e37 Mon Sep 17 00:00:00 2001 From: DeveloperJim <190177081@qq.com> Date: Tue, 4 Aug 2020 22:15:00 +0800 Subject: [PATCH 3/3] docs: 1.18.3 release, issue #0 --- docs/version/1.18.x.md | 17 +++++++++++++++++ docs/version/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/docs/version/1.18.x.md b/docs/version/1.18.x.md index fe696bbece..b583f42e8c 100644 --- a/docs/version/1.18.x.md +++ b/docs/version/1.18.x.md @@ -1,5 +1,22 @@ # 1.18.x 版本信息说明 +## 1.18.3 + +- 发布日期:2020-08-04 +- **新增功能** + * [Mesos] Mesos方案支持prometheus ServiceMonitor[#514] + * [K8S/Mesos] qcloud-eip插件支持在线扩容并兼容bridge模式[#515] + * [K8S/Mesos] bcs-user-manager支持websocket tunnel模式实现集群托管[#521] + * [Mesos] 支持机器异构场景下均匀调度容器[#25] + * [Mesos] bcs-scheduler支持环境变量数据引用[#533] +- **功能优化** + * 全模块容器化配置统一调整[#508] + * [Mesos] 优化bcs-scheduler metrics数据[#532] +- **BUG修复** + * [Mesos] bcs-scheduler修复taskgroup因为自定义数据过大导致数据重复问题[#523] + * [Mesos] bcs-scheduler修复etcd存储模式下taskgroup数据保存超时问题[#525] + * [Mesos] bcs-scheduler优化scale up超时问题[#527] + ## 1.18.1-alpha - 发布日期:2020-07-02 diff --git a/docs/version/README.md b/docs/version/README.md index c9622a53ec..4524332ebf 100644 --- a/docs/version/README.md +++ b/docs/version/README.md @@ -1,5 +1,45 @@ # 发布版本信息 +## 1.18.3 +- 发布日期:2020-08-04 +- **新增功能** + * [Mesos]bcs-scheduler支持Daemonset特性[#207] + * [Mesos]bcs-service-prometheus支持etcd存储模式[#473] + * 新增模块bcs-bkcmdb-synchronizer,支持容器数据收录至蓝鲸cmdb[#476] + * [K8S]新增模块bcs-cc-agent,为容器同步主机节点属性信息[#496] + * [K8S/Mesos]bcs-cloudnetwork-agent支持腾讯云underlay方案初始化[#499] + * [K8S/Mesos]开源bcs-egress-controller模块[#501] + * [K8S]开源bk-cmdb-operator模块[#503] + * [Mesos] Mesos方案支持prometheus ServiceMonitor[#514] + * [K8S/Mesos] qcloud-eip插件支持在线扩容并兼容bridge模式[#515] + * [K8S/Mesos] bcs-user-manager支持websocket tunnel模式实现集群托管[#521] + * [Mesos] 支持机器异构场景下均匀调度容器[#25] + * [Mesos] bcs-scheduler支持环境变量数据引用[#533] +- **功能优化** + * [K8S/Mesos]容器日志采集方案支持采集路径模糊匹配,上报Label开关[#472] + * 清理所有模块中对蓝鲸license服务依赖[#474] + * [Mesos] bcs-scheduler支持mesos方案下容器corefile目录权限[#481] + * [K8S/Mesos] bcs-loadbalance增强proxy转发规则冲突检测能力[#482] + * [K8S/Mesos] bcs-datawatch优化同步netservice underlay资源超时问题[#483] + * [Mesos] bcs-scheduler优化deepcopy导致CPU消耗过高问题[#485] + * [K8S/Mesos]针对AWS网络方案中使用到的secret进行加密[#490] + * [K8S]StatefulSetPlus更名为GameStatefulSet[#498] + * 全模块容器化配置统一调整[#508] + * [Mesos] 优化bcs-scheduler metrics数据[#532] +- **BUG修复** + * 修复所有模块中ticker未关闭问题[#478] + * [K8S]修复bcs-k8s-watch同步数据至bcs-storage数据不一致问题[#488] + * [K8S/Mesos]修复AWS弹性网卡方案无法联通问题[#489] + * [Mesos]修复bcs-mesos-adatper因为zookeeper异常时导致服务发现异常问题[#491] + * [K8S/Mesos]修复bcs-loadbalance更新转发规则异常问题[#493] + * [K8S/Mesos]修复bcs-webhook-server覆盖用户init-container的问题[#495] + * [K8S]修复bcs-api因为权限问题无法使用kubectl exec与webconsole问题[#504] + * [K8S]修复bcs-api websocket tunnel异常问题[#510] + * [K8S/Mesos]修复腾讯云网络插件qcloud-eip与全局路由方案冲突问题[#515] + * [Mesos] bcs-scheduler修复taskgroup因为自定义数据过大导致数据重复问题[#523] + * [Mesos] bcs-scheduler修复etcd存储模式下taskgroup数据保存超时问题[#525] + * [Mesos] bcs-scheduler优化scale up超时问题[#527] + ## 1.17.5 - 发布日期:2020-07-06 - **新增功能**