config.go 5.8 KB

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