config.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package config
  2. import (
  3. "errors"
  4. "github.com/cnlh/nps/lib/common"
  5. "github.com/cnlh/nps/lib/file"
  6. "regexp"
  7. "strings"
  8. )
  9. type CommonConfig struct {
  10. Server string
  11. VKey string
  12. Tp string //bridgeType kcp or tcp
  13. AutoReconnection bool
  14. Cnf *file.Config
  15. ProxyUrl string
  16. Client *file.Client
  17. }
  18. type LocalServer struct {
  19. Type string
  20. Port int
  21. Password string
  22. Target string
  23. }
  24. type Config struct {
  25. content string
  26. title []string
  27. CommonConfig *CommonConfig
  28. Hosts []*file.Host
  29. Tasks []*file.Tunnel
  30. LocalServer []*LocalServer
  31. }
  32. func NewConfig(path string) (c *Config, err error) {
  33. c = new(Config)
  34. var b []byte
  35. if b, err = common.ReadAllFromFile(path); err != nil {
  36. return
  37. } else {
  38. c.content = string(b)
  39. if c.title, err = getAllTitle(c.content); err != nil {
  40. return
  41. }
  42. var nowIndex int
  43. var nextIndex int
  44. var nowContent string
  45. for i := 0; i < len(c.title); i++ {
  46. nowIndex = strings.Index(c.content, c.title[i]) + len(c.title[i])
  47. if i < len(c.title)-1 {
  48. nextIndex = strings.Index(c.content, c.title[i+1])
  49. } else {
  50. nextIndex = len(c.content)
  51. }
  52. nowContent = c.content[nowIndex:nextIndex]
  53. if strings.Index(getTitleContent(c.title[i]), "secret") == 0 {
  54. local := delLocalService(nowContent)
  55. local.Type = "secret"
  56. c.LocalServer = append(c.LocalServer, local)
  57. continue
  58. }
  59. if strings.Index(getTitleContent(c.title[i]), "p2p") == 0 {
  60. local := delLocalService(nowContent)
  61. local.Type = "p2p"
  62. c.LocalServer = append(c.LocalServer, local)
  63. continue
  64. }
  65. switch c.title[i] {
  66. case "[common]":
  67. c.CommonConfig = dealCommon(nowContent)
  68. default:
  69. if strings.Index(nowContent, "host") > -1 {
  70. h := dealHost(nowContent)
  71. h.Remark = getTitleContent(c.title[i])
  72. c.Hosts = append(c.Hosts, h)
  73. } else {
  74. t := dealTunnel(nowContent)
  75. t.Remark = getTitleContent(c.title[i])
  76. c.Tasks = append(c.Tasks, t)
  77. }
  78. }
  79. }
  80. }
  81. return
  82. }
  83. func getTitleContent(s string) string {
  84. re, _ := regexp.Compile(`[\[\]]`)
  85. return re.ReplaceAllString(s, "")
  86. }
  87. func dealCommon(s string) *CommonConfig {
  88. c := &CommonConfig{}
  89. c.Cnf = new(file.Config)
  90. c.Client = file.NewClient("", true, true)
  91. for _, v := range strings.Split(s, "\n") {
  92. item := strings.Split(v, "=")
  93. if len(item) == 0 {
  94. continue
  95. } else if len(item) == 1 {
  96. item = append(item, "")
  97. }
  98. switch item[0] {
  99. case "server":
  100. c.Server = item[1]
  101. case "vkey":
  102. c.VKey = item[1]
  103. case "tp":
  104. c.Tp = item[1]
  105. case "auto_reconnection":
  106. c.AutoReconnection = common.GetBoolByStr(item[1])
  107. case "username":
  108. c.Cnf.U = item[1]
  109. case "password":
  110. c.Cnf.P = item[1]
  111. case "compress":
  112. c.Cnf.Compress = common.GetBoolByStr(item[1])
  113. case "crypt":
  114. c.Cnf.Crypt = common.GetBoolByStr(item[1])
  115. case "proxy_socks5_url":
  116. c.ProxyUrl = item[1]
  117. case "rate_limit":
  118. c.Client.RateLimit = common.GetIntNoErrByStr(item[1])
  119. case "flow_limit":
  120. c.Client.Flow.FlowLimit = int64(common.GetIntNoErrByStr(item[1]))
  121. case "max_conn":
  122. c.Client.MaxConn = common.GetIntNoErrByStr(item[1])
  123. case "remark":
  124. c.Client.Remark = item[1]
  125. }
  126. }
  127. return c
  128. }
  129. func dealHost(s string) *file.Host {
  130. h := &file.Host{}
  131. var headerChange string
  132. for _, v := range strings.Split(s, "\n") {
  133. item := strings.Split(v, "=")
  134. if len(item) == 0 {
  135. continue
  136. } else if len(item) == 1 {
  137. item = append(item, "")
  138. }
  139. switch item[0] {
  140. case "host":
  141. h.Host = item[1]
  142. case "target":
  143. h.Target = strings.Replace(item[1], ",", "\n", -1)
  144. case "host_change":
  145. h.HostChange = item[1]
  146. case "location":
  147. h.Location = item[1]
  148. default:
  149. if strings.Contains(item[0], "header") {
  150. headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
  151. }
  152. h.HeaderChange = headerChange
  153. }
  154. }
  155. return h
  156. }
  157. func dealTunnel(s string) *file.Tunnel {
  158. t := &file.Tunnel{}
  159. for _, v := range strings.Split(s, "\n") {
  160. item := strings.Split(v, "=")
  161. if len(item) == 0 {
  162. continue
  163. } else if len(item) == 1 {
  164. item = append(item, "")
  165. }
  166. switch item[0] {
  167. case "port":
  168. t.Ports = item[1]
  169. case "mode":
  170. t.Mode = item[1]
  171. case "target":
  172. t.Target = item[1]
  173. case "targetAddr":
  174. t.TargetAddr = item[1]
  175. case "password":
  176. t.Password = item[1]
  177. }
  178. }
  179. return t
  180. }
  181. func delLocalService(s string) *LocalServer {
  182. l := new(LocalServer)
  183. for _, v := range strings.Split(s, "\n") {
  184. item := strings.Split(v, "=")
  185. if len(item) == 0 {
  186. continue
  187. } else if len(item) == 1 {
  188. item = append(item, "")
  189. }
  190. switch item[0] {
  191. case "port":
  192. l.Port = common.GetIntNoErrByStr(item[1])
  193. case "password":
  194. l.Password = item[1]
  195. case "target":
  196. l.Target = item[1]
  197. }
  198. }
  199. return l
  200. }
  201. func getAllTitle(content string) (arr []string, err error) {
  202. var re *regexp.Regexp
  203. re, err = regexp.Compile(`\[.+?\]`)
  204. if err != nil {
  205. return
  206. }
  207. arr = re.FindAllString(content, -1)
  208. m := make(map[string]bool)
  209. for _, v := range arr {
  210. if _, ok := m[v]; ok {
  211. err = errors.New("Item names are not allowed to be duplicated")
  212. return
  213. }
  214. m[v] = true
  215. }
  216. return
  217. }