trunk.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package flowclass
  2. import (
  3. "bytes"
  4. "fmt"
  5. "idio.link/go/netaddr/v2"
  6. "idio.link/go/parser"
  7. )
  8. /*
  9. root ::= <srcs> -> <dstcs>
  10. dstcs ::= <dst> | {<dst_1>, ..., <dst_n>}
  11. dstc ::= <dsts>:<ipps>
  12. srcs ::= <pfxs>
  13. dsts ::= <pfxs>
  14. pfxs ::= <pfx> | {<pfx_1>, ..., <pfx_n>}
  15. pfx ::= <oct>[.<oct>[...]][/<len>]
  16. oct ::= 0-255
  17. port ::= 0-65535
  18. len ::= 0-32
  19. ipps ::= <ippi> | {<ippi_1>, ..., <ippi_n>}
  20. ippi ::= 0 | <ipp>[(<parm_1>, ..., <parm_n>)]
  21. ipp ::= icmp | tcp | udp | 1-255
  22. */
  23. /************************** Root **************************/
  24. type fcRoot struct{}
  25. func (t fcRoot) Shift(sm *parser.SM, e rune) error {
  26. switch e {
  27. case ' ', '\n':
  28. return nil
  29. }
  30. last := len(sm.Top().Nodes) - 1
  31. if last == -1 {
  32. return sm.Push(fcSrcs{}).Shift(sm, e)
  33. }
  34. token := sm.Top().Nodes[last].ASTNode
  35. switch token.(type) {
  36. case fcSrcs:
  37. buf := new(bytes.Buffer)
  38. buf.WriteRune(e)
  39. sm.Push(fcArrow{val: buf})
  40. case fcArrow:
  41. return sm.Push(fcDsts{}).Shift(sm, e)
  42. case fcDsts:
  43. buf := new(bytes.Buffer)
  44. buf.WriteRune(e)
  45. sm.Push(fcIPPDelim{val: buf})
  46. case fcIPPDelim:
  47. return sm.Push(fcIPPs{}).Shift(sm, e)
  48. case fcIPPs:
  49. return nil
  50. default:
  51. return fmt.Errorf("unexpected state: %+v; event: %v", sm, e)
  52. }
  53. return nil
  54. }
  55. func (t fcRoot) Coalesce(nodes []*parser.CSTNode) any {
  56. nodes[2].Coalesce().([]*DstSock),
  57. fc := &FlowClass{
  58. srcs: nodes[0].Coalesce().(map[string]*netaddr.NetAddr),
  59. dsts: nodes[2].Coalesce().([]*DstSock),
  60. }
  61. if len(nodes) == 5 {
  62. fc.ipps = nodes[4].Coalesce().(map[string]IPP)
  63. }
  64. return fc
  65. }
  66. func (t fcRoot) Value() *bytes.Buffer {
  67. return nil
  68. }
  69. /************************** Srcs **************************/
  70. type fcSrcs struct{}
  71. func (t fcSrcs) Shift(sm *parser.SM, e rune) error {
  72. if len(sm.Top().Nodes) == 0 {
  73. return sm.Push(fcPfxs{}).Shift(sm, e)
  74. }
  75. return parser.NewUnrecognized("sources", e)
  76. }
  77. func (t fcSrcs) Coalesce(nodes []*parser.CSTNode) any {
  78. return nodes[0].Coalesce()
  79. }
  80. func (t fcSrcs) Value() *bytes.Buffer {
  81. return nil
  82. }
  83. /************************* Arrow **************************/
  84. type fcArrow struct {
  85. val *bytes.Buffer
  86. }
  87. func (t fcArrow) Shift(sm *parser.SM, e rune) error {
  88. switch e {
  89. case '-', '>':
  90. t.val.WriteRune(e)
  91. default:
  92. if string(t.val.Bytes()) != "->" {
  93. return fmt.Errorf("arrow: unexpected input: '%s'", t.val.Bytes())
  94. }
  95. return parser.NewUnrecognized("arrow", e)
  96. }
  97. return nil
  98. }
  99. func (_ fcArrow) Coalesce(_ []*parser.CSTNode) any {
  100. return nil
  101. }
  102. func (t fcArrow) Value() *bytes.Buffer {
  103. return t.val
  104. }
  105. /*********************** DstSocks *************************/
  106. type fcDstSocks struct{}
  107. func (t fcDstSocks) Shift(sm *parser.SM, e rune) error {
  108. if len(sm.Top().Nodes) == 0 {
  109. return sm.Push(fcPfxs{}).Shift(sm, e)
  110. }
  111. return parser.NewUnrecognized("destinations", e)
  112. }
  113. func (t fcDstSocks) Coalesce(nodes []*parser.CSTNode) any {
  114. return nodes[0].Coalesce()
  115. }
  116. func (t fcDstSocks) Value() *bytes.Buffer {
  117. return nil
  118. }
  119. /********************** DstSockSet ************************/
  120. type fcDstSockSet struct{}
  121. func (t fcDstSockSet) Shift(sm *parser.SM, e rune) error {
  122. next := fcSet[fcDstSock, *netaddr.NetAddr]{
  123. newToken: func() fcDstSock {
  124. return fcDstSock{}
  125. },
  126. }
  127. if len(sm.Top().Nodes) == 0 {
  128. return sm.Push(next).Shift(sm, e)
  129. }
  130. return parser.NewUnrecognized("prefix set", e)
  131. }
  132. func (t fcDstSockSet) Coalesce(nodes []*parser.CSTNode) any {
  133. return nodes[0].Coalesce()
  134. }
  135. func (t fcDstSockSet) Value() *bytes.Buffer {
  136. return nil
  137. }
  138. type fcDstSock struct{}
  139. /************************** Dsts **************************/
  140. type fcDsts struct{}
  141. func (t fcDsts) Shift(sm *parser.SM, e rune) error {
  142. if len(sm.Top().Nodes) == 0 {
  143. return sm.Push(fcPfxs{}).Shift(sm, e)
  144. }
  145. return parser.NewUnrecognized("destinations", e)
  146. }
  147. func (t fcDsts) Coalesce(nodes []*parser.CSTNode) any {
  148. return nodes[0].Coalesce()
  149. }
  150. func (t fcDsts) Value() *bytes.Buffer {
  151. return nil
  152. }