main.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. package main
  2. import (
  3. "fmt"
  4. "git.swzry.com/zry/go-hhc-cli/hhc_ast"
  5. "git.swzry.com/zry/go-hhc-cli/hhc_common"
  6. "github.com/cheynewallace/tabby"
  7. "math/rand"
  8. "net"
  9. "os"
  10. "regexp"
  11. "strconv"
  12. "strings"
  13. )
  14. var FRGEXP *regexp.Regexp
  15. var ExecSB strings.Builder
  16. func FExec(ctx *hhc_ast.SDTWalkContext) hhc_common.SDTWalkError {
  17. fmt.Println("! Command Execute: ", CtxToCommand(ctx))
  18. ExecSB.WriteString(CtxToCommand(ctx) + "\r\n")
  19. return nil
  20. }
  21. func VLoopbackInf(t string) bool {
  22. i, e := strconv.Atoi(t)
  23. if e != nil {
  24. return false
  25. }
  26. if i < 0 || i > 7 {
  27. return false
  28. }
  29. return true
  30. }
  31. func VSubnetLen(t string) bool {
  32. i, e := strconv.Atoi(t)
  33. if e != nil {
  34. return false
  35. }
  36. if i < 1 || i > 31 {
  37. return false
  38. }
  39. return true
  40. }
  41. func VMTU(t string) bool {
  42. i, e := strconv.Atoi(t)
  43. if e != nil {
  44. return false
  45. }
  46. if i < 128 || i > 1500 {
  47. return false
  48. }
  49. return true
  50. }
  51. func VVlanInf(t string) bool {
  52. i, e := strconv.Atoi(t)
  53. if e != nil {
  54. return false
  55. }
  56. if i < 0 || i > 4095 {
  57. return false
  58. }
  59. return true
  60. }
  61. func VIPAddress(t string) bool {
  62. _, err := net.ResolveIPAddr("ip", t)
  63. return err == nil
  64. }
  65. func main() {
  66. var err error
  67. FRGEXP, err = regexp.Compile("INTEGER<([0-9]+)\\-([0-9]+)>")
  68. if err != nil {
  69. fmt.Println("Failed Compile Regexp:", err)
  70. return
  71. }
  72. ctx := &hhc_ast.SDTWalkContext{ASTNodes: []hhc_ast.ASTNode{}}
  73. var cur hhc_ast.SyntaxDefTreeNode
  74. cur = (&hhc_ast.SyntaxDefinitionTreeRoot{}).AddCommand(
  75. (&hhc_ast.SDTNode_Command{
  76. Name: "ip",
  77. Description: "Specify IP configuration",
  78. }).AddSubCommand(
  79. (&hhc_ast.SDTNode_Command{
  80. Name: "address",
  81. Description: "Set the IP address of an interface",
  82. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  83. Name: "dhcp-alloc",
  84. Description: "Obtain an IP address through DHCP",
  85. }).AddEnd(&hhc_ast.SDTNode_End{
  86. Exec: FExec,
  87. })).AddSubCommand((&hhc_ast.SDTNode_Command{
  88. Name: "unnumbered",
  89. Description: "Share an address with another interface",
  90. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  91. Name: "interface",
  92. Description: "Specify the interface whose ip address was unnumbered",
  93. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  94. Name: "loopback",
  95. Description: "LoopBack interface",
  96. }).AddValArgument((&hhc_ast.SDTNode_Argument{
  97. FormatDescription: "INTEGER<0-7>",
  98. Description: "LoopBack interface number",
  99. Validator: VLoopbackInf,
  100. }).AddEnd(&hhc_ast.SDTNode_End{
  101. Exec: FExec,
  102. }))).AddSubCommand((&hhc_ast.SDTNode_Command{
  103. Name: "vlan-interface",
  104. Description: "VLAN interface",
  105. }).AddValArgument((&hhc_ast.SDTNode_Argument{
  106. FormatDescription: "INTEGER<0-4095>",
  107. Description: "Vlan-interface interface number",
  108. Validator: VVlanInf,
  109. }).AddEnd(&hhc_ast.SDTNode_End{
  110. Exec: FExec,
  111. }))))).AddValArgument((&hhc_ast.SDTNode_Argument{
  112. FormatDescription: "X.X.X.X",
  113. Description: "IP address",
  114. Validator: VIPAddress,
  115. }).AddValArgument((&hhc_ast.SDTNode_Argument{
  116. FormatDescription: "INTEGER<1-31>",
  117. Description: "IP mask length",
  118. Validator: VSubnetLen,
  119. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  120. Name: "sub",
  121. Description: "Indicate a subordinate address",
  122. }).AddEnd(&hhc_ast.SDTNode_End{
  123. Exec: FExec,
  124. })).AddEnd(&hhc_ast.SDTNode_End{
  125. Exec: FExec,
  126. })).AddValArgument((&hhc_ast.SDTNode_Argument{
  127. FormatDescription: "X.X.X.X",
  128. Description: "IP mask",
  129. Validator: VIPAddress,
  130. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  131. Name: "sub",
  132. Description: "Indicate a subordinate address",
  133. }).AddEnd(&hhc_ast.SDTNode_End{
  134. Exec: FExec,
  135. })).AddEnd(&hhc_ast.SDTNode_End{
  136. Exec: FExec,
  137. })))).AddSubCommand((&hhc_ast.SDTNode_Command{
  138. Name: "mtu",
  139. Description: "Specify the MTU of the interface",
  140. }).AddValArgument((&hhc_ast.SDTNode_Argument{
  141. FormatDescription: "INTEGER<128-1500>",
  142. Description: "MTU in bytes",
  143. Validator: VMTU,
  144. }).AddEnd(&hhc_ast.SDTNode_End{
  145. Exec: FExec,
  146. })))).AddCommand((&hhc_ast.SDTNode_Command{
  147. Name: "ipv6",
  148. Description: "Specify IPv6 configuration",
  149. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  150. Name: "dhcp",
  151. Description: "Configure DHCPv6",
  152. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  153. Name: "select",
  154. Description: "Specify process mode of DHCPv6 packet",
  155. }).AddSubCommand((&hhc_ast.SDTNode_Command{
  156. Name: "relay",
  157. Description: "Relay mode",
  158. }).AddEnd(&hhc_ast.SDTNode_End{
  159. Exec: FExec,
  160. })).AddSubCommand((&hhc_ast.SDTNode_Command{
  161. Name: "server",
  162. Description: "Server mode",
  163. }).AddEnd(&hhc_ast.SDTNode_End{
  164. Exec: FExec,
  165. })))).AddSubCommand((&hhc_ast.SDTNode_Command{
  166. Name: "mtu",
  167. Description: "Specify the IPv6 MTU of the interface",
  168. }).AddValArgument((&hhc_ast.SDTNode_Argument{
  169. FormatDescription: "INTEGER<128-1500>",
  170. Description: "MTU in bytes",
  171. Validator: VMTU,
  172. }).AddEnd(&hhc_ast.SDTNode_End{
  173. Exec: FExec,
  174. }))))
  175. t := GenerateValByFormatDesc("X.X.X.X")
  176. fmt.Println(t, VIPAddress(t))
  177. t = GenerateValByFormatDesc("INTEGER<1-31>")
  178. fmt.Println(t, VSubnetLen(t))
  179. fmt.Println("==== ==== ==== Ready ==== ==== ====")
  180. AutoWalk(ctx, cur)
  181. fmt.Println("==== ==== ==== End of AutoWalk ==== ==== ====")
  182. fmt.Println("All Command Lines:")
  183. fmt.Println(ExecSB.String())
  184. //_, _ = ctx, cur
  185. }
  186. func Walk(ctx *hhc_ast.SDTWalkContext, cur hhc_ast.SyntaxDefTreeNode, token string) hhc_ast.SyntaxDefTreeNode {
  187. fmt.Println("Walk into with token:", token)
  188. ncur, err := cur.WalkNext(ctx, token)
  189. if err != nil {
  190. fmt.Println("Error In Walk")
  191. fmt.Println("FES:", err.FES())
  192. fmt.Println("EES:", err.EES())
  193. os.Exit(-1)
  194. }
  195. fmt.Println("Walked into", GetCtxPath(ctx))
  196. return ncur
  197. }
  198. func AutoWalk(ctx *hhc_ast.SDTWalkContext, cur hhc_ast.SyntaxDefTreeNode) {
  199. fmt.Println("======== Help of", GetCtxPath(ctx), "========")
  200. if cur.IsEnd() {
  201. switch cur.(type) {
  202. case *hhc_ast.SDTNode_End:
  203. ncur := cur.(*hhc_ast.SDTNode_End)
  204. ncur.Exec(ctx)
  205. }
  206. return
  207. }
  208. PrintHelp(cur.GetHelps(""))
  209. for _, v := range cur.GetHelps("") {
  210. nctx := CopyCtx(ctx)
  211. var cin hhc_ast.SyntaxDefTreeNode
  212. if v.IsArg {
  213. cin = Walk(nctx, cur, GenerateValByFormatDesc(v.Name))
  214. } else {
  215. cin = Walk(nctx, cur, v.Name)
  216. }
  217. AutoWalk(nctx, cin)
  218. }
  219. }
  220. func CopyCtx(ctx *hhc_ast.SDTWalkContext) *hhc_ast.SDTWalkContext {
  221. nctx := &hhc_ast.SDTWalkContext{ASTNodes: make([]hhc_ast.ASTNode, len(ctx.ASTNodes))}
  222. for i, v := range ctx.ASTNodes {
  223. nctx.ASTNodes[i] = v
  224. }
  225. return nctx
  226. }
  227. func PrintHelp(h []hhc_common.SDTHelpInfo) {
  228. t := tabby.New()
  229. for i, v := range h {
  230. t.AddLine(i, v.IsArg, v.Name, v.Description)
  231. }
  232. t.Print()
  233. }
  234. func GetCtxPath(ctx *hhc_ast.SDTWalkContext) string {
  235. sb := strings.Builder{}
  236. sb.WriteString("/")
  237. for _, v := range ctx.ASTNodes {
  238. sb.WriteString(v.GetTokenRaw() + "/")
  239. }
  240. return sb.String()
  241. }
  242. func CtxToCommand(ctx *hhc_ast.SDTWalkContext) string {
  243. sb := strings.Builder{}
  244. for _, v := range ctx.ASTNodes {
  245. sb.WriteString(v.GetTokenRaw() + " ")
  246. }
  247. return sb.String()
  248. }
  249. func GenerateValByFormatDesc(format string) string {
  250. if format == "<cr>" {
  251. return ""
  252. }
  253. if format == "X.X.X.X" {
  254. return "192.168.1.1"
  255. }
  256. ret := FRGEXP.FindAllStringSubmatch(format, 1)
  257. if len(ret) == 1 {
  258. if len(ret[0]) == 3 {
  259. min, _ := strconv.Atoi(ret[0][1])
  260. max, _ := strconv.Atoi(ret[0][2])
  261. vi := rand.Intn(max-min) + min
  262. return strconv.Itoa(vi)
  263. }
  264. }
  265. return ""
  266. }