github.com/fafucoder/cilium@v1.6.11/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  }