Files
goreplay/protocol.go
T
Urban IshimweandGitHub fdc8b094f0 Benchmarking, packaging, and fix issues, tests and perfomance (#797)
### performance
- handling of the very big packet(any size that can be buffered)
- speeding up TCP sessions by using message hints: Added **proto.HasFullPayload** that helps to validate the entire HTTP request, it supports `Chunked` encoding too! Added **proto.HasRequestTitle** and **proto.HasResponseTitle** for validating the beginning of HTTP request. Those methods are used `input_raw.go` with `TCP`.
- supports Keep-Alive: the above functions helps to support keep-alive

### Packaging
- **capture:** engines(capture/doc.go)
- **tcp:** tcp message parser (tcp/doc.go)

### benchmarking
- **capture.BenchmarkPcapDump:** the benchmarks regarding dumping packets in a pcap file
- **capture.BenchmarkPcapFile:** the benchmarks of reading packets from a pcap file
- **capture.BenchmarkPcap:** the benchmarks of parsing packets from the loopback interface with pcap handles
- **proto.BenchmarkHasFullPayload:**: benchmarking this function which validates the HTTP payload
- **tcp.BenchmarkPacketParseAndSort:** benchmarks of parsing and sorting packets
- **tcp.BenchmarkMessageParserWithoutHint:** benchmarks of message reasembling by using `SYN` and `FIN` flag
- **tcp.BenchmarkMessageParserWithHint:** benchmarks of message reasembling by using `proto.HasRequestTitle` and `proto.HasFullPayload` flag

### issues
see linked issues

###  tests
- fixed input raw and engine tests

**Most of the changed of the files, was about using functionalities of** `tcp` **and** `capture` **in existing functionalities**
2020-08-11 12:44:53 +03:00

93 lines
1.9 KiB
Go

package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"fmt"
)
// These constants help to indicate the type of payload
const (
RequestPayload = '1'
ResponsePayload = '2'
ReplayedResponsePayload = '3'
)
func randByte(len int) []byte {
b := make([]byte, len/2)
rand.Read(b)
h := make([]byte, len)
hex.Encode(h, b)
return h
}
func uuid() []byte {
return randByte(24)
}
var payloadSeparator = "\n🐵🙈🙉\n"
func payloadScanner(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.Index(data, []byte(payloadSeparator)); i >= 0 {
// We have a full newline-terminated line.
return i + len([]byte(payloadSeparator)), data[0:i], nil
}
if atEOF {
return len(data), data, nil
}
return 0, nil, nil
}
// Timing is request start or round-trip time, depending on payloadType
func payloadHeader(payloadType byte, uuid []byte, timing int64, latency int64) (header []byte) {
//Example:
// 3 f45590522cd1838b4a0d5c5aab80b77929dea3b3 13923489726487326 1231\n
return []byte(fmt.Sprintf("%c %s %d %d\n", payloadType, uuid, timing, latency))
}
func payloadBody(payload []byte) []byte {
headerSize := bytes.IndexByte(payload, '\n')
return payload[headerSize+1:]
}
func payloadMeta(payload []byte) [][]byte {
headerSize := bytes.IndexByte(payload, '\n')
if headerSize < 0 {
return nil
}
return bytes.Split(payload[:headerSize], []byte{' '})
}
func payloadID(payload []byte) (id []byte) {
meta := payloadMeta(payload)
if len(meta) < 2 {
return
}
// id is encoded in hex, we need to revert to how it was
id = make([]byte, 20)
hex.Decode(id, meta[1])
return
}
func isOriginPayload(payload []byte) bool {
switch payload[0] {
case RequestPayload, ResponsePayload:
return true
default:
return false
}
}
func isRequestPayload(payload []byte) bool {
return payload[0] == RequestPayload
}