config.go 6.6 KB

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