github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/qtls-go1-16/unsafe.go (about) 1 package qtls 2 3 import ( 4 "crypto/tls" 5 "reflect" 6 "unsafe" 7 ) 8 9 func init() { 10 if !structsEqual(&tls.ConnectionState{}, &connectionState{}) { 11 panic("qtls.ConnectionState doesn't match") 12 } 13 if !structsEqual(&tls.ClientSessionState{}, &clientSessionState{}) { 14 panic("qtls.ClientSessionState doesn't match") 15 } 16 if !structsEqual(&tls.CertificateRequestInfo{}, &certificateRequestInfo{}) { 17 panic("qtls.CertificateRequestInfo doesn't match") 18 } 19 if !structsEqual(&tls.Config{}, &config{}) { 20 panic("qtls.Config doesn't match") 21 } 22 if !structsEqual(&tls.ClientHelloInfo{}, &clientHelloInfo{}) { 23 panic("qtls.ClientHelloInfo doesn't match") 24 } 25 } 26 27 func toConnectionState(c connectionState) ConnectionState { 28 return *(*ConnectionState)(unsafe.Pointer(&c)) 29 } 30 31 func toClientSessionState(s *clientSessionState) *ClientSessionState { 32 return (*ClientSessionState)(unsafe.Pointer(s)) 33 } 34 35 func fromClientSessionState(s *ClientSessionState) *clientSessionState { 36 return (*clientSessionState)(unsafe.Pointer(s)) 37 } 38 39 func toCertificateRequestInfo(i *certificateRequestInfo) *CertificateRequestInfo { 40 return (*CertificateRequestInfo)(unsafe.Pointer(i)) 41 } 42 43 func toConfig(c *config) *Config { 44 return (*Config)(unsafe.Pointer(c)) 45 } 46 47 func fromConfig(c *Config) *config { 48 return (*config)(unsafe.Pointer(c)) 49 } 50 51 func toClientHelloInfo(chi *clientHelloInfo) *ClientHelloInfo { 52 return (*ClientHelloInfo)(unsafe.Pointer(chi)) 53 } 54 55 func structsEqual(a, b interface{}) bool { 56 return compare(reflect.ValueOf(a), reflect.ValueOf(b)) 57 } 58 59 func compare(a, b reflect.Value) bool { 60 sa := a.Elem() 61 sb := b.Elem() 62 if sa.NumField() != sb.NumField() { 63 return false 64 } 65 for i := 0; i < sa.NumField(); i++ { 66 fa := sa.Type().Field(i) 67 fb := sb.Type().Field(i) 68 if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) { 69 if fa.Type.Kind() != fb.Type.Kind() { 70 return false 71 } 72 if fa.Type.Kind() == reflect.Slice { 73 if !compareStruct(fa.Type.Elem(), fb.Type.Elem()) { 74 return false 75 } 76 continue 77 } 78 return false 79 } 80 } 81 return true 82 } 83 84 func compareStruct(a, b reflect.Type) bool { 85 if a.NumField() != b.NumField() { 86 return false 87 } 88 for i := 0; i < a.NumField(); i++ { 89 fa := a.Field(i) 90 fb := b.Field(i) 91 if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) { 92 return false 93 } 94 } 95 return true 96 }