123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- package cachefile
- import (
- "encoding/binary"
- "time"
- "github.com/sagernet/bbolt"
- "github.com/sagernet/sing/common/buf"
- "github.com/sagernet/sing/common/logger"
- )
- var bucketRDRC = []byte("rdrc2")
- func (c *CacheFile) StoreRDRC() bool {
- return c.storeRDRC
- }
- func (c *CacheFile) RDRCTimeout() time.Duration {
- return c.rdrcTimeout
- }
- func (c *CacheFile) LoadRDRC(transportName string, qName string, qType uint16) (rejected bool) {
- c.saveRDRCAccess.RLock()
- rejected, cached := c.saveRDRC[saveRDRCCacheKey{transportName, qName, qType}]
- c.saveRDRCAccess.RUnlock()
- if cached {
- return
- }
- key := buf.Get(2 + len(qName))
- binary.BigEndian.PutUint16(key, qType)
- copy(key[2:], qName)
- defer buf.Put(key)
- var deleteCache bool
- err := c.DB.View(func(tx *bbolt.Tx) error {
- bucket := c.bucket(tx, bucketRDRC)
- if bucket == nil {
- return nil
- }
- bucket = bucket.Bucket([]byte(transportName))
- if bucket == nil {
- return nil
- }
- content := bucket.Get(key)
- if content == nil {
- return nil
- }
- expiresAt := time.Unix(int64(binary.BigEndian.Uint64(content)), 0)
- if time.Now().After(expiresAt) {
- deleteCache = true
- return nil
- }
- rejected = true
- return nil
- })
- if err != nil {
- return
- }
- if deleteCache {
- c.DB.Update(func(tx *bbolt.Tx) error {
- bucket := c.bucket(tx, bucketRDRC)
- if bucket == nil {
- return nil
- }
- bucket = bucket.Bucket([]byte(transportName))
- if bucket == nil {
- return nil
- }
- return bucket.Delete(key)
- })
- }
- return
- }
- func (c *CacheFile) SaveRDRC(transportName string, qName string, qType uint16) error {
- return c.DB.Batch(func(tx *bbolt.Tx) error {
- bucket, err := c.createBucket(tx, bucketRDRC)
- if err != nil {
- return err
- }
- bucket, err = bucket.CreateBucketIfNotExists([]byte(transportName))
- if err != nil {
- return err
- }
- key := buf.Get(2 + len(qName))
- binary.BigEndian.PutUint16(key, qType)
- copy(key[2:], qName)
- defer buf.Put(key)
- expiresAt := buf.Get(8)
- defer buf.Put(expiresAt)
- binary.BigEndian.PutUint64(expiresAt, uint64(time.Now().Add(c.rdrcTimeout).Unix()))
- return bucket.Put(key, expiresAt)
- })
- }
- func (c *CacheFile) SaveRDRCAsync(transportName string, qName string, qType uint16, logger logger.Logger) {
- saveKey := saveRDRCCacheKey{transportName, qName, qType}
- c.saveRDRCAccess.Lock()
- c.saveRDRC[saveKey] = true
- c.saveRDRCAccess.Unlock()
- go func() {
- err := c.SaveRDRC(transportName, qName, qType)
- if err != nil {
- logger.Warn("save RDRC: ", err)
- }
- c.saveRDRCAccess.Lock()
- delete(c.saveRDRC, saveKey)
- c.saveRDRCAccess.Unlock()
- }()
- }
|