├── .gitignore
├── .gitmodules
├── README.md
├── comparison-operators
└── main.go
├── generics
└── main.go
├── go.mod
├── go.sum
├── http2
├── hpack-example
│ └── main.go
├── ja3
│ └── main.go
├── request-example
│ ├── README.md
│ └── main.go
├── server-push
│ ├── ca.crt
│ ├── ca.key
│ ├── main.go
│ └── static
│ │ ├── app.js
│ │ └── style.css
└── tls
│ ├── client.crt
│ ├── client.key
│ ├── handsh
│ ├── addr.go
│ ├── alert.go
│ ├── auth.go
│ ├── chipher_suites.go
│ ├── cipher_suites_tls13.go
│ ├── common.go
│ ├── conn.go
│ ├── key_agreement.go
│ ├── key_schedule.go
│ ├── keylog.go
│ ├── msg.go
│ ├── msg_test.go
│ ├── parse.go
│ ├── prf.go
│ ├── rand.go
│ └── raw_reader.go
│ ├── main.go
│ ├── root.crt
│ ├── root.key
│ ├── server.crt
│ └── server.key
├── httptrace
├── example
│ └── main.go
└── trace.go
├── money
└── main.go
├── pbjson
├── main.go
├── oneof
│ ├── test.pb.go
│ └── test.proto
├── p3optional
│ ├── testp3.pb.go
│ └── testp3.proto
├── p3p2
│ ├── test2.pb.go
│ ├── test2.proto
│ ├── test3.pb.go
│ └── test3.proto
└── wrapper
│ ├── test.pb.go
│ └── test.proto
├── qrcode.jpg
├── receiver
└── main.go
├── slice
└── main.go
├── ssrf
└── main.go
├── strs
├── cache.go
├── lru.go
└── version_test.go
├── types
├── main.go
└── ttt
│ └── test.go
└── zerocopy
└── writto_readfrom.md
/.gitignore:
--------------------------------------------------------------------------------
1 | #ide
2 | .DS_Store
3 | .idea
4 | .vscode
5 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Isites/go-coder/659b17c131ca41bea84ad71ecad0fc116f846116/.gitmodules
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 微信公众号:Gopher指北
2 |
3 | 
4 |
5 |
--------------------------------------------------------------------------------
/comparison-operators/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "unsafe"
6 | )
7 |
8 | type it interface {
9 | f()
10 | }
11 |
12 | type ix1 int
13 |
14 | func (x ix1) f() {}
15 |
16 | type ix2 map[int]int
17 |
18 | func (x ix2) f() {}
19 |
20 | type canC struct {
21 | c int
22 | }
23 | type blankSt struct {
24 | a int
25 | _ string
26 | }
27 | type canNotC struct {
28 | m func() int
29 | }
30 |
31 | func t() interface{} {
32 | var err *error
33 | return err
34 | }
35 |
36 | func t1() interface{} {
37 | return nil
38 | }
39 |
40 | func main() {
41 | // 复数之间的比较
42 | var c1 complex128 = complex(1, 2) // 1+2i
43 | var c2 complex128 = complex(3, 4) // 3+4i
44 | fmt.Println(c1 == c2)
45 | // fmt.Println(c1 >= c2) // 放开注释编译会报错
46 |
47 | // 结构体之间的比较
48 | var st1, st2 canC
49 | fmt.Println(st1 == st2)
50 | st1.c = 3
51 | fmt.Println(st1 == st2)
52 | // fmt.Println(st1 <= st2) // 放开注释编译会报错
53 | // 匿名结构体字段的比较
54 | var (
55 | bst1 = blankSt{1, "333"}
56 | bst2 = blankSt{1, "44444"}
57 | )
58 | fmt.Println(bst1 == bst2)
59 | // 结构体包含不可比较的类型时
60 | // fmt.Println(canNotC{} == canNotC{}) // 放开注释编译会报错
61 |
62 | // 指针之间的比较
63 | var arr1, arr2 [0]int
64 | parr1 := &arr1
65 | parr2 := &arr2
66 | fmt.Println(unsafe.Sizeof(arr1))
67 | fmt.Println(parr1 == parr2)
68 | fmt.Println(uintptr(unsafe.Pointer(parr1)), uintptr(unsafe.Pointer(parr2)))
69 |
70 | // 管道之间的比较
71 | var cint1, cint2 chan<- string
72 | cint3 := make(chan string, 2)
73 | cint4 := make(chan string, 2)
74 | cint5 := make(chan string)
75 | fmt.Println(cint1 == cint2, cint3 == cint4, cint5 == cint1)
76 | cint1 = cint4
77 | fmt.Println(cint1 == cint4)
78 |
79 | // interface{}之间的比较
80 | var (
81 | i1 interface{} = uint(1)
82 | i2 interface{} = uint(1)
83 | i3 interface{} = uint(3)
84 | i4 interface{} = int(3)
85 | i5 interface{} = []int{}
86 | i6 interface{} = map[int]string{}
87 | // i7 interface{} = map[int]string{}
88 | )
89 | // 变量不为nil,且均为可比较类型时
90 | fmt.Println(i1 == i2, i1 == i3, i3 == i4)
91 | // 变量不为nil,且均为不可比较类型时
92 | fmt.Println(i5 == i6)
93 | // fmt.Println(i7 == i6) //避免panic
94 | // interface{} 不等于nil
95 | fmt.Println(t() == nil, t1() == nil)
96 |
97 | // X类型实现了接口T,则X的变量能和T的变量t进行比较
98 | x1 := ix1(2)
99 | var t1 it = ix2{}
100 | // 类型不一致时
101 | fmt.Println(x1 == t1)
102 | // 类型一致时
103 | t1 = ix1(2)
104 | fmt.Println(t1 == x1)
105 | // interface{} 和任意可比较类型进行比较
106 | var it1 interface{} = "111"
107 | fmt.Println(it1 == 1)
108 | // 引起panic, 下面代码注释避免引起panic
109 | // var t2 it = ix2{}
110 | // var t3 it = ix2{}
111 | // fmt.Println(t2 == t3)
112 |
113 | // 数组间的比较
114 | // 类型相同但元素不可比较
115 | // var array1 [3][]int
116 | // var array2 [3][]int
117 | // fmt.Println(array1 == array2)
118 | //类型可比较元素不想等
119 | // var array3 [3]int
120 | // var array4 [2]int
121 | // fmt.Println(array3 == array4)
122 | // 数组可比较时
123 | var array5, array6 [3]int
124 | fmt.Println(array5 == array6)
125 | array5 = [...]int{3, 2, 1}
126 | array6 = [...]int{1, 2, 3}
127 | fmt.Println(array5 == array6)
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/generics/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type Number interface {
8 | ~int64 | float64
9 | }
10 |
11 | type a int64
12 |
13 | func main() {
14 | // Initialize a map for the integer values
15 | ints := map[string]int64{
16 | "first": 34,
17 | "second": 12,
18 | }
19 |
20 | // Initialize a map for the float values
21 | floats := map[string]float64{
22 | "first": 35.98,
23 | "second": 26.99,
24 | }
25 |
26 | inta := map[string]a{
27 | "first": 34,
28 | "second": 12,
29 | }
30 |
31 | fmt.Printf("Non-Generic Sums: %v and %v\n",
32 | SumInts(ints),
33 | SumFloats(floats))
34 |
35 | fmt.Printf("Generic Sums: %v and %v\n",
36 | SumIntsOrFloats[string, int64](ints),
37 | SumIntsOrFloats[string, float64](floats))
38 |
39 | fmt.Printf("Generic Sums, type parameters inferred: %v and %v\n",
40 | SumIntsOrFloats(ints),
41 | SumIntsOrFloats(floats))
42 |
43 | fmt.Printf("Generic Sums with Constraint: %v and %v\n",
44 | SumNumbers(ints),
45 | SumNumbers(floats))
46 | fmt.Println(SumNumbers(inta))
47 | }
48 |
49 | // SumInts adds together the values of m.
50 | func SumInts(m map[string]int64) int64 {
51 | var s int64
52 | for _, v := range m {
53 | s += v
54 | }
55 | return s
56 | }
57 |
58 | // SumFloats adds together the values of m.
59 | func SumFloats(m map[string]float64) float64 {
60 | var s float64
61 | for _, v := range m {
62 | s += v
63 | }
64 | return s
65 | }
66 |
67 | // SumIntsOrFloats sums the values of map m. It supports both floats and integers
68 | // as map values.
69 | func SumIntsOrFloats[K comparable, V any | float64](m map[K]V) V {
70 | var s V
71 | for _, v := range m {
72 | s += v
73 | }
74 | return s
75 | }
76 |
77 | // SumNumbers sums the values of map m. Its supports both integers
78 | // and floats as map values.
79 | func SumNumbers[K comparable, V Number](m map[K]V) V {
80 | var s V
81 | for _, v := range m {
82 | s += v
83 | }
84 | return s
85 | }
86 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/Isites/go-coder
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/gogo/protobuf v1.3.1
7 | github.com/golang/protobuf v1.4.1
8 | github.com/hashicorp/golang-lru v0.5.4
9 | github.com/open-ch/ja3 v1.0.1
10 | github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b
11 | github.com/shopspring/decimal v1.3.1
12 | github.com/stretchr/testify v1.4.0
13 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
14 | golang.org/x/net v0.0.0-20200904194848-62affa334b73
15 | golang.org/x/sys v0.0.0-20210123231150-1d476976d117
16 | google.golang.org/protobuf v1.25.0
17 | )
18 |
19 | require (
20 | github.com/davecgh/go-spew v1.1.1 // indirect
21 | github.com/kr/pretty v0.1.0 // indirect
22 | github.com/pmezard/go-difflib v1.0.0 // indirect
23 | golang.org/x/text v0.3.0 // indirect
24 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
25 | gopkg.in/yaml.v2 v2.2.7 // indirect
26 | )
27 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
4 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
9 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
10 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
11 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
12 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
13 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
14 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
15 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
16 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
17 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
18 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
19 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
20 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
21 | github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
22 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
23 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
24 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
25 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
26 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
27 | github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
28 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
29 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
30 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
31 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
32 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
33 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
34 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
35 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
36 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
37 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
38 | github.com/open-ch/ja3 v1.0.1 h1:kMqfkgS+cTasMlsQaJ627qlw7kA/qRZVTmF0BtFjOLQ=
39 | github.com/open-ch/ja3 v1.0.1/go.mod h1:lTWgltvZDGQjIa/TjWTzfpCVa/eGP+szng2DWz9mAvk=
40 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
41 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
42 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
43 | github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b h1:lzo71oHzQEz0fKMSjR0BpVzuh2hOHvJTxnN3Rnikmtg=
44 | github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
45 | github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
46 | github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
47 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
48 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
49 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
50 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
51 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
52 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
53 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
54 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
55 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
56 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
57 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
58 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
59 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
60 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
61 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
62 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
63 | golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
64 | golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
65 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
66 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
67 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
68 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
69 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
70 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
71 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
72 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
73 | golang.org/x/sys v0.0.0-20210123231150-1d476976d117 h1:M1sK0uTIn2x3HD5sySUPBg7ml5hmlQ/t7n7cIM6My9w=
74 | golang.org/x/sys v0.0.0-20210123231150-1d476976d117/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
75 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
76 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
77 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
78 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
79 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
80 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
81 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
82 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
83 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
84 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
85 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
86 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
87 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
88 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
89 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
90 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
91 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
92 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
93 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
94 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
95 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
96 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
97 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
98 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
99 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
100 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
101 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
102 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
103 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
104 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
105 | gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
106 | gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
107 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
108 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
109 |
--------------------------------------------------------------------------------
/http2/hpack-example/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "fmt"
7 | "strings"
8 |
9 | "golang.org/x/net/http/httpguts"
10 | "golang.org/x/net/http2/hpack"
11 | )
12 |
13 | func main() {
14 | var (
15 | buf bytes.Buffer
16 | oriSize int
17 | )
18 | henc := hpack.NewEncoder(&buf)
19 | headers := []hpack.HeaderField{
20 | {Name: ":authority", Value: "dss0.bdstatic.com"},
21 | {Name: ":method", Value: "GET"},
22 | {Name: ":path", Value: "/5aV1bjqh_Q23odCf/static/superman/img/topnav/baiduyun@2x-e0be79e69e.png"},
23 | {Name: ":scheme", Value: "https"},
24 | {Name: "accept-encoding", Value: "gzip"},
25 | {Name: "user-agent", Value: "Go-http-client/2.0"},
26 | {Name: "custom-header", Value: "custom-value"},
27 | }
28 | for _, header := range headers {
29 | oriSize += len(header.Name) + len(header.Value)
30 | henc.WriteField(header)
31 | }
32 | fmt.Printf("ori size: %v, encoded size: %v\n", oriSize, buf.Len())
33 |
34 | var (
35 | invalid error
36 | sawRegular bool
37 | // 16 << 20 from fr.maxHeaderListSize() from
38 | remainSize uint32 = 16 << 20
39 | )
40 | hdec := hpack.NewDecoder(4096, nil)
41 | // 16 << 20 from fr.maxHeaderStringLen() from fr.maxHeaderListSize()
42 | hdec.SetMaxStringLength(int(remainSize))
43 | hdec.SetEmitFunc(func(hf hpack.HeaderField) {
44 | if !httpguts.ValidHeaderFieldValue(hf.Value) {
45 | invalid = fmt.Errorf("invalid header field value %q", hf.Value)
46 | }
47 | isPseudo := strings.HasPrefix(hf.Name, ":")
48 | if isPseudo {
49 | if sawRegular {
50 | invalid = errors.New("pseudo header field after regular")
51 | }
52 | } else {
53 | sawRegular = true
54 | // if !http2validWireHeaderFieldName(hf.Name) {
55 | // invliad = fmt.Sprintf("invalid header field name %q", hf.Name)
56 | // }
57 | }
58 |
59 | if invalid != nil {
60 | fmt.Println(invalid)
61 | hdec.SetEmitEnabled(false)
62 | return
63 | }
64 |
65 | size := hf.Size()
66 | if size > remainSize {
67 | hdec.SetEmitEnabled(false)
68 | // mh.Truncated = true
69 | return
70 | }
71 | remainSize -= size
72 | fmt.Printf("%+v\n", hf)
73 | // mh.Fields = append(mh.Fields, hf)
74 | })
75 | defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
76 | fmt.Println(hdec.Write(buf.Bytes()))
77 |
78 | // try again
79 | fmt.Println("try again: ")
80 | buf.Reset()
81 | henc.WriteField(hpack.HeaderField{Name: "custom-header", Value: "custom-value"})
82 | fmt.Println(hdec.Write(buf.Bytes()))
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/http2/ja3/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "crypto/tls"
6 | "fmt"
7 | "io"
8 | "io/ioutil"
9 | "net"
10 | "net/http"
11 |
12 | xtls "github.com/refraction-networking/utls"
13 | "golang.org/x/net/http2"
14 | )
15 |
16 | func main() {
17 | // http 1.1的实验
18 | tr := http.DefaultTransport.(*http.Transport).Clone()
19 | tr.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
20 | dialer := net.Dialer{}
21 | con, err := dialer.DialContext(ctx, network, addr)
22 | if err != nil {
23 | return nil, err
24 | }
25 | // 根据地址获取host信息
26 | host, _, err := net.SplitHostPort(addr)
27 | if err != nil {
28 | return nil, err
29 | }
30 | // 并且不验证host信息
31 | xtlsConf := &xtls.Config{
32 | ServerName: host,
33 | Renegotiation: xtls.RenegotiateNever,
34 | }
35 | // 构建tls.UConn
36 | xtlsConn := xtls.UClient(con, xtlsConf, xtls.HelloCustom)
37 | clientHelloSpec := &xtls.ClientHelloSpec{
38 | TLSVersMax: tls.VersionTLS12,
39 | TLSVersMin: tls.VersionTLS10,
40 | CipherSuites: []uint16{
41 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
42 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
43 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
44 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
45 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
46 | tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
47 | tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
48 | tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
49 | tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
50 | tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
51 | tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
52 | tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
53 | 2333,
54 | },
55 | CompressionMethods: []byte{
56 | 0,
57 | },
58 | Extensions: []xtls.TLSExtension{
59 | &xtls.RenegotiationInfoExtension{Renegotiation: xtls.RenegotiateOnceAsClient},
60 | &xtls.SNIExtension{ServerName: host},
61 | &xtls.UtlsExtendedMasterSecretExtension{},
62 | &xtls.SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []xtls.SignatureScheme{
63 | xtls.ECDSAWithP256AndSHA256,
64 | xtls.PSSWithSHA256,
65 | xtls.PKCS1WithSHA256,
66 | xtls.ECDSAWithP384AndSHA384,
67 | xtls.ECDSAWithSHA1,
68 | xtls.PSSWithSHA384,
69 | xtls.PSSWithSHA384,
70 | xtls.PKCS1WithSHA384,
71 | xtls.PSSWithSHA512,
72 | xtls.PKCS1WithSHA512,
73 | xtls.PKCS1WithSHA1}},
74 | &xtls.StatusRequestExtension{},
75 | &xtls.NPNExtension{},
76 | &xtls.SCTExtension{},
77 | &xtls.ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
78 | &xtls.SupportedPointsExtension{SupportedPoints: []byte{1}}, // uncompressed
79 | &xtls.SupportedCurvesExtension{
80 | Curves: []xtls.CurveID{
81 | xtls.X25519,
82 | xtls.CurveP256,
83 | xtls.CurveP384,
84 | xtls.CurveP521,
85 | },
86 | },
87 | },
88 | }
89 | // 定义hellomsg的加密套件等信息
90 | err = xtlsConn.ApplyPreset(clientHelloSpec)
91 | if err != nil {
92 | return nil, err
93 | }
94 | // 握手
95 | err = xtlsConn.Handshake()
96 | if err != nil {
97 | return nil, err
98 | }
99 | fmt.Println("当前请求使用协议:", xtlsConn.HandshakeState.ServerHello.AlpnProtocol)
100 | return xtlsConn, err
101 | }
102 | c := http.Client{
103 | Transport: tr,
104 | }
105 | resp, err := c.Get("https://ja3er.com/json")
106 | if err != nil {
107 | fmt.Println(err)
108 | return
109 | }
110 | bts, err := ioutil.ReadAll(resp.Body)
111 | resp.Body.Close()
112 | fmt.Println(string(bts), err)
113 |
114 | // 判断是否支持http2
115 | // resp, err = c.Get("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/newzhidao-da1cf444b0.png")
116 | // if err != nil {
117 | // fmt.Println("req http2 err:", err)
118 | // return
119 | // }
120 | // io.CopyN(io.Discard, resp.Body, 2<<10)
121 | // resp.Body.Close()
122 | // fmt.Println(resp.StatusCode)
123 |
124 | // http 2的实验
125 | con, err := tr.DialTLSContext(context.Background(), "tcp", "dss0.bdstatic.com:443")
126 | if err != nil {
127 | fmt.Println("DialTLSContext", err)
128 | return
129 | }
130 | tr2 := http2.Transport{}
131 | h2Con, err := tr2.NewClientConn(con)
132 | if err != nil {
133 | fmt.Println("NewClientConn", err)
134 | return
135 | }
136 | req, _ := http.NewRequest("GET", "https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/newzhidao-da1cf444b0.png", nil)
137 | resp2, err := h2Con.RoundTrip(req)
138 | if err != nil {
139 | fmt.Println("RoundTrip", err)
140 | return
141 | }
142 | io.CopyN(io.Discard, resp2.Body, 2<<10)
143 | resp2.Body.Close()
144 | fmt.Println("响应code: ", resp2.StatusCode)
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/http2/request-example/README.md:
--------------------------------------------------------------------------------
1 | **推荐执行命令:**
2 | ```shell
3 | GODEBUG=http2debug=2 go run main.go
4 | ```
--------------------------------------------------------------------------------
/http2/request-example/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "time"
6 | )
7 |
8 | func main() {
9 | http.Get("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/baiduyun@2x-e0be79e69e.png")
10 | time.Sleep(time.Second * 3)
11 | }
12 |
--------------------------------------------------------------------------------
/http2/server-push/ca.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICxzCCAa+gAwIBAgIJAJ7iKjZY9WQHMA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
3 | BAMMBlhTSlpIUDAeFw0yMDEwMTcxNjA1MjlaFw0yMTEwMTcxNjA1MjlaMBExDzAN
4 | BgNVBAMMBlhTSlpIUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTW
5 | aRyjCfktLwn1OV0mOxYyb5iHMGrg3Fe3fwo6yus/k7ZV3MHZH8Z9AWc0KD9sDb2p
6 | oQ4mig3R8a0+wOneAWwbOlc7ny439q0tN7MCVu6R4ziRgMWhveVhtNKSBGl6lX/P
7 | iFJZy4C+JfEr/XCSrHGU7rUhRc6xPFsn65wriUcKwRH2ht0fjyCRwqqBj6lnzWCX
8 | zdxJWghfT5+AjUb9O8IEXvhOGccpaboFTH6cjTOWGLima4b5QegP2HNwiSJ9Dhzp
9 | jSyliN4KtdJbKte0hlDKq1XySpl5G8WW1K8g50NrzhQBcl6g+u4Qn4AGAzMzgNcU
10 | Mo7kLAacZl6eDAqT4F0CAwEAAaMiMCAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCQYD
11 | VR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAJjorudFp47lHL002Sm41n9wMgdwq
12 | EgMh6rnDX/BWvLR5OMUdvAEnnoybbSvIOcDb8YeGXUTm4ii9xZcrk1FvsKLcgfnc
13 | qGiJIX/eqmsttIoF7+4NjiMKDk1Ic7jgffMb/FhJtL6wPFFHvBSAKz6ugkoDRpal
14 | /Gct3fLsAGbonvGf1RqqitljqqHB34H8oG9wE1o1HcRSlrTJKE1InHucrfAAr2Ep
15 | fS7qUnMKYP6xXjFY4Ui00Yf8hE6s5176n642ouq/QriBTrhndFMy1V8DCKUowNNV
16 | jVHJAVNDfDtiu6N7B1WYTanLQAIGAbuZW3EHyj1Z5j7OwGJakvEx+ESw0g==
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/http2/server-push/ca.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAxNZpHKMJ+S0vCfU5XSY7FjJvmIcwauDcV7d/CjrK6z+TtlXc
3 | wdkfxn0BZzQoP2wNvamhDiaKDdHxrT7A6d4BbBs6VzufLjf2rS03swJW7pHjOJGA
4 | xaG95WG00pIEaXqVf8+IUlnLgL4l8Sv9cJKscZTutSFFzrE8WyfrnCuJRwrBEfaG
5 | 3R+PIJHCqoGPqWfNYJfN3ElaCF9Pn4CNRv07wgRe+E4ZxylpugVMfpyNM5YYuKZr
6 | hvlB6A/Yc3CJIn0OHOmNLKWI3gq10lsq17SGUMqrVfJKmXkbxZbUryDnQ2vOFAFy
7 | XqD67hCfgAYDMzOA1xQyjuQsBpxmXp4MCpPgXQIDAQABAoIBAE/GWilqBoO/hT3y
8 | 7gHLmczgOgxGViAq7AJ88vbxZwY66SHP4L2Lwu4OAcCTCfDSWStSEV0Lz43UVa+S
9 | LFtcR5VJ37Y1CsmPkuES320keJkN9Voa1mbCq5TIqaFh3nnlXavEL4q4q9qMthHt
10 | czTprQwHgUtVpdYkTMLhBgNwPZ3VjrjDslcTqE6brw1mGvCYDGZ+xvLcrb5BvF4I
11 | ZjEiWJUyHP82dQEIW/4oOyKblRBrbsCbAs188v2qsE2cIaJHYGR23VESDFymD3xK
12 | DR0bB0Tcll3D0pxtIyBF8vsVJUzb89vV9Xc9x+bmr4ngwOPDN8/7NALwLGzgH4sc
13 | NPcgIaECgYEA7SxjaNsQPmYTsmMnQZrKwclffc9i8u/A6xfvj4t9FdQC2mrBWPjg
14 | eOuTVlNfW6uUB13HLBq/Xik3Hz2FDoASwJc98bLzLhhaI8iZLapPM5w8/+7cA5HM
15 | OqLINbo8j4NepUak4d4kU8T/bhKLUfZGBtuhwbvilcsDCQHG0Aj1nwkCgYEA1HZb
16 | BZ2wDrHWYbEVCqaFZyEGbkd8ChkOtc0PWvUfRI3+QhqmCDNnw2pK5SsvFhnZMMjk
17 | 8KKnx5iWBwlAlPi+kpw4oqz81Zg46TjJdt4cVFXPtU6uaaXhBr/3fAIazfPzXFR7
18 | LCWp83qK8rdVe0TPhmxWyfAGZwZEA7S5ZNIjt7UCgYEA2M5b7W1bsv7TAJ4dM56R
19 | vIYdsb9Tv6olW4Mc7cZgSQTuusUeC/wuDruiiyZZpE37WqSCPrIQv73Dct5k9HVl
20 | LwLSkFC6dieytsVYKWNnVVF8faTXILg1zmAhzuN5GuPHMCSc8xCDesQ5j2CKVRlg
21 | uEIr4xKitbXIB4LFQEUAaykCgYBfHCSfHPoleeL4lKdQvz7U7enNEF8svg7hv8xx
22 | 8W1v6Qi7WuacoTaAOmMQuAY6JJQfzK8AMjBdn6b5u2CXz8qwIxMPb9U3YQ+JCAzY
23 | E5InBssW5QQa81ELDoChmOea7uwwlvkUyD+OaXsuMHgp2KH2ESXA/JxBHoLwDcU4
24 | pwGqSQKBgQCtFi7eNcbV6PqTUC7jSBOL7ZtJdHPXXqvvXMTYKR6RBMq3lTgUDJCh
25 | f9IMM5tkNPVaX+o9xPXAgJX0Z9IbgIV6jMvE7UktOdPtaDkYLdcj/AVRGwRyyKwh
26 | Gu+JiWVCaAY3Oo4j/BW+dzssmTJTVPK3D7nC8Tupo3CjRlqcF6xsrg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/http2/server-push/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func main() {
11 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
12 | if r.URL.Path != "/" {
13 | http.NotFound(w, r)
14 | return
15 | }
16 | pusher, ok := w.(http.Pusher)
17 | if ok {
18 | // 主动推送服务资源
19 | if err := pusher.Push("/static/app.js", nil); err != nil {
20 | log.Printf("Failed to push: %v", err)
21 | }
22 | if err := pusher.Push("/static/style.css", nil); err != nil {
23 | log.Printf("Failed to push: %v", err)
24 | }
25 | }
26 | fmt.Fprintf(w, `
27 |
28 | "Gopher指北
29 |
30 |
31 |
32 | Hello "Gopher指北
33 |
34 |
35 |
36 | `)
37 | })
38 | http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
39 | // http.ListenAndServe(":8080", nil)
40 | // http.ListenAndServeTLS(":8080", "ca.crt", "ca.key", nil)
41 | server := &http.Server{Addr: ":8080", Handler: nil}
42 | server.TLSConfig = new(tls.Config)
43 | server.TLSConfig.PreferServerCipherSuites = true
44 | server.TLSConfig.NextProtos = append(server.TLSConfig.NextProtos, "h2", "http/1.1")
45 | // 如果支持的tls版本小于VersionTLS12,则h2不能放在server.TLSConfig.NextProtos里
46 | server.TLSConfig.MaxVersion = tls.VersionTLS12
47 | server.ListenAndServeTLS("ca.crt", "ca.key")
48 | }
49 |
--------------------------------------------------------------------------------
/http2/server-push/static/app.js:
--------------------------------------------------------------------------------
1 |
2 | document.getElementById("content").innerHTML = '"Gopher指北" from js'
--------------------------------------------------------------------------------
/http2/server-push/static/style.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | margin: 20px;
4 | font-family: Arial, sans-serif;
5 | font-size: 16px;
6 | background-color: #fff;
7 | line-height: 1.3em;
8 | }
--------------------------------------------------------------------------------
/http2/tls/client.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICyTCCAbGgAwIBAgIJANK2lGlkWdmIMA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
3 | BAMMBlhTSlpIUDAeFw0yMDExMDgxMjM2MDFaFw0yMTExMDgxMjM2MDFaMBMxETAP
4 | BgNVBAMMCFhTSlpIUC5DMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
5 | tunvaqOkz4Rg7OfuqoDw5Ia8s0desvFGatRfmjqEuuKYxiZy1fFi55crYMOh1hNP
6 | +/EoBh53ShdttNSI7waW9uciwMLInSIXfzsSLEigeG8NBWe18UdtkNlfttWNwCWb
7 | ul/RuunvXB2fZ1MteXAP/WSKouVzTJVUl7kGtYBhXKKQQRVUGjnzu3PuJAy8+QDQ
8 | my5NQj+Ou9SlOlx77GAItziNB9/dtXo0xZr1Y/+6iJBzly3oI9ia+3EhtxnyX4f4
9 | 2FR3z5DttRovGb9n+xyZXaHQDKV3aZrJPIfXlsJ8MuT1G5YjCqwdM/gf6KK7H0Dz
10 | 8wGQI3PUzoZjMfj/FPjZUwIDAQABoyIwIDATBgNVHSUEDDAKBggrBgEFBQcDAjAJ
11 | BgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBZ0MJNI0xgDEuB7YeI1pwLDGuG
12 | qNkGcBeQDQ6+JPPXYLoVeD24l8Q+xkDMo1tdY2s1k05BzdRkBoY+LHB4+vIpiHHG
13 | RaRyxP4JtvH6ADvRytMZuoCVtCW6r1FW1yAOe9t+peb7wRlmlF2dozO8b4MbETle
14 | ORV8Xl8LbTBy8RKopY9ufedWr6E2pwNthxrMQby+fN7YpX+yIckBXm46F6Ei3T6L
15 | fnC9JChxvARgH+wCGkx92jUvzNr8vUg3e7PpdAw73hl3PjqBcQR8bWIe+u91iKdG
16 | BVRqduPOIQu+xd6GvFfPBZrhi3PBWxTQQ7Vx1VV2oo8C9g+/bDACQI7m99Ux
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/http2/tls/client.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAtunvaqOkz4Rg7OfuqoDw5Ia8s0desvFGatRfmjqEuuKYxiZy
3 | 1fFi55crYMOh1hNP+/EoBh53ShdttNSI7waW9uciwMLInSIXfzsSLEigeG8NBWe1
4 | 8UdtkNlfttWNwCWbul/RuunvXB2fZ1MteXAP/WSKouVzTJVUl7kGtYBhXKKQQRVU
5 | Gjnzu3PuJAy8+QDQmy5NQj+Ou9SlOlx77GAItziNB9/dtXo0xZr1Y/+6iJBzly3o
6 | I9ia+3EhtxnyX4f42FR3z5DttRovGb9n+xyZXaHQDKV3aZrJPIfXlsJ8MuT1G5Yj
7 | CqwdM/gf6KK7H0Dz8wGQI3PUzoZjMfj/FPjZUwIDAQABAoIBADfhpGlZ8WIMuWfn
8 | O70Pg4jtuPy0kzPsDm1Y0JRXyHEoBTCUUoUWJ/dE8dWwLuMuJ0N7W5Ty/dK+8Z9L
9 | R0JvKvPnjXCCkbOf1LnkHBs3XP8uPjYmhyldfxW/s0QyXgoT802vNG38RkpIKojw
10 | mnX9TIVHkCtQGjeNb7iiqHAO9q/L3jPjR9cqvfbDYj8oEfSe6udisjOvqgdCWdA2
11 | /ldjDdZXBrIJeeV+Oe6/kl9IEFPCdIC1D/ehyp2nkzhWLcmNIEkjESbaHVxegNar
12 | GZLnKom0jmMnXEo61vGMqOycH4SKbdw7MaFAQuKp/kyB9UVGFoOPnXp2LEHsMg4a
13 | reknc+ECgYEA3HjXk4k/QG2aBLdJ/FgBS8vHfp9g1P3yicBhFSkHMm02HfjMP/BV
14 | YThaFgY6E3rsA3Y9UypX22385cTbx0drQl0gU6zNho9WMlUtvqWL6hsgS/0iV8+7
15 | Dptwek2ENUkzykTT5JqjKSCl7KTJ+GG7Fo9rABzANNdTWeZNdrys2/sCgYEA1GOz
16 | ALHiAlPX54ADJ14q65ru5+wB3W2iRCdzh+zH+3p1CKFE0UJrO6r/9PAj0CzUe/Qe
17 | Kv7z67jl8Otls2vZLfmqM+ooE5+kkdY9bLQLNOMiabMfzzVWIyl/J5GmQCdFEeXb
18 | txsJFFxk7p+sCdB62JYDo4/mMmORMTWeIfubYIkCgYA2U5yjYT1xzdAW+2dCxBjF
19 | qZgl7nX45f6ezQXfJfX9CgY8ynLiCoGvbChepvgmlrKTg85GsPdnPaoEoEaby1B1
20 | 0ObHV5xpXOabjnuwL7DTZg3GS8DrrGdmiQzlRjaevsQBQoaIHUa5Oq9IKa8PAl4M
21 | iBiQtYTzQF/sliBecs2RgwKBgAx2xVx3E/JbBUKaqpS23AHzl62YlgtukaU6Q3do
22 | l9vUNeYJwMYfBbf8swSmyxM+bkHP861GRP5CXYwj5FYBMD+YdTqStUNhjQDZ98TX
23 | VAkIg058qpM4aBOsLcAetgjxxQXl3V0DgybkvS+bwzbYOz1WoGQK39F5Ml4W7W7F
24 | GzsxAoGBAM9c8evER5cRjG3NcU4STvhYZV3ik9IaGOdoZJaFIEji8Wl2g1PPy8cA
25 | mpnUStiaacu7brVb1sMBey9waoqF2gx7y7YrOPbX1ladlUAhajXo7osTZMeExhh/
26 | iuXmr6Mfpxa2g0ZhD5udyM6wzu12tbsVhDL+dThgmu39ySFcWWdd
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/http2/tls/handsh/addr.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | // TCPAddr 简单实现net.Addr接口
4 | type TCPAddr string
5 |
6 | // Network ..
7 | func (addr TCPAddr) Network() string {
8 | return "tcp"
9 | }
10 |
11 | // String ..
12 | func (addr TCPAddr) String() string {
13 | return string(addr)
14 | }
15 |
--------------------------------------------------------------------------------
/http2/tls/handsh/alert.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import "strconv"
4 |
5 | const (
6 | // alert level
7 | alertLevelWarning = 1
8 | alertLevelError = 2
9 | )
10 |
11 | const (
12 | alertCloseNotify alert = 0
13 | alertUnexpectedMessage alert = 10
14 | alertBadRecordMAC alert = 20
15 | alertDecryptionFailed alert = 21
16 | alertRecordOverflow alert = 22
17 | alertDecompressionFailure alert = 30
18 | alertHandshakeFailure alert = 40
19 | alertBadCertificate alert = 42
20 | alertUnsupportedCertificate alert = 43
21 | alertCertificateRevoked alert = 44
22 | alertCertificateExpired alert = 45
23 | alertCertificateUnknown alert = 46
24 | alertIllegalParameter alert = 47
25 | alertUnknownCA alert = 48
26 | alertAccessDenied alert = 49
27 | alertDecodeError alert = 50
28 | alertDecryptError alert = 51
29 | alertExportRestriction alert = 60
30 | alertProtocolVersion alert = 70
31 | alertInsufficientSecurity alert = 71
32 | alertInternalError alert = 80
33 | alertInappropriateFallback alert = 86
34 | alertUserCanceled alert = 90
35 | alertNoRenegotiation alert = 100
36 | alertMissingExtension alert = 109
37 | alertUnsupportedExtension alert = 110
38 | alertCertificateUnobtainable alert = 111
39 | alertUnrecognizedName alert = 112
40 | alertBadCertificateStatusResponse alert = 113
41 | alertBadCertificateHashValue alert = 114
42 | alertUnknownPSKIdentity alert = 115
43 | alertCertificateRequired alert = 116
44 | alertNoApplicationProtocol alert = 120
45 | )
46 |
47 | var alertText = map[alert]string{
48 | alertCloseNotify: "close notify",
49 | alertUnexpectedMessage: "unexpected message",
50 | alertBadRecordMAC: "bad record MAC",
51 | alertDecryptionFailed: "decryption failed",
52 | alertRecordOverflow: "record overflow",
53 | alertDecompressionFailure: "decompression failure",
54 | alertHandshakeFailure: "handshake failure",
55 | alertBadCertificate: "bad certificate",
56 | alertUnsupportedCertificate: "unsupported certificate",
57 | alertCertificateRevoked: "revoked certificate",
58 | alertCertificateExpired: "expired certificate",
59 | alertCertificateUnknown: "unknown certificate",
60 | alertIllegalParameter: "illegal parameter",
61 | alertUnknownCA: "unknown certificate authority",
62 | alertAccessDenied: "access denied",
63 | alertDecodeError: "error decoding message",
64 | alertDecryptError: "error decrypting message",
65 | alertExportRestriction: "export restriction",
66 | alertProtocolVersion: "protocol version not supported",
67 | alertInsufficientSecurity: "insufficient security level",
68 | alertInternalError: "internal error",
69 | alertInappropriateFallback: "inappropriate fallback",
70 | alertUserCanceled: "user canceled",
71 | alertNoRenegotiation: "no renegotiation",
72 | alertMissingExtension: "missing extension",
73 | alertUnsupportedExtension: "unsupported extension",
74 | alertCertificateUnobtainable: "certificate unobtainable",
75 | alertUnrecognizedName: "unrecognized name",
76 | alertBadCertificateStatusResponse: "bad certificate status response",
77 | alertBadCertificateHashValue: "bad certificate hash value",
78 | alertUnknownPSKIdentity: "unknown PSK identity",
79 | alertCertificateRequired: "certificate required",
80 | alertNoApplicationProtocol: "no application protocol",
81 | }
82 |
83 | type alert uint8
84 |
85 | func (e alert) String() string {
86 | s, ok := alertText[e]
87 | if ok {
88 | return "tls: " + s
89 | }
90 | return "tls: alert(" + strconv.Itoa(int(e)) + ")"
91 | }
92 |
93 | func (e alert) Error() string {
94 | return e.String()
95 | }
96 |
--------------------------------------------------------------------------------
/http2/tls/handsh/auth.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto"
5 | "crypto/ecdsa"
6 | "crypto/ed25519"
7 | "crypto/rsa"
8 | "crypto/tls"
9 | "errors"
10 | "fmt"
11 | )
12 |
13 | func typeAndHashFromSignatureScheme(signatureAlgorithm tls.SignatureScheme) (sigType uint8, hash crypto.Hash, err error) {
14 | switch signatureAlgorithm {
15 | case tls.PKCS1WithSHA1, tls.PKCS1WithSHA256, tls.PKCS1WithSHA384, tls.PKCS1WithSHA512:
16 | sigType = signaturePKCS1v15
17 | case tls.PSSWithSHA256, tls.PSSWithSHA384, tls.PSSWithSHA512:
18 | sigType = signatureRSAPSS
19 | case tls.ECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512:
20 | sigType = signatureECDSA
21 | case tls.Ed25519:
22 | sigType = signatureEd25519
23 | default:
24 | return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
25 | }
26 | switch signatureAlgorithm {
27 | case tls.PKCS1WithSHA1, tls.ECDSAWithSHA1:
28 | hash = crypto.SHA1
29 | case tls.PKCS1WithSHA256, tls.PSSWithSHA256, tls.ECDSAWithP256AndSHA256:
30 | hash = crypto.SHA256
31 | case tls.PKCS1WithSHA384, tls.PSSWithSHA384, tls.ECDSAWithP384AndSHA384:
32 | hash = crypto.SHA384
33 | case tls.PKCS1WithSHA512, tls.PSSWithSHA512, tls.ECDSAWithP521AndSHA512:
34 | hash = crypto.SHA512
35 | case tls.Ed25519:
36 | var d crypto.Hash = 0
37 | hash = d
38 | default:
39 | return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
40 | }
41 | return sigType, hash, nil
42 | }
43 |
44 | // legacyTypeAndHashFromPublicKey returns the fixed signature type and crypto.Hash for
45 | // a given public key used with TLS 1.0 and 1.1, before the introduction of
46 | // signature algorithm negotiation.
47 | func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash crypto.Hash, err error) {
48 | switch pub.(type) {
49 | case *rsa.PublicKey:
50 | return signaturePKCS1v15, crypto.MD5SHA1, nil
51 | case *ecdsa.PublicKey:
52 | return signatureECDSA, crypto.SHA1, nil
53 | case ed25519.PublicKey:
54 | // RFC 8422 specifies support for Ed25519 in TLS 1.0 and 1.1,
55 | // but it requires holding on to a handshake transcript to do a
56 | // full signature, and not even OpenSSL bothers with the
57 | // complexity, so we can't even test it properly.
58 | return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2")
59 | default:
60 | return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub)
61 | }
62 | }
63 |
64 | // verifyHandshakeSignature verifies a signature against pre-hashed
65 | // (if required) handshake contents.
66 | func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, signed, sig []byte) error {
67 | switch sigType {
68 | case signatureECDSA:
69 | pubKey, ok := pubkey.(*ecdsa.PublicKey)
70 | if !ok {
71 | return fmt.Errorf("expected an ECDSA public key, got %T", pubkey)
72 | }
73 | if !ecdsa.VerifyASN1(pubKey, signed, sig) {
74 | return errors.New("ECDSA verification failure")
75 | }
76 | case signatureEd25519:
77 | pubKey, ok := pubkey.(ed25519.PublicKey)
78 | if !ok {
79 | return fmt.Errorf("expected an Ed25519 public key, got %T", pubkey)
80 | }
81 | if !ed25519.Verify(pubKey, signed, sig) {
82 | return errors.New("Ed25519 verification failure")
83 | }
84 | case signaturePKCS1v15:
85 | pubKey, ok := pubkey.(*rsa.PublicKey)
86 | if !ok {
87 | return fmt.Errorf("expected an RSA public key, got %T", pubkey)
88 | }
89 | if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, signed, sig); err != nil {
90 | return err
91 | }
92 | case signatureRSAPSS:
93 | pubKey, ok := pubkey.(*rsa.PublicKey)
94 | if !ok {
95 | return fmt.Errorf("expected an RSA public key, got %T", pubkey)
96 | }
97 | signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}
98 | if err := rsa.VerifyPSS(pubKey, hashFunc, signed, sig, signOpts); err != nil {
99 | return err
100 | }
101 | default:
102 | return errors.New("internal error: unknown signature type")
103 | }
104 | return nil
105 | }
106 |
--------------------------------------------------------------------------------
/http2/tls/handsh/chipher_suites.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/cipher"
6 | "crypto/hmac"
7 | "crypto/sha1"
8 | "crypto/tls"
9 | "crypto/x509"
10 | "hash"
11 | )
12 |
13 | const (
14 | // suiteECDHE indicates that the cipher suite involves elliptic curve
15 | // Diffie-Hellman. This means that it should only be selected when the
16 | // client indicates that it supports ECC with a curve and point format
17 | // that we're happy with.
18 | suiteECDHE = 1 << iota
19 | // suiteECSign indicates that the cipher suite involves an ECDSA or
20 | // EdDSA signature and therefore may only be selected when the server's
21 | // certificate is ECDSA or EdDSA. If this is not set then the cipher suite
22 | // is RSA based.
23 | suiteECSign
24 | // suiteTLS12 indicates that the cipher suite should only be advertised
25 | // and accepted when using TLS 1.2.
26 | suiteTLS12
27 | // suiteSHA384 indicates that the cipher suite uses SHA384 as the
28 | // handshake hash.
29 | suiteSHA384
30 | // suiteDefaultOff indicates that this cipher suite is not included by
31 | // default.
32 | suiteDefaultOff
33 | )
34 |
35 | // 需要实现的密钥交换算法太多, 笔者目前只实现本例中的
36 | var cipherSuites = []*cipherSuite{
37 | // Ciphersuite order is chosen so that ECDHE comes before plain RSA and
38 | // // AEADs are the top preference.
39 | // {tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
40 | // {tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
41 | {tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
42 | // {tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM},
43 | // {tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
44 | // {tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
45 | // {tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
46 | {tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
47 | // {tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
48 | // {tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil},
49 | // {tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
50 | // {tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil},
51 | // {tls.TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
52 | // {tls.TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
53 | // {tls.TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
54 | // {tls.TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
55 | // {tls.TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
56 | // {tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
57 | // {tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
58 |
59 | // // RC4-based cipher suites are disabled by default.
60 | // {tls.TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
61 | // {tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
62 | // {tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteDefaultOff, cipherRC4, macSHA1, nil},
63 | }
64 |
65 | type prefixNonceAEAD struct {
66 | // nonce contains the fixed part of the nonce in the first four bytes.
67 | nonce [aeadNonceLength]byte
68 | aead cipher.AEAD
69 | }
70 |
71 | func (f *prefixNonceAEAD) NonceSize() int { return aeadNonceLength - noncePrefixLength }
72 | func (f *prefixNonceAEAD) Overhead() int { return f.aead.Overhead() }
73 | func (f *prefixNonceAEAD) explicitNonceLen() int { return f.NonceSize() }
74 |
75 | func (f *prefixNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
76 | copy(f.nonce[4:], nonce)
77 | return f.aead.Seal(out, f.nonce[:], plaintext, additionalData)
78 | }
79 |
80 | func (f *prefixNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) {
81 | copy(f.nonce[4:], nonce)
82 | return f.aead.Open(out, f.nonce[:], ciphertext, additionalData)
83 | }
84 |
85 | // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3.
86 | type tls10MAC struct {
87 | h hash.Hash
88 | buf []byte
89 | }
90 |
91 | func (s tls10MAC) Size() int {
92 | return s.h.Size()
93 | }
94 |
95 | // MAC is guaranteed to take constant time, as long as
96 | // len(seq)+len(header)+len(data)+len(extra) is constant. extra is not fed into
97 | // the MAC, but is only provided to make the timing profile constant.
98 | func (s tls10MAC) MAC(seq, header, data, extra []byte) []byte {
99 | s.h.Reset()
100 | s.h.Write(seq)
101 | s.h.Write(header)
102 | s.h.Write(data)
103 | res := s.h.Sum(s.buf[:0])
104 | if extra != nil {
105 | s.h.Write(extra)
106 | }
107 | return res
108 | }
109 |
110 | type constantTimeHash interface {
111 | hash.Hash
112 | ConstantTimeSum(b []byte) []byte
113 | }
114 |
115 | // cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces
116 | // with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC.
117 | type cthWrapper struct {
118 | h constantTimeHash
119 | }
120 |
121 | func (c *cthWrapper) Size() int { return c.h.Size() }
122 | func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() }
123 | func (c *cthWrapper) Reset() { c.h.Reset() }
124 | func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) }
125 | func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) }
126 |
127 | func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
128 | return func() hash.Hash {
129 | return &cthWrapper{h().(constantTimeHash)}
130 | }
131 | }
132 |
133 | func aeadAESGCM(key, noncePrefix []byte) aead {
134 | if len(noncePrefix) != noncePrefixLength {
135 | panic("tls: internal error: wrong nonce length")
136 | }
137 | aes, err := aes.NewCipher(key)
138 | if err != nil {
139 | panic(err)
140 | }
141 | aead, err := cipher.NewGCM(aes)
142 | if err != nil {
143 | panic(err)
144 | }
145 |
146 | ret := &prefixNonceAEAD{aead: aead}
147 | copy(ret.nonce[:], noncePrefix)
148 | return ret
149 | }
150 |
151 | func ecdheRSAKA(version uint16) keyAgreement {
152 | return &ecdheKeyAgreement{
153 | isRSA: true,
154 | version: version,
155 | }
156 | }
157 |
158 | func cipherAES(key, iv []byte, isRead bool) interface{} {
159 | block, _ := aes.NewCipher(key)
160 | if isRead {
161 | return cipher.NewCBCDecrypter(block, iv)
162 | }
163 | return cipher.NewCBCEncrypter(block, iv)
164 | }
165 |
166 | // macSHA1 returns a macFunction for the given protocol version.
167 | func macSHA1(version uint16, key []byte) macFunction {
168 | return tls10MAC{h: hmac.New(newConstantTimeHash(sha1.New), key)}
169 | }
170 |
171 | // a keyAgreement implements the client and server side of a TLS key agreement
172 | // protocol by generating and processing key exchange messages.
173 | type keyAgreement interface {
174 | // On the server side, the first two methods are called in order.
175 |
176 | // In the case that the key agreement protocol doesn't use a
177 | // ServerKeyExchange message, generateServerKeyExchange can return nil,
178 | // nil.
179 | generateServerKeyExchange(*tls.Config, *tls.Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
180 | processClientKeyExchange(*tls.Config, *tls.Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
181 |
182 | // On the client side, the next two methods are called in order.
183 |
184 | // This method may not be called if the server doesn't send a
185 | // ServerKeyExchange message.
186 | processServerKeyExchange(*tls.Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
187 | generateClientKeyExchange(*tls.Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
188 | }
189 |
190 | type cipherSuite struct {
191 | id uint16
192 | // the lengths, in bytes, of the key material needed for each component.
193 | keyLen int
194 | macLen int
195 | ivLen int
196 | ka func(version uint16) keyAgreement
197 | // flags is a bitmask of the suite* values, above.
198 | flags int
199 | cipher func(key, iv []byte, isRead bool) interface{}
200 | mac func(version uint16, macKey []byte) macFunction
201 | aead func(key, fixedNonce []byte) aead
202 | }
203 |
204 | func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
205 | for _, id := range have {
206 | if id == want {
207 | return cipherSuiteByID(id)
208 | }
209 | }
210 | return nil
211 | }
212 |
213 | func cipherSuiteByID(id uint16) *cipherSuite {
214 | for _, cipherSuite := range cipherSuites {
215 | if cipherSuite.id == id {
216 | return cipherSuite
217 | }
218 | }
219 | return nil
220 | }
221 |
--------------------------------------------------------------------------------
/http2/tls/handsh/cipher_suites_tls13.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto"
5 | "crypto/aes"
6 | "crypto/cipher"
7 | "crypto/tls"
8 | "hash"
9 |
10 | "golang.org/x/crypto/chacha20poly1305"
11 | "golang.org/x/crypto/cryptobyte"
12 | "golang.org/x/crypto/hkdf"
13 | )
14 |
15 | const (
16 | aeadNonceLength = 12
17 | noncePrefixLength = 4
18 | )
19 |
20 | var cipherSuitesTLS13 = []*cipherSuiteTLS13{
21 | {tls.TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256},
22 | {tls.TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256},
23 | {tls.TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384},
24 | }
25 |
26 | type cipherSuiteTLS13 struct {
27 | id uint16
28 | keyLen int
29 | aead func(key, fixedNonce []byte) aead
30 | hash crypto.Hash
31 | }
32 |
33 | // trafficKey generates traffic keys according to RFC 8446, Section 7.3.
34 | func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
35 | key = c.expandLabel(trafficSecret, "key", nil, c.keyLen)
36 | iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength)
37 | return
38 | }
39 |
40 | // expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
41 | func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
42 | var hkdfLabel cryptobyte.Builder
43 | hkdfLabel.AddUint16(uint16(length))
44 | hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
45 | b.AddBytes([]byte("tls13 "))
46 | b.AddBytes([]byte(label))
47 | })
48 | hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
49 | b.AddBytes(context)
50 | })
51 | out := make([]byte, length)
52 | n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
53 | if err != nil || n != length {
54 | panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
55 | }
56 | return out
57 | }
58 |
59 | // extract implements HKDF-Extract with the cipher suite hash.
60 | func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
61 | if newSecret == nil {
62 | newSecret = make([]byte, c.hash.Size())
63 | }
64 | return hkdf.Extract(c.hash.New, newSecret, currentSecret)
65 | }
66 |
67 | // deriveSecret implements Derive-Secret from RFC 8446, Section 7.1.
68 | func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte {
69 | if transcript == nil {
70 | transcript = c.hash.New()
71 | }
72 | return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size())
73 | }
74 |
75 | // xoredNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce
76 | // before each call.
77 | type xorNonceAEAD struct {
78 | nonceMask [aeadNonceLength]byte
79 | aead cipher.AEAD
80 | }
81 |
82 | func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number
83 | func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() }
84 | func (f *xorNonceAEAD) explicitNonceLen() int { return 0 }
85 |
86 | func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
87 | for i, b := range nonce {
88 | f.nonceMask[4+i] ^= b
89 | }
90 | result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData)
91 | for i, b := range nonce {
92 | f.nonceMask[4+i] ^= b
93 | }
94 |
95 | return result
96 | }
97 |
98 | func (f *xorNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) {
99 | for i, b := range nonce {
100 | f.nonceMask[4+i] ^= b
101 | }
102 | result, err := f.aead.Open(out, f.nonceMask[:], ciphertext, additionalData)
103 | for i, b := range nonce {
104 | f.nonceMask[4+i] ^= b
105 | }
106 |
107 | return result, err
108 | }
109 |
110 | func mutualCipherSuiteTLS13(have []uint16, want uint16) *cipherSuiteTLS13 {
111 | for _, id := range have {
112 | if id == want {
113 | return cipherSuiteTLS13ByID(id)
114 | }
115 | }
116 | return nil
117 | }
118 |
119 | func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13 {
120 | for _, cipherSuite := range cipherSuitesTLS13 {
121 | if cipherSuite.id == id {
122 | return cipherSuite
123 | }
124 | }
125 | return nil
126 | }
127 |
128 | func aeadAESGCMTLS13(key, nonceMask []byte) aead {
129 | if len(nonceMask) != aeadNonceLength {
130 | panic("tls: internal error: wrong nonce length")
131 | }
132 | aes, err := aes.NewCipher(key)
133 | if err != nil {
134 | panic(err)
135 | }
136 | aead, err := cipher.NewGCM(aes)
137 | if err != nil {
138 | panic(err)
139 | }
140 |
141 | ret := &xorNonceAEAD{aead: aead}
142 | copy(ret.nonceMask[:], nonceMask)
143 | return ret
144 | }
145 |
146 | func aeadChaCha20Poly1305(key, nonceMask []byte) aead {
147 | if len(nonceMask) != aeadNonceLength {
148 | panic("tls: internal error: wrong nonce length")
149 | }
150 | aead, err := chacha20poly1305.New(key)
151 | if err != nil {
152 | panic(err)
153 | }
154 |
155 | ret := &xorNonceAEAD{aead: aead}
156 | copy(ret.nonceMask[:], nonceMask)
157 | return ret
158 | }
159 |
--------------------------------------------------------------------------------
/http2/tls/handsh/common.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto/rand"
5 | "crypto/tls"
6 | "io"
7 |
8 | "golang.org/x/sys/cpu"
9 | )
10 |
11 | const (
12 | maxPlaintext = 16384 // maximum plaintext payload length
13 | maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
14 | maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3
15 | recordHeaderLen = 5 // record header length
16 | maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
17 | maxUselessRecords = 16 // maximum number of consecutive non-advancing records
18 | )
19 |
20 | // TLS extension numbers
21 | const (
22 | extensionServerName uint16 = 0
23 | extensionStatusRequest uint16 = 5
24 | extensionSupportedCurves uint16 = 10 // supported_groups in TLS 1.3, see RFC 8446, Section 4.2.7
25 | extensionSupportedPoints uint16 = 11
26 | extensionSignatureAlgorithms uint16 = 13
27 | extensionALPN uint16 = 16
28 | extensionSCT uint16 = 18
29 | extensionSessionTicket uint16 = 35
30 | extensionPreSharedKey uint16 = 41
31 | extensionEarlyData uint16 = 42
32 | extensionSupportedVersions uint16 = 43
33 | extensionCookie uint16 = 44
34 | extensionPSKModes uint16 = 45
35 | extensionCertificateAuthorities uint16 = 47
36 | extensionSignatureAlgorithmsCert uint16 = 50
37 | extensionKeyShare uint16 = 51
38 | extensionRenegotiationInfo uint16 = 0xff01
39 | )
40 |
41 | // TLS CertificateStatusType (RFC 3546)
42 | const (
43 | statusTypeOCSP uint8 = 1
44 | )
45 |
46 | // TLS signaling cipher suite values
47 | const (
48 | scsvRenegotiation uint16 = 0x00ff
49 | )
50 |
51 | type recordType uint8
52 |
53 | const (
54 | recordTypeChangeCipherSpec recordType = 20
55 | recordTypeAlert recordType = 21
56 | recordTypeHandshake recordType = 22
57 | recordTypeApplicationData recordType = 23
58 | )
59 |
60 | // Signature algorithms (for internal signaling use). Starting at 225 to avoid overlap with
61 | // TLS 1.2 codepoints (RFC 5246, Appendix A.4.1), with which these have nothing to do.
62 | const (
63 | signaturePKCS1v15 uint8 = iota + 225
64 | signatureRSAPSS
65 | signatureECDSA
66 | signatureEd25519
67 | )
68 |
69 | // TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
70 | type keyShare struct {
71 | group tls.CurveID
72 | data []byte
73 | }
74 |
75 | // TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
76 | // session. See RFC 8446, Section 4.2.11.
77 | type pskIdentity struct {
78 | label []byte
79 | obfuscatedTicketAge uint32
80 | }
81 |
82 | func defaultCipherSuitesTLS13() []uint16 {
83 | var (
84 | hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
85 | hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
86 | // Keep in sync with crypto/aes/cipher_s390x.go.
87 | hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
88 |
89 | hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
90 | )
91 | if hasGCMAsm {
92 | // If AES-GCM hardware is provided then prioritise AES-GCM
93 | // cipher suites.
94 | return []uint16{
95 | tls.TLS_AES_128_GCM_SHA256,
96 | tls.TLS_CHACHA20_POLY1305_SHA256,
97 | tls.TLS_AES_256_GCM_SHA384,
98 | }
99 | }
100 | // Without AES-GCM hardware, we put the ChaCha20-Poly1305
101 | // cipher suites first.
102 | return []uint16{
103 | tls.TLS_CHACHA20_POLY1305_SHA256,
104 | tls.TLS_AES_128_GCM_SHA256,
105 | tls.TLS_AES_256_GCM_SHA384,
106 | }
107 | }
108 |
109 | func curvePreferences(c *tls.Config) []tls.CurveID {
110 | if c == nil || len(c.CurvePreferences) == 0 {
111 | return []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521}
112 | }
113 | return c.CurvePreferences
114 | }
115 |
116 | func crand(c *tls.Config) io.Reader {
117 | r := c.Rand
118 | if r == nil {
119 | return rand.Reader
120 | }
121 | return r
122 | }
123 |
124 | func isSupportedSignatureAlgorithm(sigAlg tls.SignatureScheme, supportedSignatureAlgorithms []tls.SignatureScheme) bool {
125 | for _, s := range supportedSignatureAlgorithms {
126 | if s == sigAlg {
127 | return true
128 | }
129 | }
130 | return false
131 | }
132 |
--------------------------------------------------------------------------------
/http2/tls/handsh/conn.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "net"
7 | "time"
8 | )
9 |
10 | // 这里需要注意的是, ”读完一个消息才能写入另外一个消息“这个设计有缺陷
11 | // var m int
12 | // if len(b) > 1 && c.vers == VersionTLS10 {
13 | // if _, ok := c.out.cipher.(cipher.BlockMode); ok {
14 | // n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1])
15 | // if err != nil {
16 | // return n, c.out.setErrorLocked(err)
17 | // }
18 | // m, b = 1, b[1:]
19 | // }
20 | // }
21 |
22 | // n, err := c.writeRecordLocked(recordTypeApplicationData, b)
23 | // 底层针对tls1.0有这样一个逻辑,对于大于一字节的用户数据,会写为两个recordTypeApplicationData消息
24 |
25 | // TCPCon 简单模拟实现底层连接
26 | type TCPCon struct {
27 | Local TCPAddr
28 | Remote TCPAddr
29 | IsClient bool
30 | Wbuf *bytes.Buffer
31 | Rbuf *bytes.Buffer
32 | Wdone chan<- int
33 | Rdone <-chan int
34 | Praser *TLSMsgParser
35 | }
36 |
37 | // Read ..
38 | func (c *TCPCon) Read(b []byte) (n int, err error) {
39 | // 数据为空才等待数据写入, 否则直接读
40 | if c.Rbuf.Len() == 0 {
41 | <-c.Rdone
42 | }
43 | n, err = c.Rbuf.Read(b)
44 | // raw := make([]byte, n)
45 | // copy(raw, b[:n])
46 | // c.Praser.Parse(c.IsClient, raw)
47 | return n, err
48 | }
49 |
50 | // Write ..
51 | func (c *TCPCon) Write(b []byte) (n int, err error) {
52 | // 未写入数据,或者已经读完所有数据才能继续写
53 | log := server
54 | if c.IsClient {
55 | log = client
56 | }
57 | if c.Wbuf.Len() == 0 {
58 | n, err = c.Wbuf.Write(b)
59 | log.Info(fmt.Sprintf("write data len: %d", n))
60 | raw := make([]byte, n)
61 | copy(raw, b[:n])
62 | c.Praser.Parse(!c.IsClient, raw)
63 | c.Wdone <- 1
64 | }
65 | return n, err
66 | }
67 |
68 | // Close ..
69 | func (c *TCPCon) Close() error {
70 | return nil
71 | }
72 |
73 | // LocalAddr ..
74 | func (c *TCPCon) LocalAddr() net.Addr {
75 | return c.Local
76 | }
77 |
78 | // RemoteAddr ..
79 | func (c *TCPCon) RemoteAddr() net.Addr {
80 | return c.Remote
81 | }
82 |
83 | // SetDeadline ..
84 | func (c *TCPCon) SetDeadline(t time.Time) error {
85 | return nil
86 | }
87 |
88 | // SetReadDeadline ..
89 | func (c *TCPCon) SetReadDeadline(t time.Time) error {
90 | return nil
91 | }
92 |
93 | // SetWriteDeadline ..
94 | func (c *TCPCon) SetWriteDeadline(t time.Time) error {
95 | return nil
96 | }
97 |
--------------------------------------------------------------------------------
/http2/tls/handsh/key_agreement.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto"
5 | "crypto/md5"
6 | "crypto/sha1"
7 | "crypto/tls"
8 | "crypto/x509"
9 | "errors"
10 | )
11 |
12 | var (
13 | errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
14 | errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
15 | )
16 |
17 | func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte {
18 | if sigType == signatureEd25519 {
19 | var signed []byte
20 | for _, slice := range slices {
21 | signed = append(signed, slice...)
22 | }
23 | return signed
24 | }
25 | if version >= tls.VersionTLS12 {
26 | h := hashFunc.New()
27 | for _, slice := range slices {
28 | h.Write(slice)
29 | }
30 | digest := h.Sum(nil)
31 | return digest
32 | }
33 | if sigType == signatureECDSA {
34 | return sha1Hash(slices)
35 | }
36 | return md5SHA1Hash(slices)
37 | }
38 |
39 | // sha1Hash calculates a SHA1 hash over the given byte slices.
40 | func sha1Hash(slices [][]byte) []byte {
41 | hsha1 := sha1.New()
42 | for _, slice := range slices {
43 | hsha1.Write(slice)
44 | }
45 | return hsha1.Sum(nil)
46 | }
47 |
48 | // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
49 | // concatenation of an MD5 and SHA1 hash.
50 | func md5SHA1Hash(slices [][]byte) []byte {
51 | md5sha1 := make([]byte, md5.Size+sha1.Size)
52 | hmd5 := md5.New()
53 | for _, slice := range slices {
54 | hmd5.Write(slice)
55 | }
56 | copy(md5sha1, hmd5.Sum(nil))
57 | copy(md5sha1[md5.Size:], sha1Hash(slices))
58 | return md5sha1
59 | }
60 |
61 | // ecdheKeyAgreement
62 | type ecdheKeyAgreement struct {
63 | version uint16
64 | isRSA bool
65 | params ecdheParameters
66 |
67 | // ckx and preMasterSecret are generated in processServerKeyExchange
68 | // and returned in generateClientKeyExchange.
69 | ckx *clientKeyExchangeMsg
70 | preMasterSecret []byte
71 | }
72 |
73 | // 依据client逻辑解析,故忽略此内部逻辑
74 | func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *tls.Config, cert *tls.Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
75 | return nil, nil
76 | }
77 |
78 | func (ka *ecdheKeyAgreement) processServerKeyExchange(config *tls.Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
79 | if len(skx.key) < 4 {
80 | return errServerKeyExchange
81 | }
82 | if skx.key[0] != 3 { // named curve
83 | return errors.New("tls: server selected unsupported curve")
84 | }
85 | curveID := tls.CurveID(skx.key[1])<<8 | tls.CurveID(skx.key[2])
86 |
87 | publicLen := int(skx.key[3])
88 | if publicLen+4 > len(skx.key) {
89 | return errServerKeyExchange
90 | }
91 | serverECDHEParams := skx.key[:4+publicLen]
92 | publicKey := serverECDHEParams[4:]
93 |
94 | sig := skx.key[4+publicLen:]
95 | if len(sig) < 2 {
96 | return errServerKeyExchange
97 | }
98 |
99 | if _, ok := curveForCurveID(curveID); curveID != tls.X25519 && !ok {
100 | return errors.New("tls: server selected unsupported curve")
101 | }
102 |
103 | // 这里改变生成随机数据的逻辑
104 | params, err := generateECDHEParameters(crand(config), curveID)
105 | if err != nil {
106 | return err
107 | }
108 | ka.params = params
109 |
110 | ka.preMasterSecret = params.SharedKey(publicKey)
111 | if ka.preMasterSecret == nil {
112 | return errServerKeyExchange
113 | }
114 |
115 | ourPublicKey := params.PublicKey()
116 | ka.ckx = new(clientKeyExchangeMsg)
117 | ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey))
118 | ka.ckx.ciphertext[0] = byte(len(ourPublicKey))
119 | copy(ka.ckx.ciphertext[1:], ourPublicKey)
120 |
121 | var sigType uint8
122 | var sigHash crypto.Hash
123 | if ka.version >= tls.VersionTLS12 {
124 | signatureAlgorithm := tls.SignatureScheme(sig[0])<<8 | tls.SignatureScheme(sig[1])
125 | sig = sig[2:]
126 | if len(sig) < 2 {
127 | return errServerKeyExchange
128 | }
129 |
130 | if !isSupportedSignatureAlgorithm(signatureAlgorithm, clientHello.supportedSignatureAlgorithms) {
131 | return errors.New("tls: certificate used with invalid signature algorithm")
132 | }
133 | sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm)
134 | if err != nil {
135 | return err
136 | }
137 | } else {
138 | sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey)
139 | if err != nil {
140 | return err
141 | }
142 | }
143 | if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
144 | return errServerKeyExchange
145 | }
146 |
147 | sigLen := int(sig[0])<<8 | int(sig[1])
148 | if sigLen+2 != len(sig) {
149 | return errServerKeyExchange
150 | }
151 | sig = sig[2:]
152 |
153 | signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams)
154 | if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil {
155 | return errors.New("tls: invalid signature by the server certificate: " + err.Error())
156 | }
157 | return nil
158 | }
159 |
160 | // 依据client逻辑解析,故忽略此内部逻辑
161 | func (ka *ecdheKeyAgreement) processClientKeyExchange(config *tls.Config, cert *tls.Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
162 | return nil, nil
163 | }
164 |
165 | func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *tls.Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
166 | if ka.ckx == nil {
167 | return nil, nil, errors.New("tls: missing ServerKeyExchange message")
168 | }
169 |
170 | return ka.preMasterSecret, ka.ckx, nil
171 | }
172 |
--------------------------------------------------------------------------------
/http2/tls/handsh/key_schedule.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto/elliptic"
5 | "crypto/tls"
6 | "errors"
7 | "io"
8 | "math/big"
9 |
10 | "golang.org/x/crypto/curve25519"
11 | )
12 |
13 | const (
14 | resumptionBinderLabel = "res binder"
15 | clientHandshakeTrafficLabel = "c hs traffic"
16 | serverHandshakeTrafficLabel = "s hs traffic"
17 | clientApplicationTrafficLabel = "c ap traffic"
18 | serverApplicationTrafficLabel = "s ap traffic"
19 | exporterLabel = "exp master"
20 | resumptionLabel = "res master"
21 | trafficUpdateLabel = "traffic upd"
22 | )
23 |
24 | // ecdheParameters implements Diffie-Hellman with either NIST curves or X25519,
25 | // according to RFC 8446, Section 4.2.8.2.
26 | type ecdheParameters interface {
27 | CurveID() tls.CurveID
28 | PublicKey() []byte
29 | SharedKey(peerPublicKey []byte) []byte
30 | }
31 |
32 | type x25519Parameters struct {
33 | privateKey []byte
34 | publicKey []byte
35 | }
36 |
37 | func (p *x25519Parameters) CurveID() tls.CurveID {
38 | return tls.X25519
39 | }
40 |
41 | func (p *x25519Parameters) PublicKey() []byte {
42 | return p.publicKey[:]
43 | }
44 |
45 | func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte {
46 | sharedKey, err := curve25519.X25519(p.privateKey, peerPublicKey)
47 | if err != nil {
48 | return nil
49 | }
50 | return sharedKey
51 | }
52 |
53 | type nistParameters struct {
54 | privateKey []byte
55 | x, y *big.Int // public key
56 | curveID tls.CurveID
57 | }
58 |
59 | func (p *nistParameters) CurveID() tls.CurveID {
60 | return p.curveID
61 | }
62 |
63 | func (p *nistParameters) PublicKey() []byte {
64 | curve, _ := curveForCurveID(p.curveID)
65 | return elliptic.Marshal(curve, p.x, p.y)
66 | }
67 |
68 | func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
69 | curve, _ := curveForCurveID(p.curveID)
70 | // Unmarshal also checks whether the given point is on the curve.
71 | x, y := elliptic.Unmarshal(curve, peerPublicKey)
72 | if x == nil {
73 | return nil
74 | }
75 |
76 | xShared, _ := curve.ScalarMult(x, y, p.privateKey)
77 | sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
78 | return xShared.FillBytes(sharedKey)
79 | }
80 |
81 | func curveForCurveID(id tls.CurveID) (elliptic.Curve, bool) {
82 | switch id {
83 | case tls.CurveP256:
84 | return elliptic.P256(), true
85 | case tls.CurveP384:
86 | return elliptic.P384(), true
87 | case tls.CurveP521:
88 | return elliptic.P521(), true
89 | default:
90 | return nil, false
91 | }
92 | }
93 |
94 | func generateECDHEParameters(rand io.Reader, curveID tls.CurveID) (ecdheParameters, error) {
95 | if curveID == tls.X25519 {
96 | privateKey := make([]byte, curve25519.ScalarSize)
97 | if _, err := io.ReadFull(rand, privateKey); err != nil {
98 | return nil, err
99 | }
100 | publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
101 | if err != nil {
102 | return nil, err
103 | }
104 | return &x25519Parameters{privateKey: privateKey, publicKey: publicKey}, nil
105 | }
106 |
107 | curve, ok := curveForCurveID(curveID)
108 | if !ok {
109 | return nil, errors.New("tls: internal error: unsupported curve")
110 | }
111 |
112 | p := &nistParameters{curveID: curveID}
113 | var err error
114 | p.privateKey, p.x, p.y, err = elliptic.GenerateKey(curve, rand)
115 | if err != nil {
116 | return nil, err
117 | }
118 | return p, nil
119 | }
120 |
--------------------------------------------------------------------------------
/http2/tls/handsh/keylog.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | // KeyLog tls.Config 可通过KeyLogWriter字段打印部分密钥日志,KeyLogWriter类型为io.Writer
9 | type KeyLog string
10 |
11 | // Write ..
12 | func (s KeyLog) Write(p []byte) (n int, err error) {
13 | fmt.Println(s, string(p))
14 | return len(p), nil
15 | }
16 |
17 | // Info ..
18 | func (s KeyLog) Info(str string) {
19 | s.Write([]byte(str))
20 | }
21 |
22 | // Err ..
23 | func (s KeyLog) Err(str string) {
24 | fmt.Println(strings.ToUpper(string(s))+" ERR:", str)
25 | }
26 |
27 | const (
28 | client = KeyLog("Client")
29 | server = KeyLog("Server")
30 | )
31 |
--------------------------------------------------------------------------------
/http2/tls/handsh/msg_test.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/open-ch/ja3"
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func Test_clientHelloMsgja3(t *testing.T) {
11 | helloBytes := []byte{1, 0, 0, 252, 3, 3, 48, 57, 100, 97, 101, 49, 97, 97, 51, 100, 50, 97, 57, 48, 100, 51, 99, 48, 55, 54, 98, 56, 97, 100, 98, 50, 51, 57, 56, 56, 49, 49, 32, 48, 57, 100, 97, 101, 49, 97, 97, 51, 100, 50, 97, 57, 48, 100, 51, 99, 48, 55, 54, 98, 56, 97, 100, 98, 50, 51, 57, 56, 56, 49, 49, 0, 38, 192, 43, 192, 47, 192, 44, 192, 48, 204, 169, 204, 168, 192, 9, 192, 19, 192, 10, 192, 20, 0, 156, 0, 157, 0, 47, 0, 53, 192, 18, 0, 10, 19, 1, 19, 2, 19, 3, 1, 0, 0, 141, 0, 5, 0, 5, 1, 0, 0, 0, 0, 0, 10, 0, 10, 0, 8, 0, 29, 0, 23, 0, 24, 0, 25, 0, 11, 0, 2, 1, 0, 0, 13, 0, 26, 0, 24, 8, 4, 4, 3, 8, 7, 8, 5, 8, 6, 4, 1, 5, 1, 6, 1, 5, 3, 6, 3, 2, 1, 2, 3, 255, 1, 0, 1, 0, 0, 16, 0, 14, 0, 12, 2, 104, 50, 8, 104, 116, 116, 112, 47, 49, 46, 49, 0, 18, 0, 0, 0, 43, 0, 9, 8, 3, 4, 3, 3, 3, 2, 3, 1, 0, 51, 0, 38, 0, 36, 0, 29, 0, 32, 36, 158, 4, 131, 223, 74, 205, 97, 242, 132, 156, 233, 193, 238, 197, 17, 246, 243, 248, 212, 104, 76, 179, 5, 184, 163, 153, 23, 4, 205, 201, 113}
12 | chello := &clientHelloMsg{}
13 | ok := chello.unmarshal(helloBytes)
14 | assert.True(t, ok)
15 | payload := []byte{22, 3, 1, 1, 0, 1, 0, 0, 252, 3, 3, 48, 57, 100, 97, 101, 49, 97, 97, 51, 100, 50, 97, 57, 48, 100, 51, 99, 48, 55, 54, 98, 56, 97, 100, 98, 50, 51, 57, 56, 56, 49, 49, 32, 48, 57, 100, 97, 101, 49, 97, 97, 51, 100, 50, 97, 57, 48, 100, 51, 99, 48, 55, 54, 98, 56, 97, 100, 98, 50, 51, 57, 56, 56, 49, 49, 0, 38, 192, 43, 192, 47, 192, 44, 192, 48, 204, 169, 204, 168, 192, 9, 192, 19, 192, 10, 192, 20, 0, 156, 0, 157, 0, 47, 0, 53, 192, 18, 0, 10, 19, 1, 19, 2, 19, 3, 1, 0, 0, 141, 0, 5, 0, 5, 1, 0, 0, 0, 0, 0, 10, 0, 10, 0, 8, 0, 29, 0, 23, 0, 24, 0, 25, 0, 11, 0, 2, 1, 0, 0, 13, 0, 26, 0, 24, 8, 4, 4, 3, 8, 7, 8, 5, 8, 6, 4, 1, 5, 1, 6, 1, 5, 3, 6, 3, 2, 1, 2, 3, 255, 1, 0, 1, 0, 0, 16, 0, 14, 0, 12, 2, 104, 50, 8, 104, 116, 116, 112, 47, 49, 46, 49, 0, 18, 0, 0, 0, 43, 0, 9, 8, 3, 4, 3, 3, 3, 2, 3, 1, 0, 51, 0, 38, 0, 36, 0, 29, 0, 32, 36, 158, 4, 131, 223, 74, 205, 97, 242, 132, 156, 233, 193, 238, 197, 17, 246, 243, 248, 212, 104, 76, 179, 5, 184, 163, 153, 23, 4, 205, 201, 113}
16 | ja3Info, err := ja3.ComputeJA3FromSegment(payload)
17 | assert.Nil(t, err)
18 | assert.Emptyf(t, ja3Info.GetJA3String(), "特意输出ja3指纹明细:", ja3Info.GetJA3String())
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/http2/tls/handsh/parse.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto/tls"
5 | "crypto/x509"
6 | "errors"
7 | "fmt"
8 | "hash"
9 | )
10 |
11 | type processor interface {
12 | process(isClient bool, msg interface{}) error
13 | }
14 |
15 | // TLSMsgParser https 数据的解析
16 | type TLSMsgParser struct {
17 | ClientConfig *tls.Config
18 | // 保留client和server的hellomsg,这两个对拿到加密密钥至关重要
19 | clientHello *clientHelloMsg
20 | serverHello *serverHelloMsg
21 | clientReader *rawReader
22 | serverReader *rawReader
23 | vers uint16
24 | msgProcessor processor
25 | }
26 |
27 | // NewParser 。。
28 | func NewParser(conf *tls.Config) *TLSMsgParser {
29 | pr := &TLSMsgParser{
30 | ClientConfig: conf,
31 | clientReader: &rawReader{
32 | isClient: true,
33 | logger: client,
34 | },
35 | serverReader: &rawReader{
36 | logger: server,
37 | },
38 | }
39 | pr.clientReader.emit = pr.processMsg
40 | pr.serverReader.emit = pr.processMsg
41 | return pr
42 | }
43 |
44 | // Parse 交给指定reader读取数据
45 | func (pr *TLSMsgParser) Parse(isClient bool, data []byte) {
46 | if isClient {
47 | pr.clientReader.parse(data)
48 | } else {
49 | pr.serverReader.parse(data)
50 | }
51 | }
52 |
53 | // LastCheck 检查数据是否解析完毕
54 | func (pr *TLSMsgParser) LastCheck() error {
55 | // 防止数据有遗漏,再次check
56 | pr.clientReader.parse([]byte{})
57 | pr.serverReader.parse([]byte{})
58 | cn := pr.clientReader.rawData.Len()
59 | sn := pr.serverReader.rawData.Len()
60 | if cn > 0 || sn > 0 {
61 | // 仍然有数据打印错误
62 | return fmt.Errorf("client remain data: %d bytes, server remain data: %d bytes", cn, sn)
63 | }
64 | return nil
65 | }
66 |
67 | // 参考 handshake_client.go中的pickTLSVersion方法
68 | func (pr *TLSMsgParser) pickTLSVersion(serverHello *serverHelloMsg) error {
69 | peerVer := serverHello.vers
70 | if serverHello.supportedVersion != 0 {
71 | peerVer = serverHello.supportedVersion
72 | }
73 |
74 | versions := make([]uint16, 0, 4)
75 | for _, v := range []uint16{
76 | tls.VersionTLS13,
77 | tls.VersionTLS12,
78 | tls.VersionTLS11,
79 | tls.VersionTLS10,
80 | } {
81 | c := pr.ClientConfig
82 | if c != nil && c.MinVersion != 0 && v < c.MinVersion {
83 | continue
84 | }
85 | if c != nil && c.MaxVersion != 0 && v > c.MaxVersion {
86 | continue
87 | }
88 | versions = append(versions, v)
89 | }
90 |
91 | for _, peerVersion := range []uint16{peerVer} {
92 | for _, v := range versions {
93 | if v == peerVersion {
94 | // 设置client和server的tlsversion
95 | pr.clientReader.version = v
96 | pr.serverReader.version = v
97 | pr.vers = v
98 | return nil
99 | }
100 | }
101 | }
102 | return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVer)
103 | }
104 |
105 | func (pr *TLSMsgParser) processMsg(isClient bool, msg interface{}, err error) {
106 | logger := server
107 | if isClient {
108 | logger = client
109 | }
110 | if err != nil {
111 | logger.Err(err.Error())
112 | return
113 | }
114 | switch tlsMsg := msg.(type) {
115 | case *clientHelloMsg:
116 | pr.clientHello = tlsMsg
117 | case *serverHelloMsg:
118 | // client read server hello msg
119 | if err := pr.pickTLSVersion(tlsMsg); err != nil {
120 | logger.Err(err.Error())
121 | return
122 | }
123 | pr.serverHello = tlsMsg
124 | if pr.vers == tls.VersionTLS13 {
125 | pr.msgProcessor = &tls13Processor{
126 | tr: pr,
127 | }
128 | } else {
129 | pr.msgProcessor = &defalutProcessor{
130 | tr: pr,
131 | }
132 | }
133 | }
134 | // 读完serverhellomsg 之后tls版本才不为0
135 | if pr.vers == 0 {
136 | return
137 | }
138 | // 处理hellomsg 之外的信息解析解密信息
139 | pr.msgProcessor.process(isClient, msg)
140 | }
141 |
142 | type tls13Processor struct {
143 | tr *TLSMsgParser
144 | transcript hash.Hash
145 | selectedSuite *cipherSuiteTLS13
146 | handshakeSecret []byte
147 | clientSecret []byte
148 | serverSecret []byte
149 | masterSecret []byte
150 | trafficSecret []byte
151 | }
152 |
153 | type defalutProcessor struct {
154 | tr *TLSMsgParser
155 | selectedSuite *cipherSuite
156 | peerCertificates []*x509.Certificate
157 | masterSecret []byte
158 | }
159 |
160 | func (p *defalutProcessor) process(isClient bool, msg interface{}) error {
161 | tr := p.tr
162 | switch m := msg.(type) {
163 | case *serverHelloMsg:
164 | // 选择suite
165 | suite := mutualCipherSuite(tr.clientHello.cipherSuites, tr.serverHello.cipherSuite)
166 | if suite == nil {
167 | panic(errors.New("you have need to implements key exchange method"))
168 | }
169 | p.selectedSuite = suite
170 | case *certificateMsg:
171 | p.peerCertificates = make([]*x509.Certificate, len(m.certificates))
172 | for i, asn1Data := range m.certificates {
173 | cert, err := x509.ParseCertificate(asn1Data)
174 | if err != nil {
175 | return errors.New("tls: failed to parse certificate from server: " + err.Error())
176 | }
177 | p.peerCertificates[i] = cert
178 | }
179 | case *serverKeyExchangeMsg:
180 | keyAgreement := p.selectedSuite.ka(tr.vers)
181 | if err := keyAgreement.processServerKeyExchange(tr.ClientConfig, tr.clientHello, tr.serverHello, p.peerCertificates[0], m); err != nil {
182 | return err
183 | }
184 | preMasterSecret, _, err := keyAgreement.generateClientKeyExchange(tr.ClientConfig, tr.clientHello, p.peerCertificates[0])
185 | if err != nil {
186 | return err
187 | }
188 | p.masterSecret = masterFromPreMasterSecret(tr.vers, p.selectedSuite, preMasterSecret, tr.clientHello.random, tr.serverHello.random)
189 | suite := p.selectedSuite
190 | clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
191 | keysFromMasterSecret(tr.vers, suite, p.masterSecret, tr.clientHello.random, tr.serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
192 | var clientCipher, serverCipher interface{}
193 | var clientHash, serverHash macFunction
194 | if suite.cipher != nil {
195 | clientCipher = suite.cipher(clientKey, clientIV, true /* for reading */)
196 | clientHash = suite.mac(tr.vers, clientMAC)
197 | serverCipher = suite.cipher(serverKey, serverIV, true /* for reading */)
198 | serverHash = suite.mac(tr.vers, serverMAC)
199 | } else {
200 | clientCipher = suite.aead(clientKey, clientIV)
201 | serverCipher = suite.aead(serverKey, serverIV)
202 | }
203 | tr.clientReader.prepareCipherSpec(tr.vers, serverCipher, serverHash)
204 | tr.serverReader.prepareCipherSpec(tr.vers, clientCipher, clientHash)
205 |
206 | }
207 | return nil
208 | }
209 |
210 | func (p *tls13Processor) process(isClient bool, msg interface{}) error {
211 | if tlsMsg, ok := msg.(handshakeMessage); ok && p.transcript != nil {
212 | p.transcript.Write(tlsMsg.marshal())
213 | }
214 | tr := p.tr
215 | switch msg.(type) {
216 | case *serverHelloMsg:
217 | suite := mutualCipherSuiteTLS13(tr.clientHello.cipherSuites, tr.serverHello.cipherSuite)
218 | p.selectedSuite = suite
219 | // 计算clienthello和serverhello的摘要
220 | p.transcript = suite.hash.New()
221 | p.transcript.Write(tr.clientHello.marshal())
222 | p.transcript.Write(tr.serverHello.marshal())
223 | curveID := curvePreferences(tr.ClientConfig)[0]
224 | if _, ok := curveForCurveID(curveID); curveID != tls.X25519 && !ok {
225 | return fmt.Errorf("tls: CurvePreferences includes unsupported curve")
226 | }
227 | params, err := generateECDHEParameters(crand(tr.ClientConfig), curveID)
228 | if err != nil {
229 | return err
230 | }
231 | sharedKey := params.SharedKey(tr.serverHello.serverShare.data)
232 | if sharedKey == nil {
233 | return fmt.Errorf("tls: invalid server key share")
234 | }
235 | // debug handshake_client_tls13.go得到的结果
236 | earlySecret := suite.extract(nil, nil)
237 | p.handshakeSecret = suite.extract(sharedKey,
238 | suite.deriveSecret(earlySecret, "derived", nil))
239 | p.clientSecret = suite.deriveSecret(p.handshakeSecret,
240 | clientHandshakeTrafficLabel, p.transcript)
241 | p.serverSecret = suite.deriveSecret(p.handshakeSecret,
242 | serverHandshakeTrafficLabel, p.transcript)
243 | masterSecret := suite.extract(nil, suite.deriveSecret(p.handshakeSecret, "derived", nil))
244 | p.masterSecret = masterSecret
245 |
246 | tr.clientReader.setTrafficSecret(p.selectedSuite, p.serverSecret)
247 | tr.serverReader.setTrafficSecret(p.selectedSuite, p.clientSecret)
248 | case *finishedMsg:
249 | if isClient {
250 | // client read server finishedMsg 并且设置读取server数据的key
251 | suite := p.selectedSuite
252 | p.trafficSecret = suite.deriveSecret(p.masterSecret,
253 | clientApplicationTrafficLabel, p.transcript)
254 | serverSecret := suite.deriveSecret(p.masterSecret,
255 | serverApplicationTrafficLabel, p.transcript)
256 | tr.clientReader.setTrafficSecret(suite, serverSecret)
257 | } else {
258 | // server read client finishedMsg 设置server读取数据的key
259 | suite := p.selectedSuite
260 | tr.serverReader.setTrafficSecret(suite, p.trafficSecret)
261 | }
262 | }
263 | return nil
264 | }
265 |
--------------------------------------------------------------------------------
/http2/tls/handsh/prf.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto"
5 | "crypto/hmac"
6 | "crypto/md5"
7 | "crypto/sha1"
8 | "crypto/sha256"
9 | "crypto/sha512"
10 | "crypto/tls"
11 | "hash"
12 | )
13 |
14 | const (
15 | masterSecretLength = 48 // Length of a master secret in TLS 1.1.
16 | finishedVerifyLength = 12 // Length of verify_data in a Finished message.
17 | )
18 |
19 | var masterSecretLabel = []byte("master secret")
20 | var keyExpansionLabel = []byte("key expansion")
21 | var clientFinishedLabel = []byte("client finished")
22 | var serverFinishedLabel = []byte("server finished")
23 |
24 | func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
25 | switch version {
26 | case tls.VersionTLS10, tls.VersionTLS11:
27 | return prf10, crypto.Hash(0)
28 | case tls.VersionTLS12:
29 | if suite.flags&suiteSHA384 != 0 {
30 | return prf12(sha512.New384), crypto.SHA384
31 | }
32 | return prf12(sha256.New), crypto.SHA256
33 | default:
34 | panic("unknown version")
35 | }
36 | }
37 |
38 | // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5.
39 | func prf10(result, secret, label, seed []byte) {
40 | hashSHA1 := sha1.New
41 | hashMD5 := md5.New
42 |
43 | labelAndSeed := make([]byte, len(label)+len(seed))
44 | copy(labelAndSeed, label)
45 | copy(labelAndSeed[len(label):], seed)
46 |
47 | s1, s2 := splitPreMasterSecret(secret)
48 | pHash(result, s1, labelAndSeed, hashMD5)
49 | result2 := make([]byte, len(result))
50 | pHash(result2, s2, labelAndSeed, hashSHA1)
51 |
52 | for i, b := range result2 {
53 | result[i] ^= b
54 | }
55 | }
56 |
57 | // Split a premaster secret in two as specified in RFC 4346, Section 5.
58 | func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
59 | s1 = secret[0 : (len(secret)+1)/2]
60 | s2 = secret[len(secret)/2:]
61 | return
62 | }
63 |
64 | // pHash implements the P_hash function, as defined in RFC 4346, Section 5.
65 | func pHash(result, secret, seed []byte, hash func() hash.Hash) {
66 | h := hmac.New(hash, secret)
67 | h.Write(seed)
68 | a := h.Sum(nil)
69 |
70 | j := 0
71 | for j < len(result) {
72 | h.Reset()
73 | h.Write(a)
74 | h.Write(seed)
75 | b := h.Sum(nil)
76 | copy(result[j:], b)
77 | j += len(b)
78 |
79 | h.Reset()
80 | h.Write(a)
81 | a = h.Sum(nil)
82 | }
83 | }
84 |
85 | // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5.
86 | func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
87 | return func(result, secret, label, seed []byte) {
88 | labelAndSeed := make([]byte, len(label)+len(seed))
89 | copy(labelAndSeed, label)
90 | copy(labelAndSeed[len(label):], seed)
91 |
92 | pHash(result, secret, labelAndSeed, hashFunc)
93 | }
94 | }
95 |
96 | // masterFromPreMasterSecret generates the master secret from the pre-master
97 | // secret. See RFC 5246, Section 8.1.
98 | func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
99 | seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
100 | seed = append(seed, clientRandom...)
101 | seed = append(seed, serverRandom...)
102 |
103 | masterSecret := make([]byte, masterSecretLength)
104 | prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
105 | return masterSecret
106 | }
107 |
108 | func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
109 | prf, _ := prfAndHashForVersion(version, suite)
110 | return prf
111 | }
112 |
113 | // keysFromMasterSecret generates the connection keys from the master
114 | // secret, given the lengths of the MAC key, cipher key and IV, as defined in
115 | // RFC 2246, Section 6.3.
116 | func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
117 | seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
118 | seed = append(seed, serverRandom...)
119 | seed = append(seed, clientRandom...)
120 |
121 | n := 2*macLen + 2*keyLen + 2*ivLen
122 | keyMaterial := make([]byte, n)
123 | prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
124 | clientMAC = keyMaterial[:macLen]
125 | keyMaterial = keyMaterial[macLen:]
126 | serverMAC = keyMaterial[:macLen]
127 | keyMaterial = keyMaterial[macLen:]
128 | clientKey = keyMaterial[:keyLen]
129 | keyMaterial = keyMaterial[keyLen:]
130 | serverKey = keyMaterial[:keyLen]
131 | keyMaterial = keyMaterial[keyLen:]
132 | clientIV = keyMaterial[:ivLen]
133 | keyMaterial = keyMaterial[ivLen:]
134 | serverIV = keyMaterial[:ivLen]
135 | return
136 | }
137 |
--------------------------------------------------------------------------------
/http2/tls/handsh/rand.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "crypto/rand"
5 | )
6 |
7 | // Rand 自定义tls.Config中生成随机数的逻辑
8 | type Rand struct {
9 | RandomMode bool
10 | }
11 |
12 | // Read 这里为了方便调试返回固定的随机数
13 | func (r *Rand) Read(p []byte) (n int, err error) {
14 | if r.RandomMode {
15 | return rand.Reader.Read(p)
16 | }
17 | bts := []byte("09dae1aa3d2a90d3c076b8adb23988116f62e003ae8f2c763443c9e24aab3b04")
18 | bts = append(bts, "2a0071514f632c21c064fa7e95d25246802a9086f533a19cf65628812e33361b"...)
19 | bts = append(bts, "3c4b50be833eed78e0b4827b3e427a614764700c724d323147514e8ae3576a35"...)
20 | bts = append(bts, "aaff6568490bce6046928b119b63fac6c187ed1a59559b4d896c6958c253e9c9"...)
21 | n = copy(p, bts[:len(p)])
22 | return n, nil
23 | }
24 |
--------------------------------------------------------------------------------
/http2/tls/handsh/raw_reader.go:
--------------------------------------------------------------------------------
1 | package handsh
2 |
3 | import (
4 | "bytes"
5 | "crypto/cipher"
6 | "crypto/subtle"
7 | "crypto/tls"
8 | "fmt"
9 | "io"
10 | "net"
11 | )
12 |
13 | type aead interface {
14 | cipher.AEAD
15 |
16 | // explicitNonceLen returns the number of bytes of explicit nonce
17 | // included in each record. This is eight for older AEADs and
18 | // zero for modern ones.
19 | explicitNonceLen() int
20 | }
21 |
22 | type cbcMode interface {
23 | cipher.BlockMode
24 | SetIV([]byte)
25 | }
26 |
27 | type macFunction interface {
28 | // Size returns the length of the MAC.
29 | Size() int
30 | // MAC appends the MAC of (seq, header, data) to out. The extra data is fed
31 | // into the MAC after obtaining the result to normalize timing. The result
32 | // is only valid until the next invocation of MAC as the buffer is reused.
33 | MAC(seq, header, data, extra []byte) []byte
34 | }
35 |
36 | // 把数据读取为一个一个的msg
37 | type rawReader struct {
38 | isClient bool
39 |
40 | version uint16 // protocol version
41 | cipher interface{} // cipher algorithm
42 | mac macFunction
43 | seq [8]byte // 64-bit sequence number
44 | additionalData [13]byte // to avoid allocs; interface method args escape
45 |
46 | nextCipher interface{} // next encryption state
47 | nextMac macFunction // next MAC algorithm
48 |
49 | trafficSecret []byte // current TLS 1.3 traffic secret
50 | rawData bytes.Buffer
51 |
52 | logger KeyLog
53 |
54 | emit func(isClient bool, msg interface{}, err error)
55 | }
56 |
57 | // 交给指定reader读取数据
58 | func (rr *rawReader) parse(data []byte) {
59 | // 补充数据
60 | rr.rawData.Write(data)
61 | var err error
62 | // 开始解析数据
63 | for {
64 | // 如果数据已经读取完毕,或者已经没有数据了,则暂停本次解析
65 | if rr.rawData.Len() == 0 || rr.rawData.Len() < recordHeaderLen {
66 | break
67 | }
68 | hdr := rr.rawData.Bytes()[:recordHeaderLen]
69 | typ := recordType(hdr[0])
70 |
71 | n := int(hdr[3])<<8 | int(hdr[4])
72 | if rr.version == tls.VersionTLS13 && n > maxCiphertextTLS13 || n > maxCiphertext {
73 | err = fmt.Errorf("oversized record received with length %d", n)
74 | break
75 | }
76 | // 如果数据长度还是不够,则继续等待数据进入buf
77 | if rr.rawData.Len() < recordHeaderLen+n {
78 | break
79 | }
80 | // 取出原始数据
81 | record := rr.rawData.Next(recordHeaderLen + n)
82 | rawData := make([]byte, len(record))
83 | copy(rawData, record)
84 | data, typ, e := rr.decrypt(record)
85 | if e != nil {
86 | err = e
87 | break
88 | }
89 | // other check
90 | if len(data) > maxPlaintext {
91 | err = alertRecordOverflow
92 | break
93 | }
94 |
95 | // Application Data messages are always protected.
96 | if rr.cipher == nil && typ == recordTypeApplicationData {
97 | err = alertUnexpectedMessage
98 | break
99 | }
100 |
101 | switch typ {
102 | default:
103 | err = alertUnexpectedMessage
104 | case recordTypeAlert:
105 | if len(data) != 2 {
106 | err = alertUnexpectedMessage
107 | } else if alert(data[1]) == alertCloseNotify {
108 | err = io.EOF
109 | } else if rr.version == tls.VersionTLS13 {
110 | err = &net.OpError{Op: "remote error", Err: alert(data[1])}
111 | }
112 | switch data[0] {
113 | case alertLevelError:
114 | err = &net.OpError{Op: "remote error", Err: alert(data[1])}
115 | default:
116 | err = alertUnexpectedMessage
117 | }
118 |
119 | case recordTypeChangeCipherSpec:
120 | if len(data) != 1 || data[0] != 1 {
121 | err = alertDecodeError
122 | }
123 | // 本次demo使用tls1.3,在tls1.3中会忽略change_cipher_spec records
124 | if rr.version == tls.VersionTLS13 {
125 | rr.logger.Info("ignore ChangeCipherSpec record")
126 | continue
127 | }
128 | rr.logger.Info("ChangeCipherSpec")
129 | err = rr.changeCipherSpec()
130 | case recordTypeApplicationData:
131 | // 打印用户传输的数据
132 | rr.logger.Info(fmt.Sprintf("read internet deliver content: %s", string(rawData)))
133 | rr.logger.Info(fmt.Sprintf("read application content: %s", string(data)))
134 | case recordTypeHandshake:
135 | // 处理解密后的握手数据
136 | if len(data) == 0 {
137 | err = alertUnexpectedMessage
138 | break
139 | }
140 | msg, e := rr.parseToMsg(data)
141 | rr.emitMsg(rr.isClient, msg, e)
142 | if e != nil {
143 | err = e
144 | break
145 | }
146 | }
147 | }
148 | if err != nil {
149 | // 数据有误需要清除
150 | rr.rawData.Reset()
151 | rr.logger.Err(err.Error())
152 | }
153 | }
154 |
155 | func (rr *rawReader) parseToMsg(b []byte) (interface{}, error) {
156 | if len(b) < 4 {
157 | return nil, fmt.Errorf("data format error")
158 | }
159 | n := int(b[1])<<16 | int(b[2])<<8 | int(b[3])
160 | if n > 65536 { // maximum handshake we support (protocol max is 16 MB)
161 | return nil, fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, 65536)
162 | }
163 | var m handshakeMessage
164 | // b = append([]byte(nil), b...)
165 | switch b[0] {
166 | case typeHelloRequest:
167 | rr.logger.Info("read helloRequestMsg")
168 | m = new(helloRequestMsg)
169 | case typeClientHello:
170 | rr.logger.Info("read clientHelloMsg")
171 | m = new(clientHelloMsg)
172 | case typeServerHello:
173 | rr.logger.Info("read serverHelloMsg")
174 | m = new(serverHelloMsg)
175 | case typeNewSessionTicket:
176 | // TODO
177 | case typeCertificate:
178 | if rr.version == tls.VersionTLS13 {
179 | rr.logger.Info("read certificateMsgTLS13")
180 | m = new(certificateMsgTLS13)
181 | } else {
182 | rr.logger.Info("read certificateMsg")
183 | m = new(certificateMsg)
184 | }
185 | case typeCertificateRequest:
186 | if rr.version == tls.VersionTLS13 {
187 | rr.logger.Info("read certificateRequestMsgTLS13")
188 | m = new(certificateRequestMsgTLS13)
189 | } else {
190 | rr.logger.Info("read certificateRequestMsg")
191 | m = &certificateRequestMsg{
192 | hasSignatureAlgorithm: rr.version >= tls.VersionTLS12,
193 | }
194 | }
195 | case typeCertificateStatus:
196 | // TODO
197 | case typeServerKeyExchange:
198 | rr.logger.Info("read serverKeyExchangeMsg")
199 | m = new(serverKeyExchangeMsg)
200 | case typeServerHelloDone:
201 | rr.logger.Info("read serverHelloDoneMsg")
202 | m = new(serverHelloDoneMsg)
203 | case typeClientKeyExchange:
204 | rr.logger.Info("read clientKeyExchangeMsg")
205 | m = new(clientKeyExchangeMsg)
206 | case typeCertificateVerify:
207 | rr.logger.Info("read certificateVerifyMsg")
208 | m = &certificateVerifyMsg{
209 | hasSignatureAlgorithm: rr.version >= tls.VersionTLS12,
210 | }
211 | case typeFinished:
212 | rr.logger.Info("read finishedMsg")
213 | m = new(finishedMsg)
214 | case typeEncryptedExtensions:
215 | rr.logger.Info("read encryptedExtensionsMsg")
216 | m = new(encryptedExtensionsMsg)
217 | case typeEndOfEarlyData:
218 | // TODO
219 | case typeKeyUpdate:
220 | // TODO
221 | default:
222 | return nil, fmt.Errorf("unkonw handshake msg")
223 | }
224 | if m != nil && m.unmarshal(b) {
225 | return m, nil
226 | }
227 | return nil, fmt.Errorf("you need to new a msg to avoid error")
228 | }
229 |
230 | func (rr *rawReader) emitMsg(isClient bool, msg interface{}, err error) {
231 | if rr.emit == nil {
232 | return
233 | }
234 | rr.emit(isClient, msg, err)
235 | }
236 |
237 | func (rr *rawReader) decrypt(record []byte) ([]byte, recordType, error) {
238 | var plaintext []byte
239 | typ := recordType(record[0])
240 | payload := record[recordHeaderLen:]
241 |
242 | // In TLS 1.3, change_cipher_spec messages are to be ignored without being
243 | // decrypted. See RFC 8446, Appendix D.4.
244 | if rr.version == tls.VersionTLS13 && typ == recordTypeChangeCipherSpec {
245 | return payload, typ, nil
246 | }
247 |
248 | paddingGood := byte(255)
249 | paddingLen := 0
250 |
251 | explicitNonceLen := rr.explicitNonceLen()
252 |
253 | if rr.cipher != nil {
254 | switch c := rr.cipher.(type) {
255 | case cipher.Stream:
256 | c.XORKeyStream(payload, payload)
257 | case aead:
258 | if len(payload) < explicitNonceLen {
259 | return nil, 0, alertBadRecordMAC
260 | }
261 | nonce := payload[:explicitNonceLen]
262 | if len(nonce) == 0 {
263 | nonce = rr.seq[:]
264 | }
265 | payload = payload[explicitNonceLen:]
266 |
267 | additionalData := rr.additionalData[:]
268 | if rr.version == tls.VersionTLS13 {
269 | additionalData = record[:recordHeaderLen]
270 | } else {
271 | copy(additionalData, rr.seq[:])
272 | copy(additionalData[8:], record[:3])
273 | n := len(payload) - c.Overhead()
274 | additionalData[11] = byte(n >> 8)
275 | additionalData[12] = byte(n)
276 | }
277 |
278 | var err error
279 | plaintext, err = c.Open(payload[:0], nonce, payload, additionalData)
280 | if err != nil {
281 | return nil, 0, alertBadRecordMAC
282 | }
283 | case cbcMode:
284 | blockSize := c.BlockSize()
285 | minPayload := explicitNonceLen + roundUp(rr.mac.Size()+1, blockSize)
286 | if len(payload)%blockSize != 0 || len(payload) < minPayload {
287 | return nil, 0, alertBadRecordMAC
288 | }
289 |
290 | if explicitNonceLen > 0 {
291 | c.SetIV(payload[:explicitNonceLen])
292 | payload = payload[explicitNonceLen:]
293 | }
294 | c.CryptBlocks(payload, payload)
295 |
296 | // In a limited attempt to protect against CBC padding oracles like
297 | // Lucky13, the data past paddingLen (which is secret) is passed to
298 | // the MAC function as extra data, to be fed into the HMAC after
299 | // computing the digest. This makes the MAC roughly constant time as
300 | // long as the digest computation is constant time and does not
301 | // affect the subsequent write, modulo cache effects.
302 | paddingLen, paddingGood = extractPadding(payload)
303 | default:
304 | panic("unknown cipher type")
305 | }
306 |
307 | if rr.version == tls.VersionTLS13 {
308 | if typ != recordTypeApplicationData {
309 | return nil, 0, alertUnexpectedMessage
310 | }
311 | if len(plaintext) > maxPlaintext+1 {
312 | return nil, 0, alertRecordOverflow
313 | }
314 | // Remove padding and find the ContentType scanning from the end.
315 | for i := len(plaintext) - 1; i >= 0; i-- {
316 | if plaintext[i] != 0 {
317 | typ = recordType(plaintext[i])
318 | plaintext = plaintext[:i]
319 | break
320 | }
321 | if i == 0 {
322 | return nil, 0, alertUnexpectedMessage
323 | }
324 | }
325 | }
326 | } else {
327 | plaintext = payload
328 | }
329 |
330 | if rr.mac != nil {
331 | macSize := rr.mac.Size()
332 | if len(payload) < macSize {
333 | return nil, 0, alertBadRecordMAC
334 | }
335 |
336 | n := len(payload) - macSize - paddingLen
337 | n = subtle.ConstantTimeSelect(int(uint32(n)>>31), 0, n) // if n < 0 { n = 0 }
338 | record[3] = byte(n >> 8)
339 | record[4] = byte(n)
340 | remoteMAC := payload[n : n+macSize]
341 | localMAC := rr.mac.MAC(rr.seq[0:], record[:recordHeaderLen], payload[:n], payload[n+macSize:])
342 |
343 | // This is equivalent to checking the MACs and paddingGood
344 | // separately, but in constant-time to prevent distinguishing
345 | // padding failures from MAC failures. Depending on what value
346 | // of paddingLen was returned on bad padding, distinguishing
347 | // bad MAC from bad padding can lead to an attack.
348 | //
349 | // See also the logic at the end of extractPadding.
350 | macAndPaddingGood := subtle.ConstantTimeCompare(localMAC, remoteMAC) & int(paddingGood)
351 | if macAndPaddingGood != 1 {
352 | return nil, 0, alertBadRecordMAC
353 | }
354 |
355 | plaintext = payload[:n]
356 | }
357 |
358 | rr.incSeq()
359 | return plaintext, typ, nil
360 | }
361 |
362 | func (rr *rawReader) incSeq() {
363 | for i := 7; i >= 0; i-- {
364 | rr.seq[i]++
365 | if rr.seq[i] != 0 {
366 | return
367 | }
368 | }
369 |
370 | // Not allowed to let sequence number wrap.
371 | // Instead, must renegotiate before it does.
372 | // Not likely enough to bother.
373 | panic("TLS: sequence number wraparound")
374 | }
375 |
376 | func (rr *rawReader) explicitNonceLen() int {
377 | if rr.cipher == nil {
378 | return 0
379 | }
380 |
381 | switch c := rr.cipher.(type) {
382 | case cipher.Stream:
383 | return 0
384 | case aead:
385 | return c.explicitNonceLen()
386 | case cbcMode:
387 | // TLS 1.1 introduced a per-record explicit IV to fix the BEAST attack.
388 | if rr.version >= tls.VersionTLS11 {
389 | return c.BlockSize()
390 | }
391 | return 0
392 | default:
393 | panic("unknown cipher type")
394 | }
395 | }
396 |
397 | func (rr *rawReader) setTrafficSecret(suite *cipherSuiteTLS13, secret []byte) {
398 | rr.trafficSecret = secret
399 | key, iv := suite.trafficKey(secret)
400 | rr.cipher = suite.aead(key, iv)
401 | for i := range rr.seq {
402 | rr.seq[i] = 0
403 | }
404 | }
405 |
406 | func (rr *rawReader) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
407 | rr.version = version
408 | rr.nextCipher = cipher
409 | rr.nextMac = mac
410 | }
411 |
412 | // changeCipherSpec changes the encryption and MAC states
413 | // to the ones previously passed to prepareCipherSpec.
414 | func (rr *rawReader) changeCipherSpec() error {
415 | if rr.nextCipher == nil || rr.version == tls.VersionTLS13 {
416 | return alertInternalError
417 | }
418 | rr.cipher = rr.nextCipher
419 | rr.mac = rr.nextMac
420 | rr.nextCipher = nil
421 | rr.nextMac = nil
422 | for i := range rr.seq {
423 | rr.seq[i] = 0
424 | }
425 | return nil
426 | }
427 |
428 | func roundUp(a, b int) int {
429 | return a + (b-a%b)%b
430 | }
431 |
432 | func extractPadding(payload []byte) (toRemove int, good byte) {
433 | if len(payload) < 1 {
434 | return 0, 0
435 | }
436 |
437 | paddingLen := payload[len(payload)-1]
438 | t := uint(len(payload)-1) - uint(paddingLen)
439 | // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
440 | good = byte(int32(^t) >> 31)
441 |
442 | // The maximum possible padding length plus the actual length field
443 | toCheck := 256
444 | // The length of the padded data is public, so we can use an if here
445 | if toCheck > len(payload) {
446 | toCheck = len(payload)
447 | }
448 |
449 | for i := 0; i < toCheck; i++ {
450 | t := uint(paddingLen) - uint(i)
451 | // if i <= paddingLen then the MSB of t is zero
452 | mask := byte(int32(^t) >> 31)
453 | b := payload[len(payload)-1-i]
454 | good &^= mask&paddingLen ^ mask&b
455 | }
456 |
457 | // We AND together the bits of good and replicate the result across
458 | // all the bits.
459 | good &= good << 4
460 | good &= good << 2
461 | good &= good << 1
462 | good = uint8(int8(good) >> 7)
463 |
464 | // Zero the padding length on error. This ensures any unchecked bytes
465 | // are included in the MAC. Otherwise, an attacker that could
466 | // distinguish MAC failures from padding failures could mount an attack
467 | // similar to POODLE in SSL 3.0: given a good ciphertext that uses a
468 | // full block's worth of padding, replace the final block with another
469 | // block. If the MAC check passed but the padding check failed, the
470 | // last byte of that block decrypted to the block size.
471 | //
472 | // See also macAndPaddingGood logic below.
473 | paddingLen &= good
474 |
475 | toRemove = int(paddingLen) + 1
476 | return
477 | }
478 |
--------------------------------------------------------------------------------
/http2/tls/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "crypto/tls"
6 | "fmt"
7 | "sync"
8 |
9 | "github.com/Isites/go-coder/http2/tls/handsh"
10 | )
11 |
12 | // 参考 http2configureTransport
13 | func clientTLSConf(certFile, keyFile string) (*tls.Config, error) {
14 | tlsConf := new(tls.Config)
15 | tlsConf.NextProtos = append(tlsConf.NextProtos, "h2", "http/1.1")
16 | tlsConf.Certificates = make([]tls.Certificate, 1)
17 | if len(certFile) > 0 && len(keyFile) > 0 {
18 | var err error
19 | tlsConf.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
20 | if err != nil {
21 | return nil, err
22 | }
23 | }
24 | // tlsConf.KeyLogWriter = handsh.KeyLog("client")
25 | return tlsConf, nil
26 | }
27 |
28 | // 参考 (srv *Server) ServeTLS( http2ConfigureServer
29 | func serverTLSConf(certFile, keyFile string) (*tls.Config, error) {
30 | tlsConf := new(tls.Config)
31 | tlsConf.PreferServerCipherSuites = true
32 | // support http2
33 | tlsConf.NextProtos = append(tlsConf.NextProtos, "h2", "http/1.1")
34 | // 准备证书
35 | tlsConf.Certificates = make([]tls.Certificate, 1)
36 | var err error
37 | tlsConf.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
38 | if err != nil {
39 | return nil, err
40 | }
41 | // tlsConf.KeyLogWriter = handsh.KeyLog("server")
42 | return tlsConf, nil
43 | }
44 |
45 | func main() {
46 | var wg sync.WaitGroup
47 | // server write and client read
48 | var s2c = new(bytes.Buffer)
49 | // client wirte and server read
50 | var c2s = new(bytes.Buffer)
51 | // server和client交替写,即每次只有一个人写,读也是同理
52 | var ch = make(chan int, 1)
53 | sconf, err := serverTLSConf("server.crt", "server.key")
54 | // sconf.ClientAuth = tls.RequireAndVerifyClientCert
55 | if err != nil {
56 | fmt.Println("init server tls conf", err)
57 | return
58 | }
59 | cconf, err := clientTLSConf("client.crt", "client.key")
60 | if err != nil {
61 | fmt.Println("init client tls conf", err)
62 | return
63 | }
64 | // 允许不安全证书验证
65 | cconf.InsecureSkipVerify = true
66 | cconf.Rand = &handsh.Rand{}
67 | sconf.Rand = &handsh.Rand{}
68 | praser := handsh.NewParser(cconf)
69 | sc := &handsh.TCPCon{
70 | Local: "127.0.0.1",
71 | Remote: "172.18.16.51",
72 | Wbuf: s2c,
73 | Rbuf: c2s,
74 | Wdone: ch,
75 | Rdone: ch,
76 | Praser: praser,
77 | }
78 | cs := &handsh.TCPCon{
79 | Local: "127.0.0.1",
80 | Remote: "172.18.16.51",
81 | Wbuf: c2s,
82 | Rbuf: s2c,
83 | Wdone: ch,
84 | Rdone: ch,
85 | IsClient: true,
86 | Praser: praser,
87 | }
88 | // 可以限制tls1.2,tls1.3和tls1.2流程不一样
89 | sconf.MaxVersion = tls.VersionTLS12
90 | server := tls.Server(sc, sconf)
91 | client := tls.Client(cs, cconf)
92 | wg.Add(2)
93 | // client
94 | go func() {
95 | if err := client.Handshake(); err != nil {
96 | fmt.Println("client handshake err", err)
97 | wg.Done()
98 | return
99 | }
100 | // fmt.Printf("client: %+v\n", client.ConnectionState())
101 | wg.Done()
102 | }()
103 | // server
104 | go func() {
105 | if err := server.Handshake(); err != nil {
106 | fmt.Println("server handshake err", err)
107 | wg.Done()
108 | return
109 | }
110 | // fmt.Printf("server: %+v\n", server.ConnectionState())
111 | wg.Done()
112 | }()
113 | wg.Wait()
114 | client.Write([]byte("点赞关注:Gopher指北"))
115 | close(ch)
116 | praser.LastCheck()
117 | }
118 |
--------------------------------------------------------------------------------
/http2/tls/root.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICtTCCAZ2gAwIBAgIJAPZhT8okABV/MA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
3 | BAMMBlhTSlpIUDAeFw0yMDExMDgxMjI4MzBaFw0yMTExMDgxMjI4MzBaMBExDzAN
4 | BgNVBAMMBlhTSlpIUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALiH
5 | 3gZuAsJqQsVfSQ5txZhLiPtlo+uuADXjZj8mDuT89eDSr0PbRfaETXLuGN/QTXhM
6 | qYXqIKOgB2w1Oo9g2e+hOmAOONGpNI2pwZXKIRETqf2UGnohXvbwDAMaN32xsnx9
7 | sCiCbXILPKSH/Sp4njsAtAtcmWPLfqblK+XNe0k9S+jxnCTxUKRqy9ieh8NLXdU4
8 | Lu+mNfz+mG/R9UQn0yxFQydt6O52C9ijfJi8szAd+mLsuIPN6PcTd1scWHmaPF0g
9 | R8gZ/NXZpolhO35w2GkrhnUm1zhBNnZu+0nWyTr+mGEGQctiIHflqfEkx1ApfqBP
10 | PFm58nCi0nBjBjwU2RECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B
11 | AQsFAAOCAQEAA1gqZGtIdhkm48IZZaodWIftRpvPIvXD6SDLPCJ3qqdSRpA3/PO9
12 | 0Jrg59dVWgZd2VifTlY05JoItIVps9T61oJfVohrgCvAa8s6JxzMDH7pvzj1yoI8
13 | Q3njbl7ynQdxR6zeQt2MpXr3xYbbD01lbjVYhxZZiUe9tpuiKJhBsoDM4l5YM7Nv
14 | PuZ1HgRCGWieHhs13td7thC2zeK7Xkakw+D8C9fHVRKbXKdXzxj2PIT2VqZ6fnUl
15 | Zn/Hm0yQCMH6ux8Q1TIbVkVw43JOfiU28M3zvYe1khACDMmCAqIhliPli8IdF/qd
16 | cAn9WDEZ2cK1zHq/DPgTmUunbKVeDcf1Pg==
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/http2/tls/root.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAuIfeBm4CwmpCxV9JDm3FmEuI+2Wj664ANeNmPyYO5Pz14NKv
3 | Q9tF9oRNcu4Y39BNeEypheogo6AHbDU6j2DZ76E6YA440ak0janBlcohEROp/ZQa
4 | eiFe9vAMAxo3fbGyfH2wKIJtcgs8pIf9KnieOwC0C1yZY8t+puUr5c17ST1L6PGc
5 | JPFQpGrL2J6Hw0td1Tgu76Y1/P6Yb9H1RCfTLEVDJ23o7nYL2KN8mLyzMB36Yuy4
6 | g83o9xN3WxxYeZo8XSBHyBn81dmmiWE7fnDYaSuGdSbXOEE2dm77SdbJOv6YYQZB
7 | y2Igd+Wp8STHUCl+oE88WbnycKLScGMGPBTZEQIDAQABAoIBAADjDksjnjnG/vkp
8 | 4xUBrBB2VHs42tfYJ0IbDLPDABFTse7ZtGP0Gtr7ec/SmyYAP08Tt0DghjWjIEYB
9 | 330u7v063if2CYngcVM4/Kg2p4AIgymn25S4slcngjdFmfytrPjyNbWMIvCIY0s7
10 | KBlbKQ+JilP/pvEW2k39Df/1w+DvO2K/Qq+6Mb9KKt/OPZ0Yh0KziEc/H+GyHVYY
11 | Mb1b1FNpEbUsNUhBbQw72kuqfmUswlqP3fHH3wXQDhzoi5sDLX+SGoiHkPGdlJpp
12 | ABsMzMOVwHGyoQVwiOOIs6DA7EDb6zcEXwyuORfeTvOfn28Sik79bpMBk40yFtbo
13 | IDvzTMECgYEA89zcpCaiJTnS7CVBXKiDORWdgrBCWv+CnH7vd9HS6fSXyPyZzWqW
14 | GLmCnjju/3Ah3JXCVTYFGnW/zG4uLJaSTBN7ycIrBjRgQiMY/BmuOihsTkec95Yy
15 | 1C7y/TOXC9BLve6pjC6JEeXzpvMcHglvLyO4/XdAlXvmj7jc73OcUOkCgYEAwbcJ
16 | PRUpZlmYjaPUS1bOWwM5+nJDPkkRfp2O6rYix7OzEfICD8KwkQ/Emn+rhOH+H/p/
17 | T0XOp8Cnb6DQfyQ5GSCEtmXAQUBWRLY/s5GJEVflZILP/nW3+JKV3gWMIL5ERCZO
18 | BtckAk4qO+/ASNAYRh22S4gkY6SR+MO+DPf8bekCgYEAqlnN0+mc+S40lnvL9gNN
19 | b5IW7tVb9R9qSRIvDF+J257ebStv8VwUr/7fLNIOumfFb8c58raCyCIbMp6BKOqi
20 | FfzCS4WU8oeh+nF0IZ964uucBO7nytikdy641YG1cS43yt0umVtkqxkcpLJNIPps
21 | LdzhfEZS2lmsDRgRVkBHoQkCgYAk9N1/WMUwMJGpHANJaEMwG9p4zEnF3TzIMhjs
22 | 8FiMTt0v5EK+bP8wfZidfRPk4xSPV0PohMHbQSbwZfbA+tEl2Q1Ymurlx/dtXnOi
23 | t3Y159XsqgQyYJT7iEOtOtOz/3iYo9Io/exxwCXQj3nYqlKnNc3sdQm0NNZgZj+g
24 | y8LN2QKBgQCxpQ3jl/sfZj9Tk+cilT8SK8xr3hg7bh7RXhLTiZe6xr5A3NAgzt8v
25 | GuwqM65AKW2yiThUtXIio/9dNcL3YwFZf/xCFjiywb1sW40xzT5Wlz5H25pnuXqt
26 | 5oaKLc1OETp78peQdt1JOeXvxzN2u0/eCPUoKY5nduWVW04uyjcPyw==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/http2/tls/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICyTCCAbGgAwIBAgIJANK2lGlkWdmKMA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
3 | BAMMBlhTSlpIUDAeFw0yMDExMDgxMjQ2MTdaFw0yMTExMDgxMjQ2MTdaMBMxETAP
4 | BgNVBAMMCFhTWkpIUC5TMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
5 | xNZpHKMJ+S0vCfU5XSY7FjJvmIcwauDcV7d/CjrK6z+TtlXcwdkfxn0BZzQoP2wN
6 | vamhDiaKDdHxrT7A6d4BbBs6VzufLjf2rS03swJW7pHjOJGAxaG95WG00pIEaXqV
7 | f8+IUlnLgL4l8Sv9cJKscZTutSFFzrE8WyfrnCuJRwrBEfaG3R+PIJHCqoGPqWfN
8 | YJfN3ElaCF9Pn4CNRv07wgRe+E4ZxylpugVMfpyNM5YYuKZrhvlB6A/Yc3CJIn0O
9 | HOmNLKWI3gq10lsq17SGUMqrVfJKmXkbxZbUryDnQ2vOFAFyXqD67hCfgAYDMzOA
10 | 1xQyjuQsBpxmXp4MCpPgXQIDAQABoyIwIDATBgNVHSUEDDAKBggrBgEFBQcDATAJ
11 | BgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBo6LRWMuOFxqlPfTYQuTCRV8X1
12 | 3pkFqF5NNBQn5TnH/QlsLqF9UNXSuSDG87eGBohm9nGgrTCzFlhQZ38SJRweWgF6
13 | J0b0VFOfw8bH73gu4MbLJIWHQuraUZEy+npcrN4m2fnZs5xr1nWSxYHwzkejVA40
14 | QK2/0H7QT4ThKYFm56aKu46OtreQk5Jf3VK/WV7fzDmGD/XtmhjubtMBdF2bZUmb
15 | Jc09IFU7NB2tibywRosZdsY8aff9VvTww5Z4Y/+Z/hSn61ESx7EeiOo83obRYGP0
16 | xHL1UFbm+/FW85QtHzoQkRvsvJd2zvB1xBBOawTrE2wyWYH4GDj/Ozw6zBQO
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/http2/tls/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAxNZpHKMJ+S0vCfU5XSY7FjJvmIcwauDcV7d/CjrK6z+TtlXc
3 | wdkfxn0BZzQoP2wNvamhDiaKDdHxrT7A6d4BbBs6VzufLjf2rS03swJW7pHjOJGA
4 | xaG95WG00pIEaXqVf8+IUlnLgL4l8Sv9cJKscZTutSFFzrE8WyfrnCuJRwrBEfaG
5 | 3R+PIJHCqoGPqWfNYJfN3ElaCF9Pn4CNRv07wgRe+E4ZxylpugVMfpyNM5YYuKZr
6 | hvlB6A/Yc3CJIn0OHOmNLKWI3gq10lsq17SGUMqrVfJKmXkbxZbUryDnQ2vOFAFy
7 | XqD67hCfgAYDMzOA1xQyjuQsBpxmXp4MCpPgXQIDAQABAoIBAE/GWilqBoO/hT3y
8 | 7gHLmczgOgxGViAq7AJ88vbxZwY66SHP4L2Lwu4OAcCTCfDSWStSEV0Lz43UVa+S
9 | LFtcR5VJ37Y1CsmPkuES320keJkN9Voa1mbCq5TIqaFh3nnlXavEL4q4q9qMthHt
10 | czTprQwHgUtVpdYkTMLhBgNwPZ3VjrjDslcTqE6brw1mGvCYDGZ+xvLcrb5BvF4I
11 | ZjEiWJUyHP82dQEIW/4oOyKblRBrbsCbAs188v2qsE2cIaJHYGR23VESDFymD3xK
12 | DR0bB0Tcll3D0pxtIyBF8vsVJUzb89vV9Xc9x+bmr4ngwOPDN8/7NALwLGzgH4sc
13 | NPcgIaECgYEA7SxjaNsQPmYTsmMnQZrKwclffc9i8u/A6xfvj4t9FdQC2mrBWPjg
14 | eOuTVlNfW6uUB13HLBq/Xik3Hz2FDoASwJc98bLzLhhaI8iZLapPM5w8/+7cA5HM
15 | OqLINbo8j4NepUak4d4kU8T/bhKLUfZGBtuhwbvilcsDCQHG0Aj1nwkCgYEA1HZb
16 | BZ2wDrHWYbEVCqaFZyEGbkd8ChkOtc0PWvUfRI3+QhqmCDNnw2pK5SsvFhnZMMjk
17 | 8KKnx5iWBwlAlPi+kpw4oqz81Zg46TjJdt4cVFXPtU6uaaXhBr/3fAIazfPzXFR7
18 | LCWp83qK8rdVe0TPhmxWyfAGZwZEA7S5ZNIjt7UCgYEA2M5b7W1bsv7TAJ4dM56R
19 | vIYdsb9Tv6olW4Mc7cZgSQTuusUeC/wuDruiiyZZpE37WqSCPrIQv73Dct5k9HVl
20 | LwLSkFC6dieytsVYKWNnVVF8faTXILg1zmAhzuN5GuPHMCSc8xCDesQ5j2CKVRlg
21 | uEIr4xKitbXIB4LFQEUAaykCgYBfHCSfHPoleeL4lKdQvz7U7enNEF8svg7hv8xx
22 | 8W1v6Qi7WuacoTaAOmMQuAY6JJQfzK8AMjBdn6b5u2CXz8qwIxMPb9U3YQ+JCAzY
23 | E5InBssW5QQa81ELDoChmOea7uwwlvkUyD+OaXsuMHgp2KH2ESXA/JxBHoLwDcU4
24 | pwGqSQKBgQCtFi7eNcbV6PqTUC7jSBOL7ZtJdHPXXqvvXMTYKR6RBMq3lTgUDJCh
25 | f9IMM5tkNPVaX+o9xPXAgJX0Z9IbgIV6jMvE7UktOdPtaDkYLdcj/AVRGwRyyKwh
26 | Gu+JiWVCaAY3Oo4j/BW+dzssmTJTVPK3D7nC8Tupo3CjRlqcF6xsrg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/httptrace/example/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "io"
7 | "net/http"
8 | xtrace "net/http/httptrace"
9 | "time"
10 |
11 | "github.com/Isites/go-coder/httptrace"
12 | )
13 |
14 | func main() {
15 |
16 | trace := httptrace.New("ReqTest")
17 | reqCtx, _ := context.WithTimeout(context.Background(), 800*time.Millisecond)
18 | // 增加请求trace
19 | traceCtx := xtrace.WithClientTrace(reqCtx, trace.ClientTrace)
20 | transsionReq, err := http.NewRequestWithContext(traceCtx, "GET", "http://www.baidu.com", nil)
21 | if err != nil {
22 | fmt.Println(err)
23 | return
24 | }
25 | rsp, err := http.DefaultClient.Do(transsionReq)
26 | trace.End()
27 | if err == nil {
28 | io.CopyN(io.Discard, rsp.Body, 2<<10)
29 | rsp.Body.Close()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/httptrace/trace.go:
--------------------------------------------------------------------------------
1 | package httptrace
2 |
3 | import (
4 | "crypto/tls"
5 | "fmt"
6 | "math"
7 | "net/http/httptrace"
8 | "strconv"
9 | "sync"
10 | "time"
11 | )
12 |
13 | type cost struct {
14 | st time.Time
15 | et time.Time
16 | }
17 |
18 | func (c *cost) cost() float64 {
19 | d := c.et.Sub(c.st)
20 | ms := d / time.Millisecond
21 | nsec := d % time.Millisecond
22 | ct := float64(ms) + float64(nsec)/1e6
23 | // 保留两位小数
24 | return math.Round(ct*100) / 100
25 | }
26 |
27 | type costDesc struct {
28 | field string
29 | cost float64
30 | }
31 |
32 | func (c *costDesc) desc() string {
33 | if c.cost < 0 {
34 | return c.field + "wait failed"
35 | }
36 | if c.cost == 9.22337203685478e+12 {
37 | return c.field + "wait failed"
38 | }
39 | return c.field + ": " + strconv.FormatFloat(c.cost, 'f', 2, 64)
40 | }
41 |
42 | // TimeStat 目前只做耗时统计
43 | type TimeStat struct {
44 | name string
45 | endTime time.Time
46 | // 在回调中可能存在并发调用,所以写时间时需要加锁
47 | mu sync.Mutex
48 | costs map[string]*cost
49 | // http请求过程中的回调信息
50 | *httptrace.ClientTrace
51 | }
52 |
53 | // 设置开始时间
54 | func (t *TimeStat) setStTime(key string, time time.Time) {
55 | t.mu.Lock()
56 | defer t.mu.Unlock()
57 | c, ok := t.costs[key]
58 | if !ok {
59 | c = &cost{}
60 | }
61 | c.st = time
62 | t.costs[key] = c
63 | }
64 |
65 | // 设置结束时间
66 | func (t *TimeStat) setEtTime(key string, time time.Time) {
67 | t.mu.Lock()
68 | defer t.mu.Unlock()
69 | c, ok := t.costs[key]
70 | if !ok {
71 | c = &cost{}
72 | }
73 | c.et = time
74 | t.costs[key] = c
75 | }
76 |
77 | // End 结束统计, 并输出相关信息
78 | func (t *TimeStat) End() {
79 | logs := t.calcCosts()
80 | fmt.Printf("%s req stat start\n", t.name)
81 | for _, l := range logs {
82 | fmt.Println(l.desc())
83 | }
84 | fmt.Printf("%s req stat end\n", t.name)
85 | }
86 |
87 | func (t *TimeStat) calcCosts() []costDesc {
88 | // 每次计算时 设置结束时间,以供后续使用
89 | t.endTime = time.Now()
90 | t.setEtTime("read_cost", t.endTime)
91 | t.setEtTime("total", t.endTime)
92 | // wait_cost: 将请求数据发送至网络一直到到收到响应
93 | // connect_total: 建立连接
94 | // dns_cost: 解析dns耗时
95 | // write_cost: 将数据发送至网络耗时
96 | // read_cost: 从收到第一字节响应到trace end,这中间不包含网络数据读取
97 | // total,从创建请求到调用trace end
98 | // 按顺序输出
99 | costKeys := []string{"connect_total", "dns_cost", "connect", "tls_cost", "write_cost", "wait_cost", "read_cost", "total"}
100 | logs := make([]costDesc, 0, len(costKeys)+1)
101 | // logs = append(logs, log.KVString("name", t.name))
102 | for _, key := range costKeys {
103 | if c, ok := t.costs[key]; ok {
104 | // 按照毫秒统计耗时
105 | logs = append(logs, costDesc{key, c.cost()})
106 | }
107 | }
108 | return logs
109 | }
110 |
111 | // 传入请求名称
112 | func New(name string) *TimeStat {
113 | ts := &TimeStat{
114 | name: name,
115 | costs: make(map[string]*cost),
116 | }
117 | // 初始化hook
118 | ts.ClientTrace = &httptrace.ClientTrace{
119 | DNSStart: DNSStart(ts),
120 | DNSDone: DNSDone(ts),
121 | GetConn: GetConn(ts),
122 | GotConn: GotConn(ts),
123 | ConnectStart: ConnectStart(ts),
124 | ConnectDone: ConnectDone(ts),
125 | TLSHandshakeStart: TLSHandshakeStart(ts),
126 | TLSHandshakeDone: TLSHandshakeDone(ts),
127 | WroteHeaderField: WroteHeaderField(ts),
128 | WroteHeaders: WroteHeaders(ts),
129 | WroteRequest: WroteRequest(ts),
130 | GotFirstResponseByte: GotFirstResponseByte(ts),
131 | }
132 | return ts
133 | }
134 |
135 | // DNSStart dns查找开始
136 | func DNSStart(t *TimeStat) func(httptrace.DNSStartInfo) {
137 | return func(dsi httptrace.DNSStartInfo) {
138 | t.setStTime("dns_cost", time.Now())
139 | }
140 | }
141 |
142 | // DNSDone dns查找结束
143 | func DNSDone(t *TimeStat) func(httptrace.DNSDoneInfo) {
144 | return func(ddi httptrace.DNSDoneInfo) {
145 | t.setEtTime("dns_cost", time.Now())
146 | }
147 | }
148 |
149 | // GetConn 开始获取连接
150 | func GetConn(t *TimeStat) func(string) {
151 | return func(hostPort string) {
152 | now := time.Now()
153 | t.setStTime("connect_total", now)
154 | t.setStTime("total", now)
155 | }
156 | }
157 |
158 | // GetConn 获取连接到连接(包含连接从连接池中获取到连接)
159 | // 如果是非服用连接则包含DNS解析时间和连接建立时间以及tls握手时间
160 | func GotConn(t *TimeStat) func(httptrace.GotConnInfo) {
161 | return func(gci httptrace.GotConnInfo) {
162 | t.setEtTime("connect_total", time.Now())
163 | }
164 | }
165 |
166 | // ConnectStart 建立连接,可能会被多次调用
167 | func ConnectStart(t *TimeStat) func(string, string) {
168 | return func(network, addr string) {
169 | t.setStTime("connect", time.Now())
170 | }
171 | }
172 |
173 | // ConnectDone 建立连接结束,可能会被多次调用
174 | func ConnectDone(t *TimeStat) func(string, string, error) {
175 | return func(network, addr string, err error) {
176 | t.setEtTime("connect", time.Now())
177 | }
178 | }
179 |
180 | // TLSHandshakeStart tls开始握手
181 | func TLSHandshakeStart(t *TimeStat) func() {
182 | return func() {
183 | t.setStTime("tls_cost", time.Now())
184 | }
185 | }
186 |
187 | // TLSHandshakeDone tls握手结束
188 | func TLSHandshakeDone(t *TimeStat) func(tls.ConnectionState, error) {
189 | return func(cs tls.ConnectionState, e error) {
190 | t.setEtTime("tls_cost", time.Now())
191 | }
192 | }
193 |
194 | // WroteHeaderField 每次写入一个header就调用一次, 此时header并不一定写入网络
195 | func WroteHeaderField(t *TimeStat) func(string, []string) {
196 | first := true
197 | return func(s1 string, s2 []string) {
198 | if first {
199 | t.setStTime("write_cost", time.Now())
200 | first = false
201 | }
202 | }
203 | }
204 |
205 | // WroteHeaders header 写入结束,并刷新缓冲到网络
206 | func WroteHeaders(t *TimeStat) func() {
207 | return func() {}
208 | }
209 |
210 | // WroteRequest 所有请求写入网络结束,如果是重试请求可能会写入多次
211 | func WroteRequest(t *TimeStat) func(httptrace.WroteRequestInfo) {
212 | return func(wri httptrace.WroteRequestInfo) {
213 | tm := time.Now()
214 | t.setEtTime("write_cost", tm)
215 | t.setStTime("wait_cost", tm)
216 | }
217 | }
218 |
219 | // GotFirstResponseByte 当读取到响应时
220 | func GotFirstResponseByte(t *TimeStat) func() {
221 | return func() {
222 | tm := time.Now()
223 | t.setStTime("read_cost", tm)
224 | t.setEtTime("wait_cost", tm)
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/money/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/shopspring/decimal"
7 | )
8 |
9 | // 表示小数位保留8位精度
10 | const prec = 100000000
11 |
12 | var decimalPrec = decimal.NewFromFloat(prec)
13 |
14 | func float2Int(f float64) int64 {
15 | return decimal.NewFromFloat(f).Mul(decimalPrec).IntPart()
16 | }
17 |
18 | func int2float(i int64) float64 {
19 | return float64(i) / prec
20 | }
21 |
22 | func main() {
23 | // 1元钱分给3个人,每个人分多少?
24 | var m float64 = float64(1) / 3
25 | fmt.Println(m, m+m+m)
26 | // 最后一人分得的钱使用减法
27 | m3 := 1 - m - m
28 | fmt.Println(m3, m+m+m3)
29 | // var (
30 | // a float64 = 123456789012345.678
31 | // b float64 = 1.23456789012345678
32 | // )
33 |
34 | // fmt.Println(a, b, decimal.NewFromFloat(a), a == 123456789012345.67)
35 | var (
36 | // 广告平台总共收入7.11美元
37 | fee float64 = 7.1100
38 | // 以下是不同渠道带来的点击数
39 | clkDetails = []int64{220, 127, 172, 1, 17, 1039, 1596, 200, 236, 151, 91, 87, 378, 289, 2, 14, 4, 439, 1, 2373, 90}
40 | totalClk int64
41 | )
42 | // 计算所有渠道带来的总点击数
43 | for _, c := range clkDetails {
44 | totalClk += c
45 | }
46 | var (
47 | floatTotal float64
48 | // 以浮点数计算每次点击的收益
49 | floatCPC float64 = fee / float64(totalClk)
50 | intTotal int64
51 | // 以8位精度的整形计算每次点击的收益(每次点击收益转为整形)
52 | intCPC int64 = float2Int(fee / float64(totalClk))
53 | intFloatTotal float64
54 | // 以8位进度的整形计算每次点击的收益(每次点击收益保留为浮点型)
55 | intFloatCPC float64 = float64(float2Int(fee)) / float64(totalClk)
56 | decimalTotal = decimal.Zero
57 | // 以decimal计算每次点击收益
58 | decimalCPC = decimal.NewFromFloat(fee).Div(decimal.NewFromInt(totalClk))
59 | )
60 | // 计算各渠道点击收益,并累加
61 | for _, c := range clkDetails {
62 | floatTotal += floatCPC * float64(c)
63 | intTotal += intCPC * c
64 | intFloatTotal += intFloatCPC * float64(c)
65 | decimalTotal = decimalTotal.Add(decimalCPC.Mul(decimal.NewFromInt(c)))
66 | }
67 | // 累加结果对比
68 | fmt.Println(floatTotal)
69 | fmt.Println(intTotal)
70 | fmt.Println(decimal.NewFromFloat(intFloatTotal).IntPart())
71 | fmt.Println(decimalTotal.InexactFloat64())
72 | }
73 |
--------------------------------------------------------------------------------
/pbjson/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 |
7 | "github.com/Isites/go-coder/pbjson/p3p2"
8 |
9 | "github.com/Isites/go-coder/pbjson/p3optional"
10 |
11 | "github.com/Isites/go-coder/pbjson/wrapper"
12 | "google.golang.org/protobuf/types/known/wrapperspb"
13 |
14 | "github.com/Isites/go-coder/pbjson/oneof"
15 | )
16 |
17 | func main() {
18 | // oneof to json
19 | ot1 := oneof.Test{
20 | Bar: 1,
21 | St: &oneof.Status{
22 | Show: &oneof.Status_IsShow{
23 | IsShow: 1,
24 | },
25 | },
26 | }
27 | bts, err := json.Marshal(ot1)
28 | fmt.Println(string(bts), err)
29 | // json to oneof failed
30 | jsonStr := `{"bar":1,"st":{"Show":{"is_show":1}}}`
31 | var ot2 oneof.Test
32 | fmt.Println(json.Unmarshal([]byte(jsonStr), &ot2))
33 |
34 | // wrapper to json, 注意:笔者实践得知gogoproto不支持此方法
35 | wra1 := wrapper.Test{
36 | Bar: 1,
37 | St: &wrapper.Status{
38 | IsShow: wrapperspb.Int32(1),
39 | },
40 | }
41 | bts, err = json.Marshal(wra1)
42 | fmt.Println(string(bts), err)
43 | jsonStr = `{"bar":1,"st":{"is_show":{"value":1}}}`
44 | // 可正常转json
45 | var wra2 wrapper.Test
46 | fmt.Println(json.Unmarshal([]byte(jsonStr), &wra2))
47 |
48 | // p3optional to json 注意:笔者实践得知gogoproto不支持此方法
49 | var isShow int32 = 1
50 | p3o1 := p3optional.Test{
51 | Bar: 1,
52 | St: &p3optional.Status{
53 | IsShow: &isShow,
54 | },
55 | }
56 | bts, err = json.Marshal(p3o1)
57 | fmt.Println(string(bts), err)
58 | var p3o2 p3optional.Test
59 | jsonStr = `{"bar":1,"st":{"is_show":1}}`
60 | fmt.Println(json.Unmarshal([]byte(jsonStr), &p3o2))
61 |
62 | // p3p2 to json
63 | p3p21 := p3p2.Test{
64 | Bar: 1,
65 | St: &p3p2.Status{
66 | IsShow: &isShow,
67 | },
68 | }
69 | bts, err = json.Marshal(p3p21)
70 | fmt.Println(string(bts), err)
71 | var p3p22 p3p2.Test
72 | jsonStr = `{"custom_tag":1,"st":{"is_show":1}}`
73 | fmt.Println(json.Unmarshal([]byte(jsonStr), &p3p22))
74 | }
75 |
--------------------------------------------------------------------------------
/pbjson/oneof/test.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 | // source: test.proto
3 |
4 | package oneof
5 |
6 | import (
7 | fmt "fmt"
8 | proto "github.com/gogo/protobuf/proto"
9 | io "io"
10 | math "math"
11 | math_bits "math/bits"
12 | )
13 |
14 | // Reference imports to suppress errors if they are not otherwise used.
15 | var _ = proto.Marshal
16 | var _ = fmt.Errorf
17 | var _ = math.Inf
18 |
19 | // This is a compile-time assertion to ensure that this generated file
20 | // is compatible with the proto package it is being compiled against.
21 | // A compilation error at this line likely means your copy of the
22 | // proto package needs to be updated.
23 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
24 |
25 | type Status struct {
26 | // Types that are valid to be assigned to Show:
27 | // *Status_IsShow
28 | Show isStatus_Show `protobuf_oneof:"show"`
29 | XXX_NoUnkeyedLiteral struct{} `json:"-"`
30 | XXX_unrecognized []byte `json:"-"`
31 | XXX_sizecache int32 `json:"-"`
32 | }
33 |
34 | func (m *Status) Reset() { *m = Status{} }
35 | func (m *Status) String() string { return proto.CompactTextString(m) }
36 | func (*Status) ProtoMessage() {}
37 | func (*Status) Descriptor() ([]byte, []int) {
38 | return fileDescriptor_c161fcfdc0c3ff1e, []int{0}
39 | }
40 | func (m *Status) XXX_Unmarshal(b []byte) error {
41 | return m.Unmarshal(b)
42 | }
43 | func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
44 | if deterministic {
45 | return xxx_messageInfo_Status.Marshal(b, m, deterministic)
46 | } else {
47 | b = b[:cap(b)]
48 | n, err := m.MarshalToSizedBuffer(b)
49 | if err != nil {
50 | return nil, err
51 | }
52 | return b[:n], nil
53 | }
54 | }
55 | func (m *Status) XXX_Merge(src proto.Message) {
56 | xxx_messageInfo_Status.Merge(m, src)
57 | }
58 | func (m *Status) XXX_Size() int {
59 | return m.Size()
60 | }
61 | func (m *Status) XXX_DiscardUnknown() {
62 | xxx_messageInfo_Status.DiscardUnknown(m)
63 | }
64 |
65 | var xxx_messageInfo_Status proto.InternalMessageInfo
66 |
67 | type isStatus_Show interface {
68 | isStatus_Show()
69 | MarshalTo([]byte) (int, error)
70 | Size() int
71 | }
72 |
73 | type Status_IsShow struct {
74 | IsShow int32 `protobuf:"varint,1,opt,name=is_show,json=isShow,proto3,oneof" json:"is_show,omitempty"`
75 | }
76 |
77 | func (*Status_IsShow) isStatus_Show() {}
78 |
79 | func (m *Status) GetShow() isStatus_Show {
80 | if m != nil {
81 | return m.Show
82 | }
83 | return nil
84 | }
85 |
86 | func (m *Status) GetIsShow() int32 {
87 | if x, ok := m.GetShow().(*Status_IsShow); ok {
88 | return x.IsShow
89 | }
90 | return 0
91 | }
92 |
93 | // XXX_OneofWrappers is for the internal use of the proto package.
94 | func (*Status) XXX_OneofWrappers() []interface{} {
95 | return []interface{}{
96 | (*Status_IsShow)(nil),
97 | }
98 | }
99 |
100 | type Test struct {
101 | Bar int32 `protobuf:"varint,1,opt,name=bar,proto3" json:"bar,omitempty"`
102 | St *Status `protobuf:"bytes,2,opt,name=st,proto3" json:"st,omitempty"`
103 | XXX_NoUnkeyedLiteral struct{} `json:"-"`
104 | XXX_unrecognized []byte `json:"-"`
105 | XXX_sizecache int32 `json:"-"`
106 | }
107 |
108 | func (m *Test) Reset() { *m = Test{} }
109 | func (m *Test) String() string { return proto.CompactTextString(m) }
110 | func (*Test) ProtoMessage() {}
111 | func (*Test) Descriptor() ([]byte, []int) {
112 | return fileDescriptor_c161fcfdc0c3ff1e, []int{1}
113 | }
114 | func (m *Test) XXX_Unmarshal(b []byte) error {
115 | return m.Unmarshal(b)
116 | }
117 | func (m *Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
118 | if deterministic {
119 | return xxx_messageInfo_Test.Marshal(b, m, deterministic)
120 | } else {
121 | b = b[:cap(b)]
122 | n, err := m.MarshalToSizedBuffer(b)
123 | if err != nil {
124 | return nil, err
125 | }
126 | return b[:n], nil
127 | }
128 | }
129 | func (m *Test) XXX_Merge(src proto.Message) {
130 | xxx_messageInfo_Test.Merge(m, src)
131 | }
132 | func (m *Test) XXX_Size() int {
133 | return m.Size()
134 | }
135 | func (m *Test) XXX_DiscardUnknown() {
136 | xxx_messageInfo_Test.DiscardUnknown(m)
137 | }
138 |
139 | var xxx_messageInfo_Test proto.InternalMessageInfo
140 |
141 | func (m *Test) GetBar() int32 {
142 | if m != nil {
143 | return m.Bar
144 | }
145 | return 0
146 | }
147 |
148 | func (m *Test) GetSt() *Status {
149 | if m != nil {
150 | return m.St
151 | }
152 | return nil
153 | }
154 |
155 | func init() {
156 | proto.RegisterType((*Status)(nil), "oneof.Status")
157 | proto.RegisterType((*Test)(nil), "oneof.Test")
158 | }
159 |
160 | func init() { proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e) }
161 |
162 | var fileDescriptor_c161fcfdc0c3ff1e = []byte{
163 | // 156 bytes of a gzipped FileDescriptorProto
164 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
165 | 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xcd, 0xcf, 0x4b, 0xcd, 0x4f, 0x53, 0xd2, 0xe6,
166 | 0x62, 0x0b, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0x16, 0x92, 0xe4, 0x62, 0xcf, 0x2c, 0x8e, 0x2f, 0xce,
167 | 0xc8, 0x2f, 0x97, 0x60, 0x54, 0x60, 0xd4, 0x60, 0xf5, 0x60, 0x08, 0x62, 0xcb, 0x2c, 0x0e, 0xce,
168 | 0xc8, 0x2f, 0x77, 0x62, 0xe3, 0x62, 0x01, 0x89, 0x2b, 0x99, 0x73, 0xb1, 0x84, 0xa4, 0x16, 0x97,
169 | 0x08, 0x09, 0x70, 0x31, 0x27, 0x25, 0x16, 0x41, 0x94, 0x05, 0x81, 0x98, 0x42, 0xb2, 0x5c, 0x4c,
170 | 0xc5, 0x25, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xbc, 0x7a, 0x60, 0xa3, 0xf5, 0x20, 0xe6,
171 | 0x06, 0x31, 0x15, 0x97, 0x38, 0x89, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83,
172 | 0x47, 0x72, 0x8c, 0x51, 0xec, 0x7a, 0xd6, 0x60, 0x15, 0x49, 0x6c, 0x60, 0xa7, 0x18, 0x03, 0x02,
173 | 0x00, 0x00, 0xff, 0xff, 0x66, 0xcc, 0xa6, 0x19, 0x98, 0x00, 0x00, 0x00,
174 | }
175 |
176 | func (m *Status) Marshal() (dAtA []byte, err error) {
177 | size := m.Size()
178 | dAtA = make([]byte, size)
179 | n, err := m.MarshalToSizedBuffer(dAtA[:size])
180 | if err != nil {
181 | return nil, err
182 | }
183 | return dAtA[:n], nil
184 | }
185 |
186 | func (m *Status) MarshalTo(dAtA []byte) (int, error) {
187 | size := m.Size()
188 | return m.MarshalToSizedBuffer(dAtA[:size])
189 | }
190 |
191 | func (m *Status) MarshalToSizedBuffer(dAtA []byte) (int, error) {
192 | i := len(dAtA)
193 | _ = i
194 | var l int
195 | _ = l
196 | if m.XXX_unrecognized != nil {
197 | i -= len(m.XXX_unrecognized)
198 | copy(dAtA[i:], m.XXX_unrecognized)
199 | }
200 | if m.Show != nil {
201 | {
202 | size := m.Show.Size()
203 | i -= size
204 | if _, err := m.Show.MarshalTo(dAtA[i:]); err != nil {
205 | return 0, err
206 | }
207 | }
208 | }
209 | return len(dAtA) - i, nil
210 | }
211 |
212 | func (m *Status_IsShow) MarshalTo(dAtA []byte) (int, error) {
213 | size := m.Size()
214 | return m.MarshalToSizedBuffer(dAtA[:size])
215 | }
216 |
217 | func (m *Status_IsShow) MarshalToSizedBuffer(dAtA []byte) (int, error) {
218 | i := len(dAtA)
219 | i = encodeVarintTest(dAtA, i, uint64(m.IsShow))
220 | i--
221 | dAtA[i] = 0x8
222 | return len(dAtA) - i, nil
223 | }
224 | func (m *Test) Marshal() (dAtA []byte, err error) {
225 | size := m.Size()
226 | dAtA = make([]byte, size)
227 | n, err := m.MarshalToSizedBuffer(dAtA[:size])
228 | if err != nil {
229 | return nil, err
230 | }
231 | return dAtA[:n], nil
232 | }
233 |
234 | func (m *Test) MarshalTo(dAtA []byte) (int, error) {
235 | size := m.Size()
236 | return m.MarshalToSizedBuffer(dAtA[:size])
237 | }
238 |
239 | func (m *Test) MarshalToSizedBuffer(dAtA []byte) (int, error) {
240 | i := len(dAtA)
241 | _ = i
242 | var l int
243 | _ = l
244 | if m.XXX_unrecognized != nil {
245 | i -= len(m.XXX_unrecognized)
246 | copy(dAtA[i:], m.XXX_unrecognized)
247 | }
248 | if m.St != nil {
249 | {
250 | size, err := m.St.MarshalToSizedBuffer(dAtA[:i])
251 | if err != nil {
252 | return 0, err
253 | }
254 | i -= size
255 | i = encodeVarintTest(dAtA, i, uint64(size))
256 | }
257 | i--
258 | dAtA[i] = 0x12
259 | }
260 | if m.Bar != 0 {
261 | i = encodeVarintTest(dAtA, i, uint64(m.Bar))
262 | i--
263 | dAtA[i] = 0x8
264 | }
265 | return len(dAtA) - i, nil
266 | }
267 |
268 | func encodeVarintTest(dAtA []byte, offset int, v uint64) int {
269 | offset -= sovTest(v)
270 | base := offset
271 | for v >= 1<<7 {
272 | dAtA[offset] = uint8(v&0x7f | 0x80)
273 | v >>= 7
274 | offset++
275 | }
276 | dAtA[offset] = uint8(v)
277 | return base
278 | }
279 | func (m *Status) Size() (n int) {
280 | if m == nil {
281 | return 0
282 | }
283 | var l int
284 | _ = l
285 | if m.Show != nil {
286 | n += m.Show.Size()
287 | }
288 | if m.XXX_unrecognized != nil {
289 | n += len(m.XXX_unrecognized)
290 | }
291 | return n
292 | }
293 |
294 | func (m *Status_IsShow) Size() (n int) {
295 | if m == nil {
296 | return 0
297 | }
298 | var l int
299 | _ = l
300 | n += 1 + sovTest(uint64(m.IsShow))
301 | return n
302 | }
303 | func (m *Test) Size() (n int) {
304 | if m == nil {
305 | return 0
306 | }
307 | var l int
308 | _ = l
309 | if m.Bar != 0 {
310 | n += 1 + sovTest(uint64(m.Bar))
311 | }
312 | if m.St != nil {
313 | l = m.St.Size()
314 | n += 1 + l + sovTest(uint64(l))
315 | }
316 | if m.XXX_unrecognized != nil {
317 | n += len(m.XXX_unrecognized)
318 | }
319 | return n
320 | }
321 |
322 | func sovTest(x uint64) (n int) {
323 | return (math_bits.Len64(x|1) + 6) / 7
324 | }
325 | func sozTest(x uint64) (n int) {
326 | return sovTest(uint64((x << 1) ^ uint64((int64(x) >> 63))))
327 | }
328 | func (m *Status) Unmarshal(dAtA []byte) error {
329 | l := len(dAtA)
330 | iNdEx := 0
331 | for iNdEx < l {
332 | preIndex := iNdEx
333 | var wire uint64
334 | for shift := uint(0); ; shift += 7 {
335 | if shift >= 64 {
336 | return ErrIntOverflowTest
337 | }
338 | if iNdEx >= l {
339 | return io.ErrUnexpectedEOF
340 | }
341 | b := dAtA[iNdEx]
342 | iNdEx++
343 | wire |= uint64(b&0x7F) << shift
344 | if b < 0x80 {
345 | break
346 | }
347 | }
348 | fieldNum := int32(wire >> 3)
349 | wireType := int(wire & 0x7)
350 | if wireType == 4 {
351 | return fmt.Errorf("proto: Status: wiretype end group for non-group")
352 | }
353 | if fieldNum <= 0 {
354 | return fmt.Errorf("proto: Status: illegal tag %d (wire type %d)", fieldNum, wire)
355 | }
356 | switch fieldNum {
357 | case 1:
358 | if wireType != 0 {
359 | return fmt.Errorf("proto: wrong wireType = %d for field IsShow", wireType)
360 | }
361 | var v int32
362 | for shift := uint(0); ; shift += 7 {
363 | if shift >= 64 {
364 | return ErrIntOverflowTest
365 | }
366 | if iNdEx >= l {
367 | return io.ErrUnexpectedEOF
368 | }
369 | b := dAtA[iNdEx]
370 | iNdEx++
371 | v |= int32(b&0x7F) << shift
372 | if b < 0x80 {
373 | break
374 | }
375 | }
376 | m.Show = &Status_IsShow{v}
377 | default:
378 | iNdEx = preIndex
379 | skippy, err := skipTest(dAtA[iNdEx:])
380 | if err != nil {
381 | return err
382 | }
383 | if skippy < 0 {
384 | return ErrInvalidLengthTest
385 | }
386 | if (iNdEx + skippy) < 0 {
387 | return ErrInvalidLengthTest
388 | }
389 | if (iNdEx + skippy) > l {
390 | return io.ErrUnexpectedEOF
391 | }
392 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
393 | iNdEx += skippy
394 | }
395 | }
396 |
397 | if iNdEx > l {
398 | return io.ErrUnexpectedEOF
399 | }
400 | return nil
401 | }
402 | func (m *Test) Unmarshal(dAtA []byte) error {
403 | l := len(dAtA)
404 | iNdEx := 0
405 | for iNdEx < l {
406 | preIndex := iNdEx
407 | var wire uint64
408 | for shift := uint(0); ; shift += 7 {
409 | if shift >= 64 {
410 | return ErrIntOverflowTest
411 | }
412 | if iNdEx >= l {
413 | return io.ErrUnexpectedEOF
414 | }
415 | b := dAtA[iNdEx]
416 | iNdEx++
417 | wire |= uint64(b&0x7F) << shift
418 | if b < 0x80 {
419 | break
420 | }
421 | }
422 | fieldNum := int32(wire >> 3)
423 | wireType := int(wire & 0x7)
424 | if wireType == 4 {
425 | return fmt.Errorf("proto: Test: wiretype end group for non-group")
426 | }
427 | if fieldNum <= 0 {
428 | return fmt.Errorf("proto: Test: illegal tag %d (wire type %d)", fieldNum, wire)
429 | }
430 | switch fieldNum {
431 | case 1:
432 | if wireType != 0 {
433 | return fmt.Errorf("proto: wrong wireType = %d for field Bar", wireType)
434 | }
435 | m.Bar = 0
436 | for shift := uint(0); ; shift += 7 {
437 | if shift >= 64 {
438 | return ErrIntOverflowTest
439 | }
440 | if iNdEx >= l {
441 | return io.ErrUnexpectedEOF
442 | }
443 | b := dAtA[iNdEx]
444 | iNdEx++
445 | m.Bar |= int32(b&0x7F) << shift
446 | if b < 0x80 {
447 | break
448 | }
449 | }
450 | case 2:
451 | if wireType != 2 {
452 | return fmt.Errorf("proto: wrong wireType = %d for field St", wireType)
453 | }
454 | var msglen int
455 | for shift := uint(0); ; shift += 7 {
456 | if shift >= 64 {
457 | return ErrIntOverflowTest
458 | }
459 | if iNdEx >= l {
460 | return io.ErrUnexpectedEOF
461 | }
462 | b := dAtA[iNdEx]
463 | iNdEx++
464 | msglen |= int(b&0x7F) << shift
465 | if b < 0x80 {
466 | break
467 | }
468 | }
469 | if msglen < 0 {
470 | return ErrInvalidLengthTest
471 | }
472 | postIndex := iNdEx + msglen
473 | if postIndex < 0 {
474 | return ErrInvalidLengthTest
475 | }
476 | if postIndex > l {
477 | return io.ErrUnexpectedEOF
478 | }
479 | if m.St == nil {
480 | m.St = &Status{}
481 | }
482 | if err := m.St.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
483 | return err
484 | }
485 | iNdEx = postIndex
486 | default:
487 | iNdEx = preIndex
488 | skippy, err := skipTest(dAtA[iNdEx:])
489 | if err != nil {
490 | return err
491 | }
492 | if skippy < 0 {
493 | return ErrInvalidLengthTest
494 | }
495 | if (iNdEx + skippy) < 0 {
496 | return ErrInvalidLengthTest
497 | }
498 | if (iNdEx + skippy) > l {
499 | return io.ErrUnexpectedEOF
500 | }
501 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
502 | iNdEx += skippy
503 | }
504 | }
505 |
506 | if iNdEx > l {
507 | return io.ErrUnexpectedEOF
508 | }
509 | return nil
510 | }
511 | func skipTest(dAtA []byte) (n int, err error) {
512 | l := len(dAtA)
513 | iNdEx := 0
514 | depth := 0
515 | for iNdEx < l {
516 | var wire uint64
517 | for shift := uint(0); ; shift += 7 {
518 | if shift >= 64 {
519 | return 0, ErrIntOverflowTest
520 | }
521 | if iNdEx >= l {
522 | return 0, io.ErrUnexpectedEOF
523 | }
524 | b := dAtA[iNdEx]
525 | iNdEx++
526 | wire |= (uint64(b) & 0x7F) << shift
527 | if b < 0x80 {
528 | break
529 | }
530 | }
531 | wireType := int(wire & 0x7)
532 | switch wireType {
533 | case 0:
534 | for shift := uint(0); ; shift += 7 {
535 | if shift >= 64 {
536 | return 0, ErrIntOverflowTest
537 | }
538 | if iNdEx >= l {
539 | return 0, io.ErrUnexpectedEOF
540 | }
541 | iNdEx++
542 | if dAtA[iNdEx-1] < 0x80 {
543 | break
544 | }
545 | }
546 | case 1:
547 | iNdEx += 8
548 | case 2:
549 | var length int
550 | for shift := uint(0); ; shift += 7 {
551 | if shift >= 64 {
552 | return 0, ErrIntOverflowTest
553 | }
554 | if iNdEx >= l {
555 | return 0, io.ErrUnexpectedEOF
556 | }
557 | b := dAtA[iNdEx]
558 | iNdEx++
559 | length |= (int(b) & 0x7F) << shift
560 | if b < 0x80 {
561 | break
562 | }
563 | }
564 | if length < 0 {
565 | return 0, ErrInvalidLengthTest
566 | }
567 | iNdEx += length
568 | case 3:
569 | depth++
570 | case 4:
571 | if depth == 0 {
572 | return 0, ErrUnexpectedEndOfGroupTest
573 | }
574 | depth--
575 | case 5:
576 | iNdEx += 4
577 | default:
578 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
579 | }
580 | if iNdEx < 0 {
581 | return 0, ErrInvalidLengthTest
582 | }
583 | if depth == 0 {
584 | return iNdEx, nil
585 | }
586 | }
587 | return 0, io.ErrUnexpectedEOF
588 | }
589 |
590 | var (
591 | ErrInvalidLengthTest = fmt.Errorf("proto: negative length found during unmarshaling")
592 | ErrIntOverflowTest = fmt.Errorf("proto: integer overflow")
593 | ErrUnexpectedEndOfGroupTest = fmt.Errorf("proto: unexpected end of group")
594 | )
595 |
--------------------------------------------------------------------------------
/pbjson/oneof/test.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package oneof;
4 |
5 | option go_package = ".;oneof";
6 |
7 |
8 | message Status {
9 | oneof show {
10 | int32 is_show = 1;
11 | }
12 | }
13 |
14 | message Test {
15 | int32 bar = 1;
16 | Status st = 2;
17 | }
--------------------------------------------------------------------------------
/pbjson/p3optional/testp3.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.23.0
4 | // protoc v3.14.0
5 | // source: testp3.proto
6 |
7 | package p3optional
8 |
9 | import (
10 | proto "github.com/golang/protobuf/proto"
11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
13 | reflect "reflect"
14 | sync "sync"
15 | )
16 |
17 | const (
18 | // Verify that this generated code is sufficiently up-to-date.
19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
20 | // Verify that runtime/protoimpl is sufficiently up-to-date.
21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
22 | )
23 |
24 | // This is a compile-time assertion that a sufficiently up-to-date version
25 | // of the legacy proto package is being used.
26 | const _ = proto.ProtoPackageIsVersion4
27 |
28 | type Status struct {
29 | state protoimpl.MessageState
30 | sizeCache protoimpl.SizeCache
31 | unknownFields protoimpl.UnknownFields
32 |
33 | IsShow *int32 `protobuf:"varint,1,opt,name=is_show,json=isShow,proto3,oneof" json:"is_show,omitempty"`
34 | }
35 |
36 | func (x *Status) Reset() {
37 | *x = Status{}
38 | if protoimpl.UnsafeEnabled {
39 | mi := &file_testp3_proto_msgTypes[0]
40 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
41 | ms.StoreMessageInfo(mi)
42 | }
43 | }
44 |
45 | func (x *Status) String() string {
46 | return protoimpl.X.MessageStringOf(x)
47 | }
48 |
49 | func (*Status) ProtoMessage() {}
50 |
51 | func (x *Status) ProtoReflect() protoreflect.Message {
52 | mi := &file_testp3_proto_msgTypes[0]
53 | if protoimpl.UnsafeEnabled && x != nil {
54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
55 | if ms.LoadMessageInfo() == nil {
56 | ms.StoreMessageInfo(mi)
57 | }
58 | return ms
59 | }
60 | return mi.MessageOf(x)
61 | }
62 |
63 | // Deprecated: Use Status.ProtoReflect.Descriptor instead.
64 | func (*Status) Descriptor() ([]byte, []int) {
65 | return file_testp3_proto_rawDescGZIP(), []int{0}
66 | }
67 |
68 | func (x *Status) GetIsShow() int32 {
69 | if x != nil && x.IsShow != nil {
70 | return *x.IsShow
71 | }
72 | return 0
73 | }
74 |
75 | type Test struct {
76 | state protoimpl.MessageState
77 | sizeCache protoimpl.SizeCache
78 | unknownFields protoimpl.UnknownFields
79 |
80 | Bar int32 `protobuf:"varint,1,opt,name=bar,proto3" json:"bar,omitempty"`
81 | St *Status `protobuf:"bytes,2,opt,name=st,proto3" json:"st,omitempty"`
82 | }
83 |
84 | func (x *Test) Reset() {
85 | *x = Test{}
86 | if protoimpl.UnsafeEnabled {
87 | mi := &file_testp3_proto_msgTypes[1]
88 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
89 | ms.StoreMessageInfo(mi)
90 | }
91 | }
92 |
93 | func (x *Test) String() string {
94 | return protoimpl.X.MessageStringOf(x)
95 | }
96 |
97 | func (*Test) ProtoMessage() {}
98 |
99 | func (x *Test) ProtoReflect() protoreflect.Message {
100 | mi := &file_testp3_proto_msgTypes[1]
101 | if protoimpl.UnsafeEnabled && x != nil {
102 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
103 | if ms.LoadMessageInfo() == nil {
104 | ms.StoreMessageInfo(mi)
105 | }
106 | return ms
107 | }
108 | return mi.MessageOf(x)
109 | }
110 |
111 | // Deprecated: Use Test.ProtoReflect.Descriptor instead.
112 | func (*Test) Descriptor() ([]byte, []int) {
113 | return file_testp3_proto_rawDescGZIP(), []int{1}
114 | }
115 |
116 | func (x *Test) GetBar() int32 {
117 | if x != nil {
118 | return x.Bar
119 | }
120 | return 0
121 | }
122 |
123 | func (x *Test) GetSt() *Status {
124 | if x != nil {
125 | return x.St
126 | }
127 | return nil
128 | }
129 |
130 | var File_testp3_proto protoreflect.FileDescriptor
131 |
132 | var file_testp3_proto_rawDesc = []byte{
133 | 0x0a, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x70, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a,
134 | 0x70, 0x33, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x32, 0x0a, 0x06, 0x53, 0x74,
135 | 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18,
136 | 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x88,
137 | 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x22, 0x3c,
138 | 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20,
139 | 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x22, 0x0a, 0x02, 0x73, 0x74, 0x18, 0x02,
140 | 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x33, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61,
141 | 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x02, 0x73, 0x74, 0x42, 0x0e, 0x5a, 0x0c,
142 | 0x2e, 0x3b, 0x70, 0x33, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72,
143 | 0x6f, 0x74, 0x6f, 0x33,
144 | }
145 |
146 | var (
147 | file_testp3_proto_rawDescOnce sync.Once
148 | file_testp3_proto_rawDescData = file_testp3_proto_rawDesc
149 | )
150 |
151 | func file_testp3_proto_rawDescGZIP() []byte {
152 | file_testp3_proto_rawDescOnce.Do(func() {
153 | file_testp3_proto_rawDescData = protoimpl.X.CompressGZIP(file_testp3_proto_rawDescData)
154 | })
155 | return file_testp3_proto_rawDescData
156 | }
157 |
158 | var file_testp3_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
159 | var file_testp3_proto_goTypes = []interface{}{
160 | (*Status)(nil), // 0: p3optional.Status
161 | (*Test)(nil), // 1: p3optional.Test
162 | }
163 | var file_testp3_proto_depIdxs = []int32{
164 | 0, // 0: p3optional.Test.st:type_name -> p3optional.Status
165 | 1, // [1:1] is the sub-list for method output_type
166 | 1, // [1:1] is the sub-list for method input_type
167 | 1, // [1:1] is the sub-list for extension type_name
168 | 1, // [1:1] is the sub-list for extension extendee
169 | 0, // [0:1] is the sub-list for field type_name
170 | }
171 |
172 | func init() { file_testp3_proto_init() }
173 | func file_testp3_proto_init() {
174 | if File_testp3_proto != nil {
175 | return
176 | }
177 | if !protoimpl.UnsafeEnabled {
178 | file_testp3_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
179 | switch v := v.(*Status); i {
180 | case 0:
181 | return &v.state
182 | case 1:
183 | return &v.sizeCache
184 | case 2:
185 | return &v.unknownFields
186 | default:
187 | return nil
188 | }
189 | }
190 | file_testp3_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
191 | switch v := v.(*Test); i {
192 | case 0:
193 | return &v.state
194 | case 1:
195 | return &v.sizeCache
196 | case 2:
197 | return &v.unknownFields
198 | default:
199 | return nil
200 | }
201 | }
202 | }
203 | file_testp3_proto_msgTypes[0].OneofWrappers = []interface{}{}
204 | type x struct{}
205 | out := protoimpl.TypeBuilder{
206 | File: protoimpl.DescBuilder{
207 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
208 | RawDescriptor: file_testp3_proto_rawDesc,
209 | NumEnums: 0,
210 | NumMessages: 2,
211 | NumExtensions: 0,
212 | NumServices: 0,
213 | },
214 | GoTypes: file_testp3_proto_goTypes,
215 | DependencyIndexes: file_testp3_proto_depIdxs,
216 | MessageInfos: file_testp3_proto_msgTypes,
217 | }.Build()
218 | File_testp3_proto = out.File
219 | file_testp3_proto_rawDesc = nil
220 | file_testp3_proto_goTypes = nil
221 | file_testp3_proto_depIdxs = nil
222 | }
223 |
--------------------------------------------------------------------------------
/pbjson/p3optional/testp3.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package p3optional;
4 |
5 | option go_package = ".;p3optional";
6 |
7 |
8 | message Status {
9 | optional int32 is_show = 1;
10 | }
11 |
12 | message Test {
13 | int32 bar = 1;
14 | Status st = 2;
15 | }
--------------------------------------------------------------------------------
/pbjson/p3p2/test2.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 | // source: test2.proto
3 |
4 | package p3p2
5 |
6 | import (
7 | fmt "fmt"
8 | proto "github.com/gogo/protobuf/proto"
9 | io "io"
10 | math "math"
11 | math_bits "math/bits"
12 | )
13 |
14 | // Reference imports to suppress errors if they are not otherwise used.
15 | var _ = proto.Marshal
16 | var _ = fmt.Errorf
17 | var _ = math.Inf
18 |
19 | // This is a compile-time assertion to ensure that this generated file
20 | // is compatible with the proto package it is being compiled against.
21 | // A compilation error at this line likely means your copy of the
22 | // proto package needs to be updated.
23 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
24 |
25 | type Status struct {
26 | IsShow *int32 `protobuf:"varint,2,opt,name=is_show,json=isShow" json:"is_show,omitempty"`
27 | XXX_NoUnkeyedLiteral struct{} `json:"-"`
28 | XXX_unrecognized []byte `json:"-"`
29 | XXX_sizecache int32 `json:"-"`
30 | }
31 |
32 | func (m *Status) Reset() { *m = Status{} }
33 | func (m *Status) String() string { return proto.CompactTextString(m) }
34 | func (*Status) ProtoMessage() {}
35 | func (*Status) Descriptor() ([]byte, []int) {
36 | return fileDescriptor_61e5535eff96cd18, []int{0}
37 | }
38 | func (m *Status) XXX_Unmarshal(b []byte) error {
39 | return m.Unmarshal(b)
40 | }
41 | func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
42 | if deterministic {
43 | return xxx_messageInfo_Status.Marshal(b, m, deterministic)
44 | } else {
45 | b = b[:cap(b)]
46 | n, err := m.MarshalToSizedBuffer(b)
47 | if err != nil {
48 | return nil, err
49 | }
50 | return b[:n], nil
51 | }
52 | }
53 | func (m *Status) XXX_Merge(src proto.Message) {
54 | xxx_messageInfo_Status.Merge(m, src)
55 | }
56 | func (m *Status) XXX_Size() int {
57 | return m.Size()
58 | }
59 | func (m *Status) XXX_DiscardUnknown() {
60 | xxx_messageInfo_Status.DiscardUnknown(m)
61 | }
62 |
63 | var xxx_messageInfo_Status proto.InternalMessageInfo
64 |
65 | func (m *Status) GetIsShow() int32 {
66 | if m != nil && m.IsShow != nil {
67 | return *m.IsShow
68 | }
69 | return 0
70 | }
71 |
72 | func init() {
73 | proto.RegisterType((*Status)(nil), "p3p2.Status")
74 | }
75 |
76 | func init() { proto.RegisterFile("test2.proto", fileDescriptor_61e5535eff96cd18) }
77 |
78 | var fileDescriptor_61e5535eff96cd18 = []byte{
79 | // 99 bytes of a gzipped FileDescriptorProto
80 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0x49, 0x2d, 0x2e,
81 | 0x31, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x29, 0x30, 0x2e, 0x30, 0x52, 0x52, 0xe4,
82 | 0x62, 0x0b, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0x16, 0x12, 0xe7, 0x62, 0xcf, 0x2c, 0x8e, 0x2f, 0xce,
83 | 0xc8, 0x2f, 0x97, 0x60, 0x52, 0x60, 0xd4, 0x60, 0x0d, 0x62, 0xcb, 0x2c, 0x0e, 0xce, 0xc8, 0x2f,
84 | 0x77, 0x12, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0xa3,
85 | 0xd8, 0xf4, 0xac, 0x41, 0x1a, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xea, 0x13, 0x8a, 0xc3, 0x4c,
86 | 0x00, 0x00, 0x00,
87 | }
88 |
89 | func (m *Status) Marshal() (dAtA []byte, err error) {
90 | size := m.Size()
91 | dAtA = make([]byte, size)
92 | n, err := m.MarshalToSizedBuffer(dAtA[:size])
93 | if err != nil {
94 | return nil, err
95 | }
96 | return dAtA[:n], nil
97 | }
98 |
99 | func (m *Status) MarshalTo(dAtA []byte) (int, error) {
100 | size := m.Size()
101 | return m.MarshalToSizedBuffer(dAtA[:size])
102 | }
103 |
104 | func (m *Status) MarshalToSizedBuffer(dAtA []byte) (int, error) {
105 | i := len(dAtA)
106 | _ = i
107 | var l int
108 | _ = l
109 | if m.XXX_unrecognized != nil {
110 | i -= len(m.XXX_unrecognized)
111 | copy(dAtA[i:], m.XXX_unrecognized)
112 | }
113 | if m.IsShow != nil {
114 | i = encodeVarintTest2(dAtA, i, uint64(*m.IsShow))
115 | i--
116 | dAtA[i] = 0x10
117 | }
118 | return len(dAtA) - i, nil
119 | }
120 |
121 | func encodeVarintTest2(dAtA []byte, offset int, v uint64) int {
122 | offset -= sovTest2(v)
123 | base := offset
124 | for v >= 1<<7 {
125 | dAtA[offset] = uint8(v&0x7f | 0x80)
126 | v >>= 7
127 | offset++
128 | }
129 | dAtA[offset] = uint8(v)
130 | return base
131 | }
132 | func (m *Status) Size() (n int) {
133 | if m == nil {
134 | return 0
135 | }
136 | var l int
137 | _ = l
138 | if m.IsShow != nil {
139 | n += 1 + sovTest2(uint64(*m.IsShow))
140 | }
141 | if m.XXX_unrecognized != nil {
142 | n += len(m.XXX_unrecognized)
143 | }
144 | return n
145 | }
146 |
147 | func sovTest2(x uint64) (n int) {
148 | return (math_bits.Len64(x|1) + 6) / 7
149 | }
150 | func sozTest2(x uint64) (n int) {
151 | return sovTest2(uint64((x << 1) ^ uint64((int64(x) >> 63))))
152 | }
153 | func (m *Status) Unmarshal(dAtA []byte) error {
154 | l := len(dAtA)
155 | iNdEx := 0
156 | for iNdEx < l {
157 | preIndex := iNdEx
158 | var wire uint64
159 | for shift := uint(0); ; shift += 7 {
160 | if shift >= 64 {
161 | return ErrIntOverflowTest2
162 | }
163 | if iNdEx >= l {
164 | return io.ErrUnexpectedEOF
165 | }
166 | b := dAtA[iNdEx]
167 | iNdEx++
168 | wire |= uint64(b&0x7F) << shift
169 | if b < 0x80 {
170 | break
171 | }
172 | }
173 | fieldNum := int32(wire >> 3)
174 | wireType := int(wire & 0x7)
175 | if wireType == 4 {
176 | return fmt.Errorf("proto: Status: wiretype end group for non-group")
177 | }
178 | if fieldNum <= 0 {
179 | return fmt.Errorf("proto: Status: illegal tag %d (wire type %d)", fieldNum, wire)
180 | }
181 | switch fieldNum {
182 | case 2:
183 | if wireType != 0 {
184 | return fmt.Errorf("proto: wrong wireType = %d for field IsShow", wireType)
185 | }
186 | var v int32
187 | for shift := uint(0); ; shift += 7 {
188 | if shift >= 64 {
189 | return ErrIntOverflowTest2
190 | }
191 | if iNdEx >= l {
192 | return io.ErrUnexpectedEOF
193 | }
194 | b := dAtA[iNdEx]
195 | iNdEx++
196 | v |= int32(b&0x7F) << shift
197 | if b < 0x80 {
198 | break
199 | }
200 | }
201 | m.IsShow = &v
202 | default:
203 | iNdEx = preIndex
204 | skippy, err := skipTest2(dAtA[iNdEx:])
205 | if err != nil {
206 | return err
207 | }
208 | if skippy < 0 {
209 | return ErrInvalidLengthTest2
210 | }
211 | if (iNdEx + skippy) < 0 {
212 | return ErrInvalidLengthTest2
213 | }
214 | if (iNdEx + skippy) > l {
215 | return io.ErrUnexpectedEOF
216 | }
217 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
218 | iNdEx += skippy
219 | }
220 | }
221 |
222 | if iNdEx > l {
223 | return io.ErrUnexpectedEOF
224 | }
225 | return nil
226 | }
227 | func skipTest2(dAtA []byte) (n int, err error) {
228 | l := len(dAtA)
229 | iNdEx := 0
230 | depth := 0
231 | for iNdEx < l {
232 | var wire uint64
233 | for shift := uint(0); ; shift += 7 {
234 | if shift >= 64 {
235 | return 0, ErrIntOverflowTest2
236 | }
237 | if iNdEx >= l {
238 | return 0, io.ErrUnexpectedEOF
239 | }
240 | b := dAtA[iNdEx]
241 | iNdEx++
242 | wire |= (uint64(b) & 0x7F) << shift
243 | if b < 0x80 {
244 | break
245 | }
246 | }
247 | wireType := int(wire & 0x7)
248 | switch wireType {
249 | case 0:
250 | for shift := uint(0); ; shift += 7 {
251 | if shift >= 64 {
252 | return 0, ErrIntOverflowTest2
253 | }
254 | if iNdEx >= l {
255 | return 0, io.ErrUnexpectedEOF
256 | }
257 | iNdEx++
258 | if dAtA[iNdEx-1] < 0x80 {
259 | break
260 | }
261 | }
262 | case 1:
263 | iNdEx += 8
264 | case 2:
265 | var length int
266 | for shift := uint(0); ; shift += 7 {
267 | if shift >= 64 {
268 | return 0, ErrIntOverflowTest2
269 | }
270 | if iNdEx >= l {
271 | return 0, io.ErrUnexpectedEOF
272 | }
273 | b := dAtA[iNdEx]
274 | iNdEx++
275 | length |= (int(b) & 0x7F) << shift
276 | if b < 0x80 {
277 | break
278 | }
279 | }
280 | if length < 0 {
281 | return 0, ErrInvalidLengthTest2
282 | }
283 | iNdEx += length
284 | case 3:
285 | depth++
286 | case 4:
287 | if depth == 0 {
288 | return 0, ErrUnexpectedEndOfGroupTest2
289 | }
290 | depth--
291 | case 5:
292 | iNdEx += 4
293 | default:
294 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
295 | }
296 | if iNdEx < 0 {
297 | return 0, ErrInvalidLengthTest2
298 | }
299 | if depth == 0 {
300 | return iNdEx, nil
301 | }
302 | }
303 | return 0, io.ErrUnexpectedEOF
304 | }
305 |
306 | var (
307 | ErrInvalidLengthTest2 = fmt.Errorf("proto: negative length found during unmarshaling")
308 | ErrIntOverflowTest2 = fmt.Errorf("proto: integer overflow")
309 | ErrUnexpectedEndOfGroupTest2 = fmt.Errorf("proto: unexpected end of group")
310 | )
311 |
--------------------------------------------------------------------------------
/pbjson/p3p2/test2.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package p3p2;
4 |
5 | option go_package = ".;p3p2";
6 |
7 |
8 | message Status {
9 | optional int32 is_show = 2;
10 | }
--------------------------------------------------------------------------------
/pbjson/p3p2/test3.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 | // source: test3.proto
3 |
4 | package p3p2
5 |
6 | import (
7 | fmt "fmt"
8 | _ "github.com/gogo/protobuf/gogoproto"
9 | proto "github.com/gogo/protobuf/proto"
10 | io "io"
11 | math "math"
12 | math_bits "math/bits"
13 | )
14 |
15 | // Reference imports to suppress errors if they are not otherwise used.
16 | var _ = proto.Marshal
17 | var _ = fmt.Errorf
18 | var _ = math.Inf
19 |
20 | // This is a compile-time assertion to ensure that this generated file
21 | // is compatible with the proto package it is being compiled against.
22 | // A compilation error at this line likely means your copy of the
23 | // proto package needs to be updated.
24 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
25 |
26 | type Test struct {
27 | Bar int32 `protobuf:"varint,1,opt,name=bar,proto3" json:"custom_tag" form:"more_bar"`
28 | St *Status `protobuf:"bytes,2,opt,name=st,proto3" json:"st,omitempty"`
29 | XXX_NoUnkeyedLiteral struct{} `json:"-"`
30 | XXX_unrecognized []byte `json:"-"`
31 | XXX_sizecache int32 `json:"-"`
32 | }
33 |
34 | func (m *Test) Reset() { *m = Test{} }
35 | func (m *Test) String() string { return proto.CompactTextString(m) }
36 | func (*Test) ProtoMessage() {}
37 | func (*Test) Descriptor() ([]byte, []int) {
38 | return fileDescriptor_ce14422a7e578aae, []int{0}
39 | }
40 | func (m *Test) XXX_Unmarshal(b []byte) error {
41 | return m.Unmarshal(b)
42 | }
43 | func (m *Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
44 | if deterministic {
45 | return xxx_messageInfo_Test.Marshal(b, m, deterministic)
46 | } else {
47 | b = b[:cap(b)]
48 | n, err := m.MarshalToSizedBuffer(b)
49 | if err != nil {
50 | return nil, err
51 | }
52 | return b[:n], nil
53 | }
54 | }
55 | func (m *Test) XXX_Merge(src proto.Message) {
56 | xxx_messageInfo_Test.Merge(m, src)
57 | }
58 | func (m *Test) XXX_Size() int {
59 | return m.Size()
60 | }
61 | func (m *Test) XXX_DiscardUnknown() {
62 | xxx_messageInfo_Test.DiscardUnknown(m)
63 | }
64 |
65 | var xxx_messageInfo_Test proto.InternalMessageInfo
66 |
67 | func (m *Test) GetBar() int32 {
68 | if m != nil {
69 | return m.Bar
70 | }
71 | return 0
72 | }
73 |
74 | func (m *Test) GetSt() *Status {
75 | if m != nil {
76 | return m.St
77 | }
78 | return nil
79 | }
80 |
81 | func init() {
82 | proto.RegisterType((*Test)(nil), "p3p2.Test")
83 | }
84 |
85 | func init() { proto.RegisterFile("test3.proto", fileDescriptor_ce14422a7e578aae) }
86 |
87 | var fileDescriptor_ce14422a7e578aae = []byte{
88 | // 222 bytes of a gzipped FileDescriptorProto
89 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0x49, 0x2d, 0x2e,
90 | 0x31, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x29, 0x30, 0x2e, 0x30, 0x92, 0x32, 0x4a,
91 | 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xf7, 0x2c, 0xce, 0x2c, 0x49, 0x2d,
92 | 0xd6, 0x4f, 0xcf, 0xd7, 0x4d, 0xce, 0x4f, 0x49, 0x2d, 0xd2, 0x2f, 0x48, 0xca, 0x2a, 0xce, 0xcf,
93 | 0xd3, 0x07, 0xa9, 0xd3, 0x07, 0xe9, 0x34, 0x82, 0xe8, 0x94, 0xd2, 0x45, 0xd2, 0x93, 0x9e, 0x9f,
94 | 0x9e, 0xaf, 0x0f, 0x16, 0x4e, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0xa2, 0x5c, 0x29,
95 | 0x92, 0x8b, 0x25, 0x24, 0xb5, 0xb8, 0x44, 0xc8, 0x98, 0x8b, 0x39, 0x29, 0xb1, 0x48, 0x82, 0x51,
96 | 0x81, 0x51, 0x83, 0xd5, 0x49, 0xf1, 0xd5, 0x3d, 0x79, 0xae, 0xe4, 0xd2, 0xe2, 0x92, 0xfc, 0xdc,
97 | 0xf8, 0x92, 0xc4, 0xf4, 0x4f, 0xf7, 0xe4, 0xf9, 0xd3, 0xf2, 0x8b, 0x72, 0xad, 0x94, 0x72, 0xf3,
98 | 0x8b, 0x52, 0xe3, 0x93, 0x12, 0x8b, 0x94, 0x82, 0x40, 0xaa, 0x85, 0x64, 0xb8, 0x98, 0x8a, 0x4b,
99 | 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8, 0x8d, 0x78, 0xf4, 0x40, 0x4e, 0xd1, 0x0b, 0x2e, 0x49, 0x2c,
100 | 0x29, 0x2d, 0x0e, 0x62, 0x2a, 0x2e, 0x71, 0x12, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
101 | 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0xa3, 0xd8, 0xf4, 0xac, 0x41, 0x0a, 0x92, 0xd8, 0xc0, 0xf6, 0x1a,
102 | 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x30, 0xf4, 0xa7, 0xb8, 0xef, 0x00, 0x00, 0x00,
103 | }
104 |
105 | func (m *Test) Marshal() (dAtA []byte, err error) {
106 | size := m.Size()
107 | dAtA = make([]byte, size)
108 | n, err := m.MarshalToSizedBuffer(dAtA[:size])
109 | if err != nil {
110 | return nil, err
111 | }
112 | return dAtA[:n], nil
113 | }
114 |
115 | func (m *Test) MarshalTo(dAtA []byte) (int, error) {
116 | size := m.Size()
117 | return m.MarshalToSizedBuffer(dAtA[:size])
118 | }
119 |
120 | func (m *Test) MarshalToSizedBuffer(dAtA []byte) (int, error) {
121 | i := len(dAtA)
122 | _ = i
123 | var l int
124 | _ = l
125 | if m.XXX_unrecognized != nil {
126 | i -= len(m.XXX_unrecognized)
127 | copy(dAtA[i:], m.XXX_unrecognized)
128 | }
129 | if m.St != nil {
130 | {
131 | size, err := m.St.MarshalToSizedBuffer(dAtA[:i])
132 | if err != nil {
133 | return 0, err
134 | }
135 | i -= size
136 | i = encodeVarintTest3(dAtA, i, uint64(size))
137 | }
138 | i--
139 | dAtA[i] = 0x12
140 | }
141 | if m.Bar != 0 {
142 | i = encodeVarintTest3(dAtA, i, uint64(m.Bar))
143 | i--
144 | dAtA[i] = 0x8
145 | }
146 | return len(dAtA) - i, nil
147 | }
148 |
149 | func encodeVarintTest3(dAtA []byte, offset int, v uint64) int {
150 | offset -= sovTest3(v)
151 | base := offset
152 | for v >= 1<<7 {
153 | dAtA[offset] = uint8(v&0x7f | 0x80)
154 | v >>= 7
155 | offset++
156 | }
157 | dAtA[offset] = uint8(v)
158 | return base
159 | }
160 | func (m *Test) Size() (n int) {
161 | if m == nil {
162 | return 0
163 | }
164 | var l int
165 | _ = l
166 | if m.Bar != 0 {
167 | n += 1 + sovTest3(uint64(m.Bar))
168 | }
169 | if m.St != nil {
170 | l = m.St.Size()
171 | n += 1 + l + sovTest3(uint64(l))
172 | }
173 | if m.XXX_unrecognized != nil {
174 | n += len(m.XXX_unrecognized)
175 | }
176 | return n
177 | }
178 |
179 | func sovTest3(x uint64) (n int) {
180 | return (math_bits.Len64(x|1) + 6) / 7
181 | }
182 | func sozTest3(x uint64) (n int) {
183 | return sovTest3(uint64((x << 1) ^ uint64((int64(x) >> 63))))
184 | }
185 | func (m *Test) Unmarshal(dAtA []byte) error {
186 | l := len(dAtA)
187 | iNdEx := 0
188 | for iNdEx < l {
189 | preIndex := iNdEx
190 | var wire uint64
191 | for shift := uint(0); ; shift += 7 {
192 | if shift >= 64 {
193 | return ErrIntOverflowTest3
194 | }
195 | if iNdEx >= l {
196 | return io.ErrUnexpectedEOF
197 | }
198 | b := dAtA[iNdEx]
199 | iNdEx++
200 | wire |= uint64(b&0x7F) << shift
201 | if b < 0x80 {
202 | break
203 | }
204 | }
205 | fieldNum := int32(wire >> 3)
206 | wireType := int(wire & 0x7)
207 | if wireType == 4 {
208 | return fmt.Errorf("proto: Test: wiretype end group for non-group")
209 | }
210 | if fieldNum <= 0 {
211 | return fmt.Errorf("proto: Test: illegal tag %d (wire type %d)", fieldNum, wire)
212 | }
213 | switch fieldNum {
214 | case 1:
215 | if wireType != 0 {
216 | return fmt.Errorf("proto: wrong wireType = %d for field Bar", wireType)
217 | }
218 | m.Bar = 0
219 | for shift := uint(0); ; shift += 7 {
220 | if shift >= 64 {
221 | return ErrIntOverflowTest3
222 | }
223 | if iNdEx >= l {
224 | return io.ErrUnexpectedEOF
225 | }
226 | b := dAtA[iNdEx]
227 | iNdEx++
228 | m.Bar |= int32(b&0x7F) << shift
229 | if b < 0x80 {
230 | break
231 | }
232 | }
233 | case 2:
234 | if wireType != 2 {
235 | return fmt.Errorf("proto: wrong wireType = %d for field St", wireType)
236 | }
237 | var msglen int
238 | for shift := uint(0); ; shift += 7 {
239 | if shift >= 64 {
240 | return ErrIntOverflowTest3
241 | }
242 | if iNdEx >= l {
243 | return io.ErrUnexpectedEOF
244 | }
245 | b := dAtA[iNdEx]
246 | iNdEx++
247 | msglen |= int(b&0x7F) << shift
248 | if b < 0x80 {
249 | break
250 | }
251 | }
252 | if msglen < 0 {
253 | return ErrInvalidLengthTest3
254 | }
255 | postIndex := iNdEx + msglen
256 | if postIndex < 0 {
257 | return ErrInvalidLengthTest3
258 | }
259 | if postIndex > l {
260 | return io.ErrUnexpectedEOF
261 | }
262 | if m.St == nil {
263 | m.St = &Status{}
264 | }
265 | if err := m.St.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
266 | return err
267 | }
268 | iNdEx = postIndex
269 | default:
270 | iNdEx = preIndex
271 | skippy, err := skipTest3(dAtA[iNdEx:])
272 | if err != nil {
273 | return err
274 | }
275 | if skippy < 0 {
276 | return ErrInvalidLengthTest3
277 | }
278 | if (iNdEx + skippy) < 0 {
279 | return ErrInvalidLengthTest3
280 | }
281 | if (iNdEx + skippy) > l {
282 | return io.ErrUnexpectedEOF
283 | }
284 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
285 | iNdEx += skippy
286 | }
287 | }
288 |
289 | if iNdEx > l {
290 | return io.ErrUnexpectedEOF
291 | }
292 | return nil
293 | }
294 | func skipTest3(dAtA []byte) (n int, err error) {
295 | l := len(dAtA)
296 | iNdEx := 0
297 | depth := 0
298 | for iNdEx < l {
299 | var wire uint64
300 | for shift := uint(0); ; shift += 7 {
301 | if shift >= 64 {
302 | return 0, ErrIntOverflowTest3
303 | }
304 | if iNdEx >= l {
305 | return 0, io.ErrUnexpectedEOF
306 | }
307 | b := dAtA[iNdEx]
308 | iNdEx++
309 | wire |= (uint64(b) & 0x7F) << shift
310 | if b < 0x80 {
311 | break
312 | }
313 | }
314 | wireType := int(wire & 0x7)
315 | switch wireType {
316 | case 0:
317 | for shift := uint(0); ; shift += 7 {
318 | if shift >= 64 {
319 | return 0, ErrIntOverflowTest3
320 | }
321 | if iNdEx >= l {
322 | return 0, io.ErrUnexpectedEOF
323 | }
324 | iNdEx++
325 | if dAtA[iNdEx-1] < 0x80 {
326 | break
327 | }
328 | }
329 | case 1:
330 | iNdEx += 8
331 | case 2:
332 | var length int
333 | for shift := uint(0); ; shift += 7 {
334 | if shift >= 64 {
335 | return 0, ErrIntOverflowTest3
336 | }
337 | if iNdEx >= l {
338 | return 0, io.ErrUnexpectedEOF
339 | }
340 | b := dAtA[iNdEx]
341 | iNdEx++
342 | length |= (int(b) & 0x7F) << shift
343 | if b < 0x80 {
344 | break
345 | }
346 | }
347 | if length < 0 {
348 | return 0, ErrInvalidLengthTest3
349 | }
350 | iNdEx += length
351 | case 3:
352 | depth++
353 | case 4:
354 | if depth == 0 {
355 | return 0, ErrUnexpectedEndOfGroupTest3
356 | }
357 | depth--
358 | case 5:
359 | iNdEx += 4
360 | default:
361 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
362 | }
363 | if iNdEx < 0 {
364 | return 0, ErrInvalidLengthTest3
365 | }
366 | if depth == 0 {
367 | return iNdEx, nil
368 | }
369 | }
370 | return 0, io.ErrUnexpectedEOF
371 | }
372 |
373 | var (
374 | ErrInvalidLengthTest3 = fmt.Errorf("proto: negative length found during unmarshaling")
375 | ErrIntOverflowTest3 = fmt.Errorf("proto: integer overflow")
376 | ErrUnexpectedEndOfGroupTest3 = fmt.Errorf("proto: unexpected end of group")
377 | )
378 |
--------------------------------------------------------------------------------
/pbjson/p3p2/test3.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package p3p2;
4 |
5 | option go_package = ".;p3p2";
6 |
7 |
8 | import "github.com/Isites/go-coder/pbjson/p3p2/test2.proto";
9 | import "github.com/gogo/protobuf/gogoproto/gogo.proto";
10 |
11 |
12 | message Test {
13 | int32 bar = 1 [(gogoproto.moretags) = 'form:"more_bar"', (gogoproto.jsontag) = 'custom_tag'];
14 | p3p2.Status st = 2;
15 | }
--------------------------------------------------------------------------------
/pbjson/wrapper/test.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.23.0
4 | // protoc v3.14.0
5 | // source: test.proto
6 |
7 | package wrapper
8 |
9 | import (
10 | proto "github.com/golang/protobuf/proto"
11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
13 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
14 | reflect "reflect"
15 | sync "sync"
16 | )
17 |
18 | const (
19 | // Verify that this generated code is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
21 | // Verify that runtime/protoimpl is sufficiently up-to-date.
22 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
23 | )
24 |
25 | // This is a compile-time assertion that a sufficiently up-to-date version
26 | // of the legacy proto package is being used.
27 | const _ = proto.ProtoPackageIsVersion4
28 |
29 | type Status struct {
30 | state protoimpl.MessageState
31 | sizeCache protoimpl.SizeCache
32 | unknownFields protoimpl.UnknownFields
33 |
34 | IsShow *wrapperspb.Int32Value `protobuf:"bytes,1,opt,name=is_show,json=isShow,proto3" json:"is_show,omitempty"`
35 | }
36 |
37 | func (x *Status) Reset() {
38 | *x = Status{}
39 | if protoimpl.UnsafeEnabled {
40 | mi := &file_test_proto_msgTypes[0]
41 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
42 | ms.StoreMessageInfo(mi)
43 | }
44 | }
45 |
46 | func (x *Status) String() string {
47 | return protoimpl.X.MessageStringOf(x)
48 | }
49 |
50 | func (*Status) ProtoMessage() {}
51 |
52 | func (x *Status) ProtoReflect() protoreflect.Message {
53 | mi := &file_test_proto_msgTypes[0]
54 | if protoimpl.UnsafeEnabled && x != nil {
55 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
56 | if ms.LoadMessageInfo() == nil {
57 | ms.StoreMessageInfo(mi)
58 | }
59 | return ms
60 | }
61 | return mi.MessageOf(x)
62 | }
63 |
64 | // Deprecated: Use Status.ProtoReflect.Descriptor instead.
65 | func (*Status) Descriptor() ([]byte, []int) {
66 | return file_test_proto_rawDescGZIP(), []int{0}
67 | }
68 |
69 | func (x *Status) GetIsShow() *wrapperspb.Int32Value {
70 | if x != nil {
71 | return x.IsShow
72 | }
73 | return nil
74 | }
75 |
76 | type Test struct {
77 | state protoimpl.MessageState
78 | sizeCache protoimpl.SizeCache
79 | unknownFields protoimpl.UnknownFields
80 |
81 | Bar int32 `protobuf:"varint,1,opt,name=bar,proto3" json:"bar,omitempty"`
82 | St *Status `protobuf:"bytes,2,opt,name=st,proto3" json:"st,omitempty"`
83 | }
84 |
85 | func (x *Test) Reset() {
86 | *x = Test{}
87 | if protoimpl.UnsafeEnabled {
88 | mi := &file_test_proto_msgTypes[1]
89 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
90 | ms.StoreMessageInfo(mi)
91 | }
92 | }
93 |
94 | func (x *Test) String() string {
95 | return protoimpl.X.MessageStringOf(x)
96 | }
97 |
98 | func (*Test) ProtoMessage() {}
99 |
100 | func (x *Test) ProtoReflect() protoreflect.Message {
101 | mi := &file_test_proto_msgTypes[1]
102 | if protoimpl.UnsafeEnabled && x != nil {
103 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
104 | if ms.LoadMessageInfo() == nil {
105 | ms.StoreMessageInfo(mi)
106 | }
107 | return ms
108 | }
109 | return mi.MessageOf(x)
110 | }
111 |
112 | // Deprecated: Use Test.ProtoReflect.Descriptor instead.
113 | func (*Test) Descriptor() ([]byte, []int) {
114 | return file_test_proto_rawDescGZIP(), []int{1}
115 | }
116 |
117 | func (x *Test) GetBar() int32 {
118 | if x != nil {
119 | return x.Bar
120 | }
121 | return 0
122 | }
123 |
124 | func (x *Test) GetSt() *Status {
125 | if x != nil {
126 | return x.St
127 | }
128 | return nil
129 | }
130 |
131 | var File_test_proto protoreflect.FileDescriptor
132 |
133 | var file_test_proto_rawDesc = []byte{
134 | 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x77, 0x72,
135 | 0x61, 0x70, 0x70, 0x65, 0x72, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
136 | 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e,
137 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3e, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
138 | 0x34, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
139 | 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
140 | 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x69,
141 | 0x73, 0x53, 0x68, 0x6f, 0x77, 0x22, 0x39, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a,
142 | 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x12,
143 | 0x1f, 0x0a, 0x02, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x72,
144 | 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x02, 0x73, 0x74,
145 | 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x62, 0x06, 0x70,
146 | 0x72, 0x6f, 0x74, 0x6f, 0x33,
147 | }
148 |
149 | var (
150 | file_test_proto_rawDescOnce sync.Once
151 | file_test_proto_rawDescData = file_test_proto_rawDesc
152 | )
153 |
154 | func file_test_proto_rawDescGZIP() []byte {
155 | file_test_proto_rawDescOnce.Do(func() {
156 | file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData)
157 | })
158 | return file_test_proto_rawDescData
159 | }
160 |
161 | var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
162 | var file_test_proto_goTypes = []interface{}{
163 | (*Status)(nil), // 0: wrapper.Status
164 | (*Test)(nil), // 1: wrapper.Test
165 | (*wrapperspb.Int32Value)(nil), // 2: google.protobuf.Int32Value
166 | }
167 | var file_test_proto_depIdxs = []int32{
168 | 2, // 0: wrapper.Status.is_show:type_name -> google.protobuf.Int32Value
169 | 0, // 1: wrapper.Test.st:type_name -> wrapper.Status
170 | 2, // [2:2] is the sub-list for method output_type
171 | 2, // [2:2] is the sub-list for method input_type
172 | 2, // [2:2] is the sub-list for extension type_name
173 | 2, // [2:2] is the sub-list for extension extendee
174 | 0, // [0:2] is the sub-list for field type_name
175 | }
176 |
177 | func init() { file_test_proto_init() }
178 | func file_test_proto_init() {
179 | if File_test_proto != nil {
180 | return
181 | }
182 | if !protoimpl.UnsafeEnabled {
183 | file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
184 | switch v := v.(*Status); i {
185 | case 0:
186 | return &v.state
187 | case 1:
188 | return &v.sizeCache
189 | case 2:
190 | return &v.unknownFields
191 | default:
192 | return nil
193 | }
194 | }
195 | file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
196 | switch v := v.(*Test); i {
197 | case 0:
198 | return &v.state
199 | case 1:
200 | return &v.sizeCache
201 | case 2:
202 | return &v.unknownFields
203 | default:
204 | return nil
205 | }
206 | }
207 | }
208 | type x struct{}
209 | out := protoimpl.TypeBuilder{
210 | File: protoimpl.DescBuilder{
211 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
212 | RawDescriptor: file_test_proto_rawDesc,
213 | NumEnums: 0,
214 | NumMessages: 2,
215 | NumExtensions: 0,
216 | NumServices: 0,
217 | },
218 | GoTypes: file_test_proto_goTypes,
219 | DependencyIndexes: file_test_proto_depIdxs,
220 | MessageInfos: file_test_proto_msgTypes,
221 | }.Build()
222 | File_test_proto = out.File
223 | file_test_proto_rawDesc = nil
224 | file_test_proto_goTypes = nil
225 | file_test_proto_depIdxs = nil
226 | }
227 |
--------------------------------------------------------------------------------
/pbjson/wrapper/test.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package wrapper;
4 |
5 | option go_package = ".;wrapper";
6 |
7 | import "google/protobuf/wrappers.proto";
8 |
9 | message Status {
10 | google.protobuf.Int32Value is_show = 1;
11 | }
12 |
13 |
14 | message Test {
15 | int32 bar = 1;
16 | Status st = 2;
17 | }
--------------------------------------------------------------------------------
/qrcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Isites/go-coder/659b17c131ca41bea84ad71ecad0fc116f846116/qrcode.jpg
--------------------------------------------------------------------------------
/receiver/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type set interface {
8 | set1(s string)
9 | set2(s string)
10 | }
11 |
12 | type test struct {
13 | s string
14 | }
15 |
16 | func (t *test) set1(s string) {
17 | t.s = s
18 | }
19 |
20 | func (t test) set2(s string) {
21 | t.s = s
22 | }
23 |
24 | type los string
25 |
26 | func (s los) p1() {
27 | fmt.Println(s)
28 | }
29 |
30 | func (s *los) p2() {
31 | fmt.Println(s)
32 | }
33 |
34 | func main() {
35 | // 例子一
36 | var (
37 | t1 test
38 | t2 = new(test)
39 | )
40 | t1.set1("1")
41 | fmt.Print(t1.s)
42 | t1.set2("2")
43 | fmt.Print(t1.s)
44 | t2.set1("3")
45 | fmt.Print(t2.s)
46 | t2.set2("4")
47 | fmt.Print(t2.s)
48 | fmt.Print(" ")
49 | _, ok1 := (interface{}(t1)).(set)
50 | _, ok2 := (interface{}(t2)).(set)
51 | fmt.Println(ok1, ok2)
52 | // 例子二
53 | var s1 los = "1111"
54 | var s2 *los = &s1
55 | const s3 los = "3333"
56 | s1.p1()
57 | s1.p2()
58 | s2.p1()
59 | s2.p2()
60 | s3.p1()
61 | // s3.p2() // 注释以防止无法运行
62 | }
63 |
--------------------------------------------------------------------------------
/slice/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | "unsafe"
7 | )
8 |
9 | type mySlice struct {
10 | data uintptr
11 | len int
12 | cap int
13 | }
14 |
15 | func otherOP(a, b *int) {
16 | // 确保逃逸到堆
17 | reflect.ValueOf(a)
18 | reflect.ValueOf(b)
19 | }
20 |
21 | func main() {
22 | // 切片强转为结构体
23 | s := mySlice{}
24 | fmt.Println(fmt.Sprintf("%+v", s))
25 | s1 := make([]int, 10)
26 | s1[2] = 2
27 | fmt.Println(fmt.Sprintf("%+v, len(%d), cap(%d)", s1, len(s1), cap(s1)))
28 | s = *(*mySlice)(unsafe.Pointer(&s1))
29 | fmt.Println(fmt.Sprintf("%+v", s))
30 | fmt.Printf("%p, %v\n", s1, unsafe.Pointer(s.data))
31 |
32 | // 修改数组中的值
33 | //Data强转为一个数组
34 | s2 := (*[5]int)(unsafe.Pointer(s.data))
35 | s3 := (*[10]int)(unsafe.Pointer(s.data))
36 | // 修改数组中的数据后切片中对应位置的值也发生了变化
37 | s2[4] = 4
38 | fmt.Println(s1)
39 | fmt.Println(*s2)
40 | fmt.Println(*s3)
41 |
42 | // 结构体转为切片
43 | var (
44 | // 一个长度为5的数组
45 | dt [5]int
46 | s4 []int
47 | )
48 | s5 := mySlice{
49 | // 将数组地址赋值给data
50 | data: uintptr(unsafe.Pointer(&dt)),
51 | len: 2,
52 | cap: 5,
53 | }
54 | // 结构体强转为切片
55 | s4 = *((*[]int)(unsafe.Pointer(&s5)))
56 | fmt.Println(s4, len(s4), cap(s4))
57 | // 修改数组中的值, 切片内容也会发生变化
58 | dt[1] = 3
59 | fmt.Println(dt, s4)
60 |
61 | // 为什么不安全
62 | var (
63 | a = new(int)
64 | b = new(int)
65 | )
66 | otherOP(a, b)
67 | *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(a)) + unsafe.Sizeof(int(*a)))) = 1
68 | fmt.Println(*a, *b)
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/ssrf/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "io"
7 | "io/ioutil"
8 | "net"
9 | "net/http"
10 | "net/url"
11 | "syscall"
12 | )
13 |
14 | func readAndClose(resp *http.Response, err error) {
15 | if err != nil {
16 | fmt.Println(err)
17 | return
18 | }
19 | io.CopyN(ioutil.Discard, resp.Body, 2<<10)
20 | fmt.Println("resp status code:", resp.StatusCode)
21 | resp.Body.Close()
22 | }
23 |
24 | // IsLocalIP 判断是否是内网ip
25 | func IsLocalIP(ip net.IP) bool {
26 | if ip == nil {
27 | return false
28 | }
29 | // 判断是否是回环地址, ipv4时是127.0.0.1;ipv6时是::1
30 | if ip.IsLoopback() {
31 | return true
32 | }
33 | // 判断ipv4是否是内网
34 | if ip4 := ip.To4(); ip4 != nil {
35 | return ip4[0] == 10 || // 10.0.0.0/8
36 | (ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12
37 | (ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16
38 | }
39 | // 判断ipv6是否是内网
40 | if ip16 := ip.To16(); ip16 != nil {
41 | // 参考 https://tools.ietf.org/html/rfc4193#section-3
42 | // 参考 https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses
43 | // 判断ipv6唯一本地地址
44 | return 0xfd == ip16[0]
45 | }
46 | // 不是ip直接返回false
47 | return false
48 | }
49 |
50 | func main() {
51 | checkList := []string{
52 | "http://0266.075.0310.07/",
53 | "http://www.192.168.3.6.xip.io",
54 | "http://www.baidu.com@192.168.1.3",
55 | "http://0xc0.0xa8.774",
56 | "http://182.4048903",
57 | }
58 | for _, reqURL := range checkList {
59 | uri, err := url.Parse(reqURL)
60 | if err != nil {
61 | fmt.Println(err)
62 | continue
63 | }
64 | ips, err := net.LookupIP(uri.Hostname())
65 | if err != nil {
66 | fmt.Println(err)
67 | continue
68 | }
69 | for _, ip := range ips {
70 | fmt.Printf("%s -> %s is localip?: %v\n", uri.Hostname(), ip.String(), IsLocalIP(ip))
71 | }
72 | }
73 | // 自定义CheckRedirect
74 | client := &http.Client{
75 | CheckRedirect: func(req *http.Request, via []*http.Request) error {
76 | // 跳转超过10次,也拒绝继续跳转
77 | if len(via) >= 10 {
78 | return fmt.Errorf("redirect too much")
79 | }
80 | statusCode := req.Response.StatusCode
81 | if statusCode == 307 || statusCode == 308 {
82 | // 拒绝跳转访问
83 | return fmt.Errorf("unsupport redirect method")
84 | }
85 | // 判断ip
86 | ips, err := net.LookupIP(req.URL.Host)
87 | if err != nil {
88 | return err
89 | }
90 | for _, ip := range ips {
91 | if IsLocalIP(ip) {
92 | return fmt.Errorf("have local ip")
93 | }
94 | fmt.Printf("%s -> %s is localip?: %v\n", req.URL, ip.String(), IsLocalIP(ip))
95 | }
96 | return nil
97 | },
98 | }
99 | // 以taobao域名为例发出请求
100 | readAndClose(client.Get("http://taobao.com"))
101 | // 方案一:修改transport的DialContext
102 | // copy from http.
103 | dialer := &net.Dialer{}
104 | // copy from http.DefaultTransport
105 | transport := http.DefaultTransport.(*http.Transport).Clone()
106 | transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
107 | host, port, err := net.SplitHostPort(addr)
108 | // 解析host和 端口
109 | if err != nil {
110 | return nil, err
111 | }
112 | // dns解析域名
113 | ips, err := net.LookupIP(host)
114 | if err != nil {
115 | return nil, err
116 | }
117 | // 对所有的ip进行串行发起请求
118 | for _, ip := range ips {
119 | fmt.Printf("%v -> %v is localip?: %v\n", addr, ip.String(), IsLocalIP(ip))
120 | if IsLocalIP(ip) {
121 | continue
122 | }
123 | // 拼接地址
124 | addr := net.JoinHostPort(ip.String(), port)
125 | con, err := dialer.DialContext(ctx, network, addr)
126 | if err == nil {
127 | return con, nil
128 | }
129 | fmt.Println(err)
130 | }
131 |
132 | return nil, fmt.Errorf("connect failed")
133 | }
134 | client1 := &http.Client{
135 | Transport: transport,
136 | }
137 | readAndClose(client1.Get("http://taobao.com"))
138 | // 方案二, 修改transport的Control
139 | dialer.Control = func(network, address string, c syscall.RawConn) error {
140 | host, _, err := net.SplitHostPort(address)
141 | if err != nil {
142 | return err
143 | }
144 | fmt.Printf("%v is localip?: %v\n", address, IsLocalIP(net.ParseIP(host)))
145 | return nil
146 | }
147 | // clone 一次避免链接复用
148 | transport = transport.Clone()
149 | transport.DialContext = dialer.DialContext
150 | client2 := &http.Client{
151 | Transport: transport,
152 | }
153 | readAndClose(client2.Get("http://taobao.com"))
154 | }
155 |
--------------------------------------------------------------------------------
/strs/cache.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "sync"
5 | "time"
6 | )
7 |
8 | type cacheItem struct {
9 | data interface{}
10 | expiredAt int64
11 | }
12 |
13 | // IsExpired 判断缓存内容是否到期
14 | func (c *cacheItem) IsExpired() bool {
15 | return c.expiredAt > 0 && time.Now().Unix() >= c.expiredAt
16 | }
17 |
18 | func (c *cacheItem) Data() interface{} {
19 | return c.data
20 | }
21 |
22 | var (
23 | cacheMap sync.Map
24 | )
25 |
26 | // Set 设置缓存
27 | func Set(key string, val interface{}, expiredAt int64) {
28 | cv := &cacheItem{val, expiredAt}
29 | cacheMap.Store(key, cv)
30 | }
31 |
32 | // Get 得到缓存中的值
33 | func Get(key string) (interface{}, bool) {
34 | // 不存在缓存
35 | cv, isExists := cacheMap.Load(key)
36 | if !isExists {
37 | return nil, false
38 | }
39 | // 缓存不正确
40 | citem, ok := cv.(*cacheItem)
41 | if !ok {
42 | return nil, false
43 | }
44 | // 读数据时删除缓存
45 | if citem.IsExpired() {
46 | cacheMap.Delete(key)
47 | return nil, false
48 | }
49 | // 最后返回结果
50 | return citem.Data(), true
51 | }
52 |
--------------------------------------------------------------------------------
/strs/lru.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "math/rand"
5 | "sync"
6 | )
7 |
8 | type lruCacheItem struct {
9 | prev, next *lruCacheItem
10 | data interface{}
11 | key string
12 | }
13 |
14 | type lruc struct {
15 | head, tail *lruCacheItem
16 | lruMap map[string]*lruCacheItem
17 | rw sync.RWMutex
18 | size int64
19 | }
20 |
21 | func NewLRU(size int64) *lruc {
22 | if size < 0 {
23 | size = 100
24 | }
25 | lru := &lruc{
26 | head: new(lruCacheItem),
27 | tail: new(lruCacheItem),
28 | lruMap: make(map[string]*lruCacheItem),
29 | size: size,
30 | }
31 | lru.head.next = lru.tail
32 | lru.tail.prev = lru.head
33 | return lru
34 | }
35 |
36 | func (lru *lruc) Get(key string) (interface{}, bool) {
37 | lru.rw.RLock()
38 | v, ok := lru.lruMap[key]
39 | lru.rw.RUnlock()
40 |
41 | if ok {
42 | // move to head.next 1
43 | // lru.rw.Lock()
44 | // v.prev.next = v.next
45 | // v.next.prev = v.prev
46 |
47 | // v.prev = lru.head
48 | // v.next = lru.head.next
49 | // lru.head.next = v
50 | // lru.rw.Unlock()
51 | // move to head.next 2
52 | if len(lru.lruMap) > int(lru.size)-1 && rand.Int()%100 == 1 {
53 | lru.rw.Lock()
54 | v.prev.next = v.next
55 | v.next.prev = v.prev
56 |
57 | v.prev = lru.head
58 | v.next = lru.head.next
59 | lru.head.next = v
60 | lru.rw.Unlock()
61 | }
62 | return v.data, true
63 | }
64 | return nil, false
65 | }
66 |
67 | func (lru *lruc) Set(key string, v interface{}) {
68 | // fast path
69 | if _, exist := lru.lruMap[key]; exist {
70 | return
71 | }
72 | node := &lruCacheItem{
73 | data: v,
74 | prev: lru.head,
75 | next: lru.head.next,
76 | key: key,
77 | }
78 | // add first
79 | lru.rw.Lock()
80 | // double check
81 | if _, exist := lru.lruMap[key]; !exist {
82 | lru.lruMap[key] = node
83 | lru.head.next = node
84 | node.next.prev = node
85 | }
86 | if len(lru.lruMap) > int(lru.size) {
87 | // delete tail
88 | prev := lru.tail.prev
89 | prev.prev.next = lru.tail
90 | lru.tail.prev = prev.prev
91 | delete(lru.lruMap, prev.key)
92 | }
93 | lru.rw.Unlock()
94 | }
95 |
--------------------------------------------------------------------------------
/strs/version_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "runtime/pprof"
6 | "strconv"
7 | "strings"
8 | "testing"
9 | "time"
10 |
11 | lru "github.com/hashicorp/golang-lru"
12 | )
13 |
14 | // 判断是否全为0
15 | func zeroRune(s []rune) bool {
16 | for _, r := range s {
17 | if r != '0' && r != '.' {
18 | return false
19 | }
20 | }
21 | return true
22 | }
23 |
24 | func CompareVersionNoSplit(ver1, ver2 string) (ret int) {
25 | defer func() {
26 | if ret > 0 {
27 | ret = 1
28 | } else if ret < 0 {
29 | ret = -1
30 | }
31 | }()
32 | if ver1 == ver2 {
33 | return 0
34 | }
35 | rv1, rv2 := []rune(ver1), []rune(ver2)
36 | var (
37 | l1, l2 = len(ver1), len(ver2)
38 | i, j = 0, 0
39 | )
40 | for i < l1 && j < l2 {
41 | if rv1[i] == rv2[j] {
42 | i++
43 | j++
44 | continue
45 | }
46 | k := diffPart(i, rv1)
47 | rv1Str := string(rv1[i:k])
48 | curV1, e1 := strconv.Atoi(rv1Str)
49 | i = k
50 | k = diffPart(j, rv2)
51 | rv2Str := string(rv2[j:k])
52 | curV2, e2 := strconv.Atoi(rv2Str)
53 | j = k
54 | if e1 != nil || e2 != nil {
55 | ret = strings.Compare(rv1Str, rv2Str)
56 | } else {
57 | ret = curV1 - curV2
58 | }
59 | if ret != 0 {
60 | return ret
61 | }
62 | }
63 | if i < l1 {
64 | if zeroRune(rv1[i:]) {
65 | return 0
66 | }
67 | ret = 1
68 | } else if j < l2 {
69 | if zeroRune(rv2[j:]) {
70 | return 0
71 | }
72 | ret = -1
73 | }
74 | return ret
75 | }
76 |
77 | func diffPart(i int, rv []rune) (j int) {
78 | j = i
79 | for j = i; j < len(rv); j++ {
80 | // if rv[j] == '0' {
81 | // offset++
82 | // }
83 | if rv[j] == '.' {
84 | return j
85 | }
86 | }
87 | return j
88 | }
89 |
90 | // CompareVersion 比较两个appversion的大小
91 | // return 0 means ver1 == ver2
92 | // return 1 means ver1 > ver2
93 | // return -1 means ver1 < ver2
94 | func CompareVersion(ver1, ver2 string) int {
95 | // fast path
96 | if ver1 == ver2 {
97 | return 0
98 | }
99 | // slow path
100 | vers1 := strings.Split(ver1, ".")
101 | vers2 := strings.Split(ver2, ".")
102 | var (
103 | v1l, v2l = len(vers1), len(vers2)
104 | i = 0
105 | )
106 | for ; i < v1l && i < v2l; i++ {
107 | a, e1 := strconv.Atoi(vers1[i])
108 | b, e2 := strconv.Atoi(vers2[i])
109 | res := 0
110 | // 如果不能转换为数字,使用go默认的字符串比较
111 | if e1 != nil || e2 != nil {
112 | res = strings.Compare(vers1[i], vers2[i])
113 | } else {
114 | res = a - b
115 | }
116 | // 根据比较结果进行返回, 如果res=0,则此部分相等
117 | if res > 0 {
118 | return 1
119 | } else if res < 0 {
120 | return -1
121 | }
122 | }
123 | // 最后谁仍有剩余且不为0,则谁大
124 | if i < v1l {
125 | for ; i < v1l; i++ {
126 | if !zeroRune([]rune(vers1[i])) {
127 | return 1
128 | }
129 | }
130 | } else if i < v2l {
131 | for ; i < v2l; i++ {
132 | if !zeroRune([]rune(vers2[i])) {
133 | return -1
134 | }
135 | }
136 | }
137 | return 0
138 | }
139 |
140 | type cmVal struct {
141 | iv int
142 | sv string
143 | // 能否转换为整形
144 | canInt bool
145 | }
146 |
147 | func strs2cmVs(strs []string) []*cmVal {
148 | cmvs := make([]*cmVal, 0, len(strs))
149 | for _, v := range strs {
150 | it, e := strconv.Atoi(v)
151 | // 全部数据都保存
152 | cmvs = append(cmvs, &cmVal{it, v, e == nil})
153 | }
154 | return cmvs
155 | }
156 |
157 | var (
158 | lruC, _ = lru.New(500)
159 | slru = NewLRU(10)
160 | )
161 |
162 | // CompareVersion 比较两个appversion的大小
163 | // return 0 means ver1 == ver2
164 | // return 1 means ver1 > ver2
165 | // return -1 means ver1 < ver2
166 | func CompareVersionWithCache1(ver1, ver2 string) int {
167 | // fast path
168 | if ver1 == ver2 {
169 | return 0
170 | }
171 | // slow path
172 | var (
173 | cmv1, cmv2 []*cmVal
174 | cmv1Exists, cmv2Exists bool
175 | expire int64 = 200 * 60
176 | )
177 | // read cache 1
178 | cmv, cmvExists := Get(ver1)
179 | if cmvExists {
180 | cmv1, cmv1Exists = cmv.([]*cmVal)
181 | }
182 | if !cmv1Exists {
183 | // set val and cache
184 | cmv1 = strs2cmVs(strings.Split(ver1, "."))
185 | Set(ver1, cmv1, time.Now().Unix()+expire)
186 | }
187 | // read cache 2
188 | cmv, cmvExists = Get(ver2)
189 | if cmvExists {
190 | cmv2, cmv2Exists = cmv.([]*cmVal)
191 | }
192 | if !cmv2Exists {
193 | // set val and cache
194 | cmv2 = strs2cmVs(strings.Split(ver2, "."))
195 | Set(ver2, cmv2, time.Now().Unix()+expire)
196 | }
197 | // compare ver str
198 | var (
199 | v1l, v2l = len(cmv1), len(cmv2)
200 | i = 0
201 | )
202 | for ; i < len(cmv1) && i < len(cmv2); i++ {
203 | res := 0
204 | // can use int compare
205 | if cmv1[i].canInt && cmv2[i].canInt {
206 | res = cmv1[i].iv - cmv2[i].iv
207 | } else {
208 | res = strings.Compare(cmv1[i].sv, cmv2[i].sv)
209 | }
210 | if res > 0 {
211 | return 1
212 | } else if res < 0 {
213 | return -1
214 | }
215 | }
216 | // 比较剩余部分,且剩余部分不为0
217 | if i < v1l {
218 | for ; i < v1l; i++ {
219 | if cmv1[i].canInt && cmv1[i].iv != 0 {
220 | return 1
221 | }
222 | if !zeroRune([]rune(cmv1[i].sv)) {
223 | return 1
224 | }
225 | }
226 | } else if i < v2l {
227 | for ; i < v2l; i++ {
228 | for ; i < v1l; i++ {
229 | if cmv2[i].canInt && cmv2[i].iv != 0 {
230 | return -1
231 | }
232 | if !zeroRune([]rune(cmv2[i].sv)) {
233 | return -1
234 | }
235 | }
236 | }
237 | }
238 | return 0
239 | }
240 |
241 | func CompareVersionWithCache2(ver1, ver2 string) int {
242 | // fast path
243 | if ver1 == ver2 {
244 | return 0
245 | }
246 | // slow path
247 | var (
248 | cmv1, cmv2 []*cmVal
249 | cmv1Exists, cmv2Exists bool
250 | // expire int64 = 200 * 60
251 | )
252 | // read cache 1
253 | cmv, cmvExists := lruC.Get(ver1)
254 | if cmvExists {
255 | cmv1, cmv1Exists = cmv.([]*cmVal)
256 | }
257 | if !cmv1Exists {
258 | // set val and cache
259 | cmv1 = strs2cmVs(strings.Split(ver1, "."))
260 | lruC.Add(ver1, cmv1)
261 | }
262 | // read cache 2
263 | cmv, cmvExists = lruC.Get(ver2)
264 | if cmvExists {
265 | cmv2, cmv2Exists = cmv.([]*cmVal)
266 | }
267 | if !cmv2Exists {
268 | // set val and cache
269 | cmv2 = strs2cmVs(strings.Split(ver2, "."))
270 | lruC.Add(ver2, cmv2)
271 | }
272 | // compare ver str
273 | v1l, v2l := len(cmv1), len(cmv2)
274 | for i := 0; i < len(cmv1) && i < len(cmv2); i++ {
275 | res := 0
276 | // can use int compare
277 | if cmv1[i].canInt && cmv2[i].canInt {
278 | res = cmv1[i].iv - cmv2[i].iv
279 | } else {
280 | res = strings.Compare(cmv1[i].sv, cmv2[i].sv)
281 | }
282 | if res > 0 {
283 | return 1
284 | } else if res < 0 {
285 | return -1
286 | }
287 | }
288 | if v1l > v2l {
289 | return 1
290 | } else if v1l < v2l {
291 | return -1
292 | }
293 | return 0
294 | }
295 |
296 | func CompareVersionWithCache3(ver1, ver2 string) int {
297 | // fast path
298 | if ver1 == ver2 {
299 | return 0
300 | }
301 | // slow path
302 | var (
303 | cmv1, cmv2 []*cmVal
304 | cmv1Exists, cmv2Exists bool
305 | // expire int64 = 200 * 60
306 | )
307 | // read cache 1
308 | cmv, cmvExists := slru.Get(ver1)
309 | if cmvExists {
310 | cmv1, cmv1Exists = cmv.([]*cmVal)
311 | }
312 | if !cmv1Exists {
313 | // set val and cache
314 | cmv1 = strs2cmVs(strings.Split(ver1, "."))
315 | slru.Set(ver1, cmv1)
316 | }
317 | // read cache 2
318 | cmv, cmvExists = slru.Get(ver2)
319 | if cmvExists {
320 | cmv2, cmv2Exists = cmv.([]*cmVal)
321 | }
322 | if !cmv2Exists {
323 | // set val and cache
324 | cmv2 = strs2cmVs(strings.Split(ver2, "."))
325 | slru.Set(ver2, cmv2)
326 | }
327 | // compare ver str
328 | v1l, v2l := len(cmv1), len(cmv2)
329 | for i := 0; i < len(cmv1) && i < len(cmv2); i++ {
330 | res := 0
331 | // can use int compare
332 | if cmv1[i].canInt && cmv2[i].canInt {
333 | res = cmv1[i].iv - cmv2[i].iv
334 | } else {
335 | res = strings.Compare(cmv1[i].sv, cmv2[i].sv)
336 | }
337 | if res > 0 {
338 | return 1
339 | } else if res < 0 {
340 | return -1
341 | }
342 | }
343 | if v1l > v2l {
344 | return 1
345 | } else if v1l < v2l {
346 | return -1
347 | }
348 | return 0
349 | }
350 |
351 | func TestMain(m *testing.M) {
352 | f, _ := os.Create("compare_ver.pprof")
353 | pprof.StartCPUProfile(f)
354 | defer pprof.StopCPUProfile()
355 | m.Run()
356 | }
357 |
358 | func BenchmarkCompareVersion(b *testing.B) {
359 | b.ResetTimer()
360 | for i := 0; i < b.N; i++ {
361 | CompareVersion("7.0.09.000", "7.0.09")
362 | CompareVersion("7.0.08.9999", "7.0.09.9999")
363 | CompareVersion("9.01", "9.0")
364 | }
365 | }
366 |
367 | // func BenchmarkCompareVersionWithCache1(b *testing.B) {
368 | // b.ResetTimer()
369 | // for i := 0; i < b.N; i++ {
370 | // CompareVersionWithCache1("7.0.09.000", "7.0.09")
371 | // CompareVersionWithCache1("7.0.08.9999", "7.0.09.9999")
372 | // CompareVersionWithCache1("9.01", "9.0")
373 | // }
374 | // }
375 |
376 | // func BenchmarkCompareVersionWithCache2(b *testing.B) {
377 | // b.ResetTimer()
378 | // for i := 0; i < b.N; i++ {
379 | // CompareVersionWithCache2("7.0.09.000", "7.0.09")
380 | // CompareVersionWithCache2("7.0.08.9999", "7.0.09.9999")
381 | // CompareVersionWithCache2("9.01", "9.0")
382 | // }
383 | // }
384 |
385 | func BenchmarkCompareVersionWithCache3(b *testing.B) {
386 | b.ResetTimer()
387 | for i := 0; i < b.N; i++ {
388 | CompareVersionWithCache3("7.0.09.000", "7.0.09")
389 | CompareVersionWithCache3("7.0.08.9999", "7.0.09.9999")
390 | CompareVersionWithCache3("9.01", "9.0")
391 | }
392 | }
393 |
394 | func BenchmarkCompareVersionNoSplit(b *testing.B) {
395 | b.ResetTimer()
396 | for i := 0; i < b.N; i++ {
397 | CompareVersionNoSplit("7.0.09.000", "7.0.09")
398 | CompareVersionNoSplit("7.0.08.9999", "7.0.09.9999")
399 | CompareVersionNoSplit("9.01", "9.0")
400 | }
401 | }
402 |
403 | // func BenchmarkSplit(b *testing.B) {
404 | // b.ResetTimer()
405 | // for i := 0; i < b.N; i++ {
406 | // strings.Split("7.0.09.000", ".")
407 | // strings.Split("7.0.09", ".")
408 | // strings.Split("9.01", ".")
409 | // }
410 | // }
411 |
412 | // func BenchmarkFieldsFunc(b *testing.B) {
413 | // b.ResetTimer()
414 | // for i := 0; i < b.N; i++ {
415 | // strings.FieldsFunc("7.0.09.000", func(r rune) bool { return r == '.' })
416 | // strings.FieldsFunc("7.0.09", func(r rune) bool { return r == '.' })
417 | // strings.FieldsFunc("9.01", func(r rune) bool { return r == '.' })
418 | // }
419 | // }
420 |
--------------------------------------------------------------------------------
/types/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/Isites/go-coder/types/ttt"
7 | )
8 |
9 | type blankSt struct {
10 | a int
11 | _ string
12 | }
13 |
14 | type blankSt1 struct {
15 | a int `json:"a"`
16 | _ string
17 | }
18 |
19 | type (
20 | m1 map[int]string
21 | m2 m1
22 | )
23 |
24 | type (
25 | str1 string
26 | str2 str1
27 |
28 | int1 int
29 | )
30 |
31 | type st1 struct {
32 | F string
33 | }
34 |
35 | type st2 struct {
36 | F string
37 | a string
38 | }
39 |
40 | func main() {
41 |
42 | // defined type 可赋值
43 | var map1 map[int]string = make(map[int]string)
44 | var map2 m1 = map1
45 | fmt.Println(map2)
46 | // defined type 不可赋值
47 | var map3 m2 = map1
48 | fmt.Println(map3)
49 | // var map4 m2 = map2 // 注释程保证程序的运行
50 |
51 | // 通道赋值
52 | var c1 chan int = make(chan int)
53 | var c2 chan<- int = c1
54 | fmt.Println(c2 == c1)
55 | // c1 = c2 // 注释程保证程序的运行
56 |
57 | //无类型常量和string
58 | const s1 = "1111"
59 | // 无类型常量string赋值
60 | var s3 str1 = s1
61 | var s4 str2 = s1
62 | fmt.Println(s3, s4)
63 | const s2 string = "1111"
64 | // var s5 str1 = s2 // 注释程保证程序的运行
65 |
66 | // var i1 int = 1 // 注释程保证程序的运行
67 | const i2 int = 1
68 | // var i3 int1 = i1 // 注释程保证程序的运行
69 | // var i4 int1 = i2 // 注释程保证程序的运行
70 |
71 | // 结构体类型相等
72 |
73 | // 相同包,不同tag
74 | // bst11 := struct {
75 | // a int
76 | // _ string
77 | // }{1, "555"}
78 | // var bst12 blankSt1 = bst11 // 注释程保证程序的运行
79 | // 不同包,所字段均导出
80 | var st11 st1 = ttt.A
81 | fmt.Println(st11)
82 | // 不同包,有字段未导出
83 | // var st21 st2 = ttt.B // 注释程保证程序的运行
84 | // fmt.Println(st21) // 注释程保证程序的运行
85 |
86 | bst1 := blankSt{1, "333"}
87 | bst2 := struct {
88 | a int
89 | _ string
90 | }{1, "555"}
91 | fmt.Println(bst1 == bst2)
92 | }
93 |
--------------------------------------------------------------------------------
/types/ttt/test.go:
--------------------------------------------------------------------------------
1 | package ttt
2 |
3 | type ST1 = struct {
4 | F string
5 | }
6 |
7 | type ST2 = struct {
8 | F string
9 | a string
10 | }
11 |
12 | var A = ST1{
13 | F: "1111",
14 | }
15 |
16 | var B = ST2{
17 | F: "1111",
18 | }
19 |
--------------------------------------------------------------------------------
/zerocopy/writto_readfrom.md:
--------------------------------------------------------------------------------
1 | ./io/io.go
2 |
3 |
4 | WriteTo
5 | ./bufio/bufio.go
6 | ./net/udpsock.go
7 | ./net/unixsock_posix.go
8 | ./net/fd_posix.go
9 | ./net/iprawsock.go
10 | ./net/net.go
11 | ./net/udpsock_posix.go
12 | ./net/iprawsock_posix.go
13 | ./net/unixsock.go
14 | ./internal/poll/fd_unix.go
15 |
16 |
17 | ReaderFrom
18 | ./bufio/bufio.go
19 | ./net/net.go
20 | ./net/http/transport.go
21 | ./net/tcpsock.go
22 | ./os/file.go
--------------------------------------------------------------------------------