├── .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 | ![](./qrcode.jpg) 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 --------------------------------------------------------------------------------