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  }