config.go 5.0 KB

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