rdrc.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package cachefile
  2. import (
  3. "encoding/binary"
  4. "time"
  5. "github.com/sagernet/bbolt"
  6. "github.com/sagernet/sing/common/buf"
  7. "github.com/sagernet/sing/common/logger"
  8. )
  9. var bucketRDRC = []byte("rdrc")
  10. func (c *CacheFile) StoreRDRC() bool {
  11. return c.storeRDRC
  12. }
  13. func (c *CacheFile) RDRCTimeout() time.Duration {
  14. return c.rdrcTimeout
  15. }
  16. func (c *CacheFile) LoadRDRC(transportName string, qName string) (rejected bool) {
  17. c.saveRDRCAccess.RLock()
  18. rejected, cached := c.saveRDRC[saveRDRCCacheKey{transportName, qName}]
  19. c.saveRDRCAccess.RUnlock()
  20. if cached {
  21. return
  22. }
  23. var deleteCache bool
  24. err := c.DB.View(func(tx *bbolt.Tx) error {
  25. bucket := c.bucket(tx, bucketRDRC)
  26. if bucket == nil {
  27. return nil
  28. }
  29. bucket = bucket.Bucket([]byte(transportName))
  30. if bucket == nil {
  31. return nil
  32. }
  33. content := bucket.Get([]byte(qName))
  34. if content == nil {
  35. return nil
  36. }
  37. expiresAt := time.Unix(int64(binary.BigEndian.Uint64(content)), 0)
  38. if time.Now().After(expiresAt) {
  39. deleteCache = true
  40. return nil
  41. }
  42. rejected = true
  43. return nil
  44. })
  45. if err != nil {
  46. return
  47. }
  48. if deleteCache {
  49. c.DB.Update(func(tx *bbolt.Tx) error {
  50. bucket := c.bucket(tx, bucketRDRC)
  51. if bucket == nil {
  52. return nil
  53. }
  54. bucket = bucket.Bucket([]byte(transportName))
  55. if bucket == nil {
  56. return nil
  57. }
  58. return bucket.Delete([]byte(qName))
  59. })
  60. }
  61. return
  62. }
  63. func (c *CacheFile) SaveRDRC(transportName string, qName string) error {
  64. return c.DB.Batch(func(tx *bbolt.Tx) error {
  65. bucket, err := c.createBucket(tx, bucketRDRC)
  66. if err != nil {
  67. return err
  68. }
  69. bucket, err = bucket.CreateBucketIfNotExists([]byte(transportName))
  70. if err != nil {
  71. return err
  72. }
  73. expiresAt := buf.Get(8)
  74. defer buf.Put(expiresAt)
  75. binary.BigEndian.PutUint64(expiresAt, uint64(time.Now().Add(c.rdrcTimeout).Unix()))
  76. return bucket.Put([]byte(qName), expiresAt)
  77. })
  78. }
  79. func (c *CacheFile) SaveRDRCAsync(transportName string, qName string, logger logger.Logger) {
  80. saveKey := saveRDRCCacheKey{transportName, qName}
  81. c.saveRDRCAccess.Lock()
  82. c.saveRDRC[saveKey] = true
  83. c.saveRDRCAccess.Unlock()
  84. go func() {
  85. err := c.SaveRDRC(transportName, qName)
  86. if err != nil {
  87. logger.Warn("save RDRC: ", err)
  88. }
  89. c.saveRDRCAccess.Lock()
  90. delete(c.saveRDRC, saveKey)
  91. c.saveRDRCAccess.Unlock()
  92. }()
  93. }