profile_import.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package libbox
  2. import (
  3. "bufio"
  4. "bytes"
  5. "compress/gzip"
  6. "encoding/binary"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. "github.com/sagernet/sing/common/varbin"
  9. )
  10. func EncodeChunkedMessage(data []byte) []byte {
  11. var buffer bytes.Buffer
  12. binary.Write(&buffer, binary.BigEndian, uint16(len(data)))
  13. buffer.Write(data)
  14. return buffer.Bytes()
  15. }
  16. func DecodeLengthChunk(data []byte) int32 {
  17. return int32(binary.BigEndian.Uint16(data))
  18. }
  19. const (
  20. MessageTypeError = iota
  21. MessageTypeProfileList
  22. MessageTypeProfileContentRequest
  23. MessageTypeProfileContent
  24. )
  25. type ErrorMessage struct {
  26. Message string
  27. }
  28. func (e *ErrorMessage) Encode() []byte {
  29. var buffer bytes.Buffer
  30. buffer.WriteByte(MessageTypeError)
  31. varbin.Write(&buffer, binary.BigEndian, e.Message)
  32. return buffer.Bytes()
  33. }
  34. func DecodeErrorMessage(data []byte) (*ErrorMessage, error) {
  35. reader := bytes.NewReader(data)
  36. messageType, err := reader.ReadByte()
  37. if err != nil {
  38. return nil, err
  39. }
  40. if messageType != MessageTypeError {
  41. return nil, E.New("invalid message")
  42. }
  43. var message ErrorMessage
  44. message.Message, err = varbin.ReadValue[string](reader, binary.BigEndian)
  45. if err != nil {
  46. return nil, err
  47. }
  48. return &message, nil
  49. }
  50. const (
  51. ProfileTypeLocal int32 = iota
  52. ProfileTypeiCloud
  53. ProfileTypeRemote
  54. )
  55. type ProfilePreview struct {
  56. ProfileID int64
  57. Name string
  58. Type int32
  59. }
  60. type ProfilePreviewIterator interface {
  61. Next() *ProfilePreview
  62. HasNext() bool
  63. }
  64. type ProfileEncoder struct {
  65. profiles []ProfilePreview
  66. }
  67. func (e *ProfileEncoder) Append(profile *ProfilePreview) {
  68. e.profiles = append(e.profiles, *profile)
  69. }
  70. func (e *ProfileEncoder) Encode() []byte {
  71. var buffer bytes.Buffer
  72. buffer.WriteByte(MessageTypeProfileList)
  73. binary.Write(&buffer, binary.BigEndian, uint16(len(e.profiles)))
  74. for _, preview := range e.profiles {
  75. binary.Write(&buffer, binary.BigEndian, preview.ProfileID)
  76. varbin.Write(&buffer, binary.BigEndian, preview.Name)
  77. binary.Write(&buffer, binary.BigEndian, preview.Type)
  78. }
  79. return buffer.Bytes()
  80. }
  81. type ProfileDecoder struct {
  82. profiles []*ProfilePreview
  83. }
  84. func (d *ProfileDecoder) Decode(data []byte) error {
  85. reader := bytes.NewReader(data)
  86. messageType, err := reader.ReadByte()
  87. if err != nil {
  88. return err
  89. }
  90. if messageType != MessageTypeProfileList {
  91. return E.New("invalid message")
  92. }
  93. var profileCount uint16
  94. err = binary.Read(reader, binary.BigEndian, &profileCount)
  95. if err != nil {
  96. return err
  97. }
  98. for i := 0; i < int(profileCount); i++ {
  99. var profile ProfilePreview
  100. err = binary.Read(reader, binary.BigEndian, &profile.ProfileID)
  101. if err != nil {
  102. return err
  103. }
  104. profile.Name, err = varbin.ReadValue[string](reader, binary.BigEndian)
  105. if err != nil {
  106. return err
  107. }
  108. err = binary.Read(reader, binary.BigEndian, &profile.Type)
  109. if err != nil {
  110. return err
  111. }
  112. d.profiles = append(d.profiles, &profile)
  113. }
  114. return nil
  115. }
  116. func (d *ProfileDecoder) Iterator() ProfilePreviewIterator {
  117. return newIterator(d.profiles)
  118. }
  119. type ProfileContentRequest struct {
  120. ProfileID int64
  121. }
  122. func (r *ProfileContentRequest) Encode() []byte {
  123. var buffer bytes.Buffer
  124. buffer.WriteByte(MessageTypeProfileContentRequest)
  125. binary.Write(&buffer, binary.BigEndian, r.ProfileID)
  126. return buffer.Bytes()
  127. }
  128. func DecodeProfileContentRequest(data []byte) (*ProfileContentRequest, error) {
  129. reader := bytes.NewReader(data)
  130. messageType, err := reader.ReadByte()
  131. if err != nil {
  132. return nil, err
  133. }
  134. if messageType != MessageTypeProfileContentRequest {
  135. return nil, E.New("invalid message")
  136. }
  137. var request ProfileContentRequest
  138. err = binary.Read(reader, binary.BigEndian, &request.ProfileID)
  139. if err != nil {
  140. return nil, err
  141. }
  142. return &request, nil
  143. }
  144. type ProfileContent struct {
  145. Name string
  146. Type int32
  147. Config string
  148. RemotePath string
  149. AutoUpdate bool
  150. AutoUpdateInterval int32
  151. LastUpdated int64
  152. }
  153. func (c *ProfileContent) Encode() []byte {
  154. buffer := new(bytes.Buffer)
  155. buffer.WriteByte(MessageTypeProfileContent)
  156. buffer.WriteByte(1)
  157. gWriter := gzip.NewWriter(buffer)
  158. writer := bufio.NewWriter(gWriter)
  159. varbin.Write(writer, binary.BigEndian, c.Name)
  160. binary.Write(writer, binary.BigEndian, c.Type)
  161. varbin.Write(writer, binary.BigEndian, c.Config)
  162. if c.Type != ProfileTypeLocal {
  163. varbin.Write(writer, binary.BigEndian, c.RemotePath)
  164. }
  165. if c.Type == ProfileTypeRemote {
  166. binary.Write(writer, binary.BigEndian, c.AutoUpdate)
  167. binary.Write(writer, binary.BigEndian, c.AutoUpdateInterval)
  168. binary.Write(writer, binary.BigEndian, c.LastUpdated)
  169. }
  170. writer.Flush()
  171. gWriter.Flush()
  172. gWriter.Close()
  173. return buffer.Bytes()
  174. }
  175. func DecodeProfileContent(data []byte) (*ProfileContent, error) {
  176. reader := bytes.NewReader(data)
  177. messageType, err := reader.ReadByte()
  178. if err != nil {
  179. return nil, err
  180. }
  181. if messageType != MessageTypeProfileContent {
  182. return nil, E.New("invalid message")
  183. }
  184. version, err := reader.ReadByte()
  185. if err != nil {
  186. return nil, err
  187. }
  188. gReader, err := gzip.NewReader(reader)
  189. if err != nil {
  190. return nil, E.Cause(err, "unsupported profile")
  191. }
  192. bReader := varbin.StubReader(gReader)
  193. var content ProfileContent
  194. content.Name, err = varbin.ReadValue[string](bReader, binary.BigEndian)
  195. if err != nil {
  196. return nil, err
  197. }
  198. err = binary.Read(bReader, binary.BigEndian, &content.Type)
  199. if err != nil {
  200. return nil, err
  201. }
  202. content.Config, err = varbin.ReadValue[string](bReader, binary.BigEndian)
  203. if err != nil {
  204. return nil, err
  205. }
  206. if content.Type != ProfileTypeLocal {
  207. content.RemotePath, err = varbin.ReadValue[string](bReader, binary.BigEndian)
  208. if err != nil {
  209. return nil, err
  210. }
  211. }
  212. if content.Type == ProfileTypeRemote || (version == 0 && content.Type != ProfileTypeLocal) {
  213. err = binary.Read(bReader, binary.BigEndian, &content.AutoUpdate)
  214. if err != nil {
  215. return nil, err
  216. }
  217. if version >= 1 {
  218. err = binary.Read(bReader, binary.BigEndian, &content.AutoUpdateInterval)
  219. if err != nil {
  220. return nil, err
  221. }
  222. }
  223. err = binary.Read(bReader, binary.BigEndian, &content.LastUpdated)
  224. if err != nil {
  225. return nil, err
  226. }
  227. }
  228. return &content, nil
  229. }