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