config.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. Healths []*file.Health
  31. LocalServer []*LocalServer
  32. }
  33. func NewConfig(path string) (c *Config, err error) {
  34. c = new(Config)
  35. var b []byte
  36. if b, err = common.ReadAllFromFile(path); err != nil {
  37. return
  38. } else {
  39. if c.content, err = common.ParseStr(string(b)); err != nil {
  40. return nil, err
  41. }
  42. if c.title, err = getAllTitle(c.content); err != nil {
  43. return
  44. }
  45. var nowIndex int
  46. var nextIndex int
  47. var nowContent string
  48. for i := 0; i < len(c.title); i++ {
  49. nowIndex = strings.Index(c.content, c.title[i]) + len(c.title[i])
  50. if i < len(c.title)-1 {
  51. nextIndex = strings.Index(c.content, c.title[i+1])
  52. } else {
  53. nextIndex = len(c.content)
  54. }
  55. nowContent = c.content[nowIndex:nextIndex]
  56. if strings.Index(getTitleContent(c.title[i]), "secret") == 0 && !strings.Contains(nowContent, "mode") {
  57. local := delLocalService(nowContent)
  58. local.Type = "secret"
  59. c.LocalServer = append(c.LocalServer, local)
  60. continue
  61. }
  62. //except mode
  63. if strings.Index(getTitleContent(c.title[i]), "p2p") == 0 && !strings.Contains(nowContent, "mode") {
  64. local := delLocalService(nowContent)
  65. local.Type = "p2p"
  66. c.LocalServer = append(c.LocalServer, local)
  67. continue
  68. }
  69. //health set
  70. if strings.Index(getTitleContent(c.title[i]), "health") == 0 {
  71. c.Healths = append(c.Healths, dealHealth(nowContent))
  72. continue
  73. }
  74. switch c.title[i] {
  75. case "[common]":
  76. c.CommonConfig = dealCommon(nowContent)
  77. default:
  78. if strings.Index(nowContent, "host") > -1 {
  79. h := dealHost(nowContent)
  80. h.Remark = getTitleContent(c.title[i])
  81. c.Hosts = append(c.Hosts, h)
  82. } else {
  83. t := dealTunnel(nowContent)
  84. t.Remark = getTitleContent(c.title[i])
  85. c.Tasks = append(c.Tasks, t)
  86. }
  87. }
  88. }
  89. }
  90. return
  91. }
  92. func getTitleContent(s string) string {
  93. re, _ := regexp.Compile(`[\[\]]`)
  94. return re.ReplaceAllString(s, "")
  95. }
  96. func dealCommon(s string) *CommonConfig {
  97. c := &CommonConfig{}
  98. c.Cnf = new(file.Config)
  99. c.Client = file.NewClient("", true, true)
  100. for _, v := range strings.Split(s, "\n") {
  101. item := strings.Split(v, "=")
  102. if len(item) == 0 {
  103. continue
  104. } else if len(item) == 1 {
  105. item = append(item, "")
  106. }
  107. switch item[0] {
  108. case "server":
  109. c.Server = item[1]
  110. case "vkey":
  111. c.VKey = item[1]
  112. case "tp":
  113. c.Tp = item[1]
  114. case "auto_reconnection":
  115. c.AutoReconnection = common.GetBoolByStr(item[1])
  116. case "username":
  117. c.Cnf.U = item[1]
  118. case "password":
  119. c.Cnf.P = item[1]
  120. case "compress":
  121. c.Cnf.Compress = common.GetBoolByStr(item[1])
  122. case "crypt":
  123. c.Cnf.Crypt = common.GetBoolByStr(item[1])
  124. case "proxy_socks5_url":
  125. c.ProxyUrl = item[1]
  126. case "rate_limit":
  127. c.Client.RateLimit = common.GetIntNoErrByStr(item[1])
  128. case "flow_limit":
  129. c.Client.Flow.FlowLimit = int64(common.GetIntNoErrByStr(item[1]))
  130. case "max_conn":
  131. c.Client.MaxConn = common.GetIntNoErrByStr(item[1])
  132. case "remark":
  133. c.Client.Remark = item[1]
  134. }
  135. }
  136. return c
  137. }
  138. func dealHost(s string) *file.Host {
  139. h := &file.Host{}
  140. var headerChange string
  141. var configDataArr []string
  142. configDataArr = strings.Split(s, "\n")
  143. if len(configDataArr) < 3 {
  144. configDataArr = strings.Split(s, "\r\n")
  145. }
  146. for _, v := range configDataArr {
  147. item := strings.Split(v, "=")
  148. if len(item) == 0 {
  149. continue
  150. } else if len(item) == 1 {
  151. item = append(item, "")
  152. }
  153. switch strings.TrimSpace(item[0]) {
  154. case "host":
  155. h.Host = item[1]
  156. case "target":
  157. h.Target = strings.Replace(item[1], ",", "\n", -1)
  158. case "host_change":
  159. h.HostChange = item[1]
  160. case "schemego":
  161. h.Scheme = item[1]
  162. case "location":
  163. h.Location = item[1]
  164. default:
  165. if strings.Contains(item[0], "header") {
  166. headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
  167. }
  168. h.HeaderChange = headerChange
  169. }
  170. }
  171. return h
  172. }
  173. func dealHealth(s string) *file.Health {
  174. h := &file.Health{}
  175. for _, v := range strings.Split(s, "\n") {
  176. item := strings.Split(v, "=")
  177. if len(item) == 0 {
  178. continue
  179. } else if len(item) == 1 {
  180. item = append(item, "")
  181. }
  182. switch strings.TrimSpace(item[0]) {
  183. case "health_check_timeout":
  184. h.HealthCheckTimeout = common.GetIntNoErrByStr(item[1])
  185. case "health_check_max_failed":
  186. h.HealthMaxFail = common.GetIntNoErrByStr(item[1])
  187. case "health_check_interval":
  188. h.HealthCheckInterval = common.GetIntNoErrByStr(item[1])
  189. case "health_http_url":
  190. h.HttpHealthUrl = item[1]
  191. case "health_check_type":
  192. h.HealthCheckType = item[1]
  193. case "health_check_target":
  194. h.HealthCheckTarget = item[1]
  195. }
  196. }
  197. return h
  198. }
  199. func dealTunnel(s string) *file.Tunnel {
  200. t := &file.Tunnel{}
  201. for _, v := range strings.Split(s, "\n") {
  202. item := strings.Split(v, "=")
  203. if len(item) == 0 {
  204. continue
  205. } else if len(item) == 1 {
  206. item = append(item, "")
  207. }
  208. switch strings.TrimSpace(item[0]) {
  209. case "port":
  210. t.Ports = item[1]
  211. case "mode":
  212. t.Mode = item[1]
  213. case "target":
  214. t.Target = strings.Replace(item[1], ",", "\n", -1)
  215. case "targetAddr":
  216. t.TargetAddr = item[1]
  217. case "password":
  218. t.Password = item[1]
  219. case "local_path":
  220. t.LocalPath = item[1]
  221. case "strip_pre":
  222. t.StripPre = item[1]
  223. }
  224. }
  225. return t
  226. }
  227. func delLocalService(s string) *LocalServer {
  228. l := new(LocalServer)
  229. for _, v := range strings.Split(s, "\n") {
  230. item := strings.Split(v, "=")
  231. if len(item) == 0 {
  232. continue
  233. } else if len(item) == 1 {
  234. item = append(item, "")
  235. }
  236. switch item[0] {
  237. case "port":
  238. l.Port = common.GetIntNoErrByStr(item[1])
  239. case "password":
  240. l.Password = item[1]
  241. case "target":
  242. l.Target = item[1]
  243. }
  244. }
  245. return l
  246. }
  247. func getAllTitle(content string) (arr []string, err error) {
  248. var re *regexp.Regexp
  249. re, err = regexp.Compile(`\[.+?\]`)
  250. if err != nil {
  251. return
  252. }
  253. arr = re.FindAllString(content, -1)
  254. m := make(map[string]bool)
  255. for _, v := range arr {
  256. if _, ok := m[v]; ok {
  257. err = errors.New("Item names are not allowed to be duplicated")
  258. return
  259. }
  260. m[v] = true
  261. }
  262. return
  263. }