certificate_provider.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package option
  2. import (
  3. "context"
  4. E "github.com/sagernet/sing/common/exceptions"
  5. "github.com/sagernet/sing/common/json"
  6. "github.com/sagernet/sing/common/json/badjson"
  7. "github.com/sagernet/sing/service"
  8. )
  9. type CertificateProviderOptionsRegistry interface {
  10. CreateOptions(providerType string) (any, bool)
  11. }
  12. type _CertificateProvider struct {
  13. Type string `json:"type"`
  14. Tag string `json:"tag,omitempty"`
  15. Options any `json:"-"`
  16. }
  17. type CertificateProvider _CertificateProvider
  18. func (h *CertificateProvider) MarshalJSONContext(ctx context.Context) ([]byte, error) {
  19. return badjson.MarshallObjectsContext(ctx, (*_CertificateProvider)(h), h.Options)
  20. }
  21. func (h *CertificateProvider) UnmarshalJSONContext(ctx context.Context, content []byte) error {
  22. err := json.UnmarshalContext(ctx, content, (*_CertificateProvider)(h))
  23. if err != nil {
  24. return err
  25. }
  26. registry := service.FromContext[CertificateProviderOptionsRegistry](ctx)
  27. if registry == nil {
  28. return E.New("missing certificate provider options registry in context")
  29. }
  30. options, loaded := registry.CreateOptions(h.Type)
  31. if !loaded {
  32. return E.New("unknown certificate provider type: ", h.Type)
  33. }
  34. err = badjson.UnmarshallExcludedContext(ctx, content, (*_CertificateProvider)(h), options)
  35. if err != nil {
  36. return err
  37. }
  38. h.Options = options
  39. return nil
  40. }
  41. type CertificateProviderOptions struct {
  42. Tag string `json:"-"`
  43. Type string `json:"-"`
  44. Options any `json:"-"`
  45. }
  46. type _CertificateProviderInline struct {
  47. Type string `json:"type"`
  48. }
  49. func (o *CertificateProviderOptions) MarshalJSONContext(ctx context.Context) ([]byte, error) {
  50. if o.Tag != "" {
  51. return json.Marshal(o.Tag)
  52. }
  53. return badjson.MarshallObjectsContext(ctx, _CertificateProviderInline{Type: o.Type}, o.Options)
  54. }
  55. func (o *CertificateProviderOptions) UnmarshalJSONContext(ctx context.Context, content []byte) error {
  56. if len(content) == 0 {
  57. return E.New("empty certificate_provider value")
  58. }
  59. if content[0] == '"' {
  60. return json.UnmarshalContext(ctx, content, &o.Tag)
  61. }
  62. var inline _CertificateProviderInline
  63. err := json.UnmarshalContext(ctx, content, &inline)
  64. if err != nil {
  65. return err
  66. }
  67. o.Type = inline.Type
  68. if o.Type == "" {
  69. return E.New("missing certificate provider type")
  70. }
  71. registry := service.FromContext[CertificateProviderOptionsRegistry](ctx)
  72. if registry == nil {
  73. return E.New("missing certificate provider options registry in context")
  74. }
  75. options, loaded := registry.CreateOptions(o.Type)
  76. if !loaded {
  77. return E.New("unknown certificate provider type: ", o.Type)
  78. }
  79. err = badjson.UnmarshallExcludedContext(ctx, content, &inline, options)
  80. if err != nil {
  81. return err
  82. }
  83. o.Options = options
  84. return nil
  85. }
  86. func (o *CertificateProviderOptions) IsShared() bool {
  87. return o.Tag != ""
  88. }