npc.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package main
  2. import (
  3. "ehang.io/nps/client"
  4. "ehang.io/nps/lib/common"
  5. "ehang.io/nps/lib/daemon"
  6. "ehang.io/nps/lib/version"
  7. "fmt"
  8. "fyne.io/fyne/v2"
  9. "fyne.io/fyne/v2/app"
  10. "fyne.io/fyne/v2/container"
  11. "fyne.io/fyne/v2/layout"
  12. "fyne.io/fyne/v2/widget"
  13. "github.com/astaxie/beego/logs"
  14. "io/ioutil"
  15. "os"
  16. "path"
  17. "runtime"
  18. "strings"
  19. "time"
  20. )
  21. func main() {
  22. daemon.InitDaemon("npc", common.GetRunPath(), common.GetTmpPath())
  23. logs.SetLogger("store")
  24. application := app.New()
  25. window := application.NewWindow("Npc " + version.VERSION)
  26. window.SetContent(WidgetScreen())
  27. window.Resize(fyne.NewSize(910, 350))
  28. window.ShowAndRun()
  29. }
  30. var (
  31. start bool
  32. closing bool
  33. status = "Start!"
  34. connType = "tcp"
  35. cl = new(client.TRPClient)
  36. refreshCh = make(chan struct{})
  37. )
  38. func WidgetScreen() fyne.CanvasObject {
  39. return fyne.NewContainerWithLayout(layout.NewBorderLayout(nil, nil, nil, nil),
  40. makeMainTab(),
  41. )
  42. }
  43. func makeMainTab() *fyne.Container {
  44. serverPort := widget.NewEntry()
  45. serverPort.SetPlaceHolder("Server:Port")
  46. vKey := widget.NewEntry()
  47. vKey.SetPlaceHolder("Vkey")
  48. radio := widget.NewRadioGroup([]string{"tcp", "kcp"}, func(s string) { connType = s })
  49. radio.Horizontal = true
  50. button := widget.NewButton(status, func() {
  51. onclick(serverPort.Text, vKey.Text, connType)
  52. })
  53. go func() {
  54. for {
  55. <-refreshCh
  56. button.SetText(status)
  57. }
  58. }()
  59. lo := widget.NewMultiLineEntry()
  60. lo.Disable()
  61. lo.Resize(fyne.NewSize(910, 250))
  62. slo := container.NewScroll(lo)
  63. slo.Resize(fyne.NewSize(910, 250))
  64. go func() {
  65. for {
  66. time.Sleep(time.Second)
  67. lo.SetText(common.GetLogMsg())
  68. slo.Resize(fyne.NewSize(910, 250))
  69. }
  70. }()
  71. sp, vk, ct := loadConfig()
  72. if sp != "" && vk != "" && ct != "" {
  73. serverPort.SetText(sp)
  74. vKey.SetText(vk)
  75. connType = ct
  76. radio.SetSelected(ct)
  77. onclick(sp, vk, ct)
  78. }
  79. return container.NewVBox(
  80. widget.NewLabel("Npc "+version.VERSION),
  81. serverPort,
  82. vKey,
  83. radio,
  84. button,
  85. slo,
  86. )
  87. }
  88. func onclick(s, v, c string) {
  89. start = !start
  90. if start {
  91. closing = false
  92. status = "Stop!"
  93. // init the npc
  94. fmt.Println("submit", s, v, c)
  95. sp, vk, ct := loadConfig()
  96. if sp != s || vk != v || ct != c {
  97. saveConfig(s, v, c)
  98. }
  99. go func() {
  100. for {
  101. cl = client.NewRPClient(s, v, c, "", nil, 60)
  102. status = "Stop!"
  103. refreshCh <- struct{}{}
  104. cl.Start()
  105. logs.Warn("client closed, reconnecting in 5 seconds...")
  106. if closing {
  107. return
  108. }
  109. status = "Reconnecting..."
  110. refreshCh <- struct{}{}
  111. time.Sleep(time.Second * 5)
  112. }
  113. }()
  114. } else {
  115. // close the npc
  116. status = "Start!"
  117. closing = true
  118. if cl != nil {
  119. go cl.Close()
  120. cl = nil
  121. }
  122. }
  123. refreshCh <- struct{}{}
  124. }
  125. func getDir() (dir string, err error) {
  126. if runtime.GOOS != "android" {
  127. dir, err = os.UserConfigDir()
  128. if err != nil {
  129. return
  130. }
  131. } else {
  132. dir = "/data/data/org.nps.client/files"
  133. }
  134. return
  135. }
  136. func saveConfig(host, vkey, connType string) {
  137. data := strings.Join([]string{host, vkey, connType}, "\n")
  138. ph, err := getDir()
  139. if err != nil {
  140. logs.Warn("not found config dir")
  141. return
  142. }
  143. _ = os.Remove(path.Join(ph, "npc.conf"))
  144. f, err := os.OpenFile(path.Join(ph, "npc.conf"), os.O_CREATE|os.O_WRONLY, 0644)
  145. defer f.Close()
  146. if err != nil {
  147. logs.Error(err)
  148. return
  149. }
  150. if _, err := f.Write([]byte(data)); err != nil {
  151. _ = f.Close() // ignore error; Write error takes precedence
  152. logs.Error(err)
  153. return
  154. }
  155. }
  156. func loadConfig() (host, vkey, connType string) {
  157. ph, err := getDir()
  158. if err != nil {
  159. logs.Warn("not found config dir")
  160. return
  161. }
  162. f, err := os.OpenFile(path.Join(ph, "npc.conf"), os.O_RDONLY, 0644)
  163. defer f.Close()
  164. if err != nil {
  165. logs.Error(err)
  166. return
  167. }
  168. data, err := ioutil.ReadAll(f)
  169. if err != nil {
  170. logs.Error(err)
  171. return
  172. }
  173. li := strings.Split(string(data), "\n")
  174. host = li[0]
  175. vkey = li[1]
  176. connType = li[2]
  177. return
  178. }