manager.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package subscriptionmanager
  2. import (
  3. "archive/zip"
  4. "bytes"
  5. "context"
  6. "time"
  7. core "github.com/v2fly/v2ray-core/v5"
  8. "github.com/v2fly/v2ray-core/v5/app/subscription"
  9. "github.com/v2fly/v2ray-core/v5/app/subscription/entries"
  10. "github.com/v2fly/v2ray-core/v5/app/subscription/entries/nonnative/nonnativeifce"
  11. "github.com/v2fly/v2ray-core/v5/common"
  12. "github.com/v2fly/v2ray-core/v5/common/task"
  13. "github.com/v2fly/v2ray-core/v5/features/extension"
  14. )
  15. //go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
  16. type SubscriptionManagerImpl struct {
  17. config *subscription.Config
  18. ctx context.Context
  19. s *core.Instance
  20. converter *entries.ConverterRegistry
  21. trackedSubscriptions map[string]*trackedSubscription
  22. refreshTask *task.Periodic
  23. }
  24. func (s *SubscriptionManagerImpl) Type() interface{} {
  25. return extension.SubscriptionManagerType()
  26. }
  27. func (s *SubscriptionManagerImpl) housekeeping() error {
  28. for subscriptionName := range s.trackedSubscriptions {
  29. if err := s.checkupSubscription(subscriptionName); err != nil {
  30. newError("failed to checkup subscription: ", err).AtWarning().WriteToLog()
  31. }
  32. }
  33. return nil
  34. }
  35. func (s *SubscriptionManagerImpl) Start() error {
  36. if err := s.refreshTask.Start(); err != nil {
  37. return err
  38. }
  39. return nil
  40. }
  41. func (s *SubscriptionManagerImpl) Close() error {
  42. if err := s.refreshTask.Close(); err != nil {
  43. return err
  44. }
  45. return nil
  46. }
  47. func (s *SubscriptionManagerImpl) init() error {
  48. s.refreshTask = &task.Periodic{
  49. Interval: time.Duration(60) * time.Second,
  50. Execute: s.housekeeping,
  51. }
  52. s.trackedSubscriptions = make(map[string]*trackedSubscription)
  53. s.converter = entries.GetOverlayConverterRegistry()
  54. if s.config.NonnativeConverterOverlay != nil {
  55. zipReader, err := zip.NewReader(bytes.NewReader(s.config.NonnativeConverterOverlay), int64(len(s.config.NonnativeConverterOverlay)))
  56. if err != nil {
  57. return newError("failed to read nonnative converter overlay: ", err)
  58. }
  59. converter, err := nonnativeifce.NewNonNativeConverterConstructor(zipReader)
  60. if err != nil {
  61. return newError("failed to construct nonnative converter: ", err)
  62. }
  63. if err := s.converter.RegisterConverter("user_nonnative", converter); err != nil {
  64. return newError("failed to register user nonnative converter: ", err)
  65. }
  66. }
  67. for _, v := range s.config.Imports {
  68. tracked, err := newTrackedSubscription(v)
  69. if err != nil {
  70. return newError("failed to init subscription ", v.Name, ": ", err)
  71. }
  72. s.trackedSubscriptions[v.Name] = tracked
  73. }
  74. return nil
  75. }
  76. func NewSubscriptionManager(ctx context.Context, config *subscription.Config) (*SubscriptionManagerImpl, error) {
  77. instance := core.MustFromContext(ctx)
  78. impl := &SubscriptionManagerImpl{ctx: ctx, s: instance, config: config}
  79. if err := impl.init(); err != nil {
  80. return nil, newError("failed to init subscription manager: ", err)
  81. }
  82. return impl, nil
  83. }
  84. func init() {
  85. common.Must(common.RegisterConfig((*subscription.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  86. return NewSubscriptionManager(ctx, config.(*subscription.Config))
  87. }))
  88. }