github.com/zhyoulun/cilium@v1.6.12/proxylib/testparsers/lineparser.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package testparsers 16 17 import ( 18 "bytes" 19 20 . "github.com/cilium/cilium/proxylib/proxylib" 21 22 log "github.com/sirupsen/logrus" 23 ) 24 25 // 26 // Line parser used for testing 27 // 28 29 type LineParserFactory struct{} 30 31 var lineParserFactory *LineParserFactory 32 33 func init() { 34 log.Debug("init(): Registering lineParserFactory") 35 RegisterParserFactory("test.lineparser", lineParserFactory) 36 } 37 38 type LineParser struct { 39 connection *Connection 40 inserted bool 41 } 42 43 func (p *LineParserFactory) Create(connection *Connection) Parser { 44 log.Debugf("LineParserFactory: Create: %v", connection) 45 return &LineParser{connection: connection} 46 } 47 48 func getLine(data [][]byte) ([]byte, bool) { 49 var line bytes.Buffer 50 for i, s := range data { 51 index := bytes.IndexByte(s, '\n') 52 if index < 0 { 53 line.Write(s) 54 } else { 55 log.Debugf("getLine: unit: %d length: %d index: %d", i, len(s), index) 56 line.Write(s[:index+1]) 57 return line.Bytes(), true 58 } 59 } 60 return line.Bytes(), false 61 } 62 63 // 64 // Parses individual lines that must start with one of: 65 // "PASS" the line is passed 66 // "DROP" the line is dropped 67 // "INJECT" the line is injected in reverse direction 68 // "INSERT" the line is injected in current direction 69 // 70 func (p *LineParser) OnData(reply, endStream bool, data [][]byte) (OpType, int) { 71 line, ok := getLine(data) 72 line_len := len(line) 73 74 if p.inserted { 75 p.inserted = false 76 return DROP, line_len 77 } 78 79 if !reply { 80 log.Debugf("LineParser: Request: %s", line) 81 } else { 82 log.Debugf("LineParser: Response: %s", line) 83 } 84 85 if !ok { 86 if line_len > 0 { 87 // Partial line received, but no newline, ask for more 88 return MORE, 1 89 } else { 90 // Nothing received, don't know if more will be coming; do nothing 91 return NOP, 0 92 } 93 } 94 95 if bytes.HasPrefix(line, []byte("PASS")) { 96 return PASS, line_len 97 } 98 if bytes.HasPrefix(line, []byte("DROP")) { 99 return DROP, line_len 100 } 101 if bytes.HasPrefix(line, []byte("INJECT")) { 102 // Inject line in the reverse direction 103 p.connection.Inject(!reply, []byte(line)) 104 // Drop the INJECT line in the current direction 105 return DROP, line_len 106 } 107 if bytes.HasPrefix(line, []byte("INSERT")) { 108 // Inject the line in the current direction 109 p.connection.Inject(reply, []byte(line)) 110 // Drop the INJECT line in the current direction 111 p.inserted = true 112 return INJECT, line_len 113 } 114 115 return ERROR, int(ERROR_INVALID_FRAME_TYPE) 116 }