123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package flowclass
- import (
- "bytes"
- "fmt"
- "idio.link/go/netaddr/v2"
- "idio.link/go/parser"
- )
- /*
- root ::= <srcs> -> <dstcs>
- dstcs ::= <dst> | {<dst_1>, ..., <dst_n>}
- dstc ::= <dsts>:<ipps>
- srcs ::= <pfxs>
- dsts ::= <pfxs>
- pfxs ::= <pfx> | {<pfx_1>, ..., <pfx_n>}
- pfx ::= <oct>[.<oct>[...]][/<len>]
- oct ::= 0-255
- port ::= 0-65535
- len ::= 0-32
- ipps ::= <ippi> | {<ippi_1>, ..., <ippi_n>}
- ippi ::= 0 | <ipp>[(<parm_1>, ..., <parm_n>)]
- ipp ::= icmp | tcp | udp | 1-255
- */
- /************************** Root **************************/
- type fcRoot struct{}
- func (t fcRoot) Shift(sm *parser.SM, e rune) error {
- switch e {
- case ' ', '\n':
- return nil
- }
- last := len(sm.Top().Nodes) - 1
- if last == -1 {
- return sm.Push(fcSrcs{}).Shift(sm, e)
- }
- token := sm.Top().Nodes[last].ASTNode
- switch token.(type) {
- case fcSrcs:
- buf := new(bytes.Buffer)
- buf.WriteRune(e)
- sm.Push(fcArrow{val: buf})
- case fcArrow:
- return sm.Push(fcDsts{}).Shift(sm, e)
- case fcDsts:
- buf := new(bytes.Buffer)
- buf.WriteRune(e)
- sm.Push(fcIPPDelim{val: buf})
- case fcIPPDelim:
- return sm.Push(fcIPPs{}).Shift(sm, e)
- case fcIPPs:
- return nil
- default:
- return fmt.Errorf("unexpected state: %+v; event: %v", sm, e)
- }
- return nil
- }
- func (t fcRoot) Coalesce(nodes []*parser.CSTNode) any {
- nodes[2].Coalesce().([]*DstSock),
- fc := &FlowClass{
- srcs: nodes[0].Coalesce().(map[string]*netaddr.NetAddr),
- dsts: nodes[2].Coalesce().([]*DstSock),
- }
- if len(nodes) == 5 {
- fc.ipps = nodes[4].Coalesce().(map[string]IPP)
- }
- return fc
- }
- func (t fcRoot) Value() *bytes.Buffer {
- return nil
- }
- /************************** Srcs **************************/
- type fcSrcs struct{}
- func (t fcSrcs) Shift(sm *parser.SM, e rune) error {
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(fcPfxs{}).Shift(sm, e)
- }
- return parser.NewUnrecognized("sources", e)
- }
- func (t fcSrcs) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcSrcs) Value() *bytes.Buffer {
- return nil
- }
- /************************* Arrow **************************/
- type fcArrow struct {
- val *bytes.Buffer
- }
- func (t fcArrow) Shift(sm *parser.SM, e rune) error {
- switch e {
- case '-', '>':
- t.val.WriteRune(e)
- default:
- if string(t.val.Bytes()) != "->" {
- return fmt.Errorf("arrow: unexpected input: '%s'", t.val.Bytes())
- }
- return parser.NewUnrecognized("arrow", e)
- }
- return nil
- }
- func (_ fcArrow) Coalesce(_ []*parser.CSTNode) any {
- return nil
- }
- func (t fcArrow) Value() *bytes.Buffer {
- return t.val
- }
- /*********************** DstSocks *************************/
- type fcDstSocks struct{}
- func (t fcDstSocks) Shift(sm *parser.SM, e rune) error {
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(fcPfxs{}).Shift(sm, e)
- }
- return parser.NewUnrecognized("destinations", e)
- }
- func (t fcDstSocks) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcDstSocks) Value() *bytes.Buffer {
- return nil
- }
- /********************** DstSockSet ************************/
- type fcDstSockSet struct{}
- func (t fcDstSockSet) Shift(sm *parser.SM, e rune) error {
- next := fcSet[fcDstSock, *netaddr.NetAddr]{
- newToken: func() fcDstSock {
- return fcDstSock{}
- },
- }
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(next).Shift(sm, e)
- }
- return parser.NewUnrecognized("prefix set", e)
- }
- func (t fcDstSockSet) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcDstSockSet) Value() *bytes.Buffer {
- return nil
- }
- type fcDstSock struct{}
- /************************** Dsts **************************/
- type fcDsts struct{}
- func (t fcDsts) Shift(sm *parser.SM, e rune) error {
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(fcPfxs{}).Shift(sm, e)
- }
- return parser.NewUnrecognized("destinations", e)
- }
- func (t fcDsts) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcDsts) Value() *bytes.Buffer {
- return nil
- }
|