Documentation ¶
Overview ¶
Package tcpreader provides an implementation for tcpassembly.Stream which presents the caller with an io.Reader for easy processing.
The assembly package handles packet data reordering, but its output is library-specific, thus not usable by the majority of external Go libraries. The io.Reader interface, on the other hand, is used throughout much of Go code as an easy mechanism for reading in data streams and decoding them. For example, the net/http package provides the ReadRequest function, which can parase an HTTP request from a live data stream, just what we'd want when sniffing HTTP traffic. Using ReaderStream, this is relatively easy to set up:
// Create our StreamFactory type httpStreamFactory struct {} func (f *httpStreamFactory) New(a, b gopacket.Flow) { r := tcpreader.NewReaderStream(false) go printRequests(r) return &r } func printRequests(r io.Reader) { // Convert to bufio, since that's what ReadRequest wants. buf := bufio.NewReader(r) for { if req, err := http.ReadRequest(buf); err == io.EOF { return } else if err != nil { log.Println("Error parsing HTTP requests:", err) } else { fmt.Println("HTTP REQUEST:", req) fmt.Println("Body contains", tcpreader.DiscardBytesToEOF(req.Body), "bytes") } } }
Using just this code, we're able to reference a powerful, built-in library for HTTP request parsing to do all the dirty-work of parsing requests from the wire in real-time. Pass this stream factory to an tcpassembly.StreamPool, start up an tcpassembly.Assembler, and you're good to go!
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DataLost error = errors.New("lost data")
DataLost is returned by the ReaderStream's Read function when it encounters a Reassembly with Skip != 0.
Functions ¶
func DiscardBytesToEOF ¶
DiscardBytesToEOF will read in all bytes from a Reader until it encounters an io.EOF, then return the number of bytes. Be careful of this... if used on a Reader that returns a non-io.EOF error consistently, this will loop forever discarding that error while it waits for an EOF.
Example ¶
b := bytes.NewBuffer([]byte{1, 2, 3, 4, 5}) fmt.Println(DiscardBytesToEOF(b))
Output: 5
Types ¶
type ReaderStream ¶
type ReaderStream struct { ReaderStreamOptions // contains filtered or unexported fields }
ReaderStream implements both tcpassembly.Stream and io.Reader. You can use it as a building block to make simple, easy stream handlers.
IMPORTANT: If you use a ReaderStream, you MUST read ALL BYTES from it, quickly. Not reading available bytes will block TCP stream reassembly. It's a common pattern to do this by starting a goroutine in the factory's New method:
type myStreamHandler struct { r ReaderStream } func (m *myStreamHandler) run() { // Do something here that reads all of the ReaderStream, or your assembly // will block. fmt.Println(tcpreader.DiscardBytesToEOF(&m.r)) } func (f *myStreamFactory) New(a, b gopacket.Flow) tcpassembly.Stream { s := &myStreamHandler{} go s.run() // Return the ReaderStream as the stream that assembly should populate. return &s.r }
func NewReaderStream ¶
func NewReaderStream() ReaderStream
NewReaderStream returns a new ReaderStream object.
func (*ReaderStream) Close ¶
func (r *ReaderStream) Close() error
Close implements io.Closer's Close function, making ReaderStream a io.ReadCloser. It discards all remaining bytes in the reassembly in a manner that's safe for the assembler (IE: it doesn't block).
func (*ReaderStream) Read ¶
func (r *ReaderStream) Read(p []byte) (int, error)
Read implements io.Reader's Read function. Given a byte slice, it will either copy a non-zero number of bytes into that slice and return the number of bytes and a nil error, or it will leave slice p as is and return 0, io.EOF.
func (*ReaderStream) Reassembled ¶
func (r *ReaderStream) Reassembled(reassembly []tcpassembly.Reassembly)
Reassembled implements tcpassembly.Stream's Reassembled function.
func (*ReaderStream) ReassemblyComplete ¶
func (r *ReaderStream) ReassemblyComplete()
ReassemblyComplete implements tcpassembly.Stream's ReassemblyComplete function.
type ReaderStreamOptions ¶
type ReaderStreamOptions struct { // LossErrors determines whether this stream will return // ReaderStreamDataLoss errors from its Read function whenever it // determines data has been lost. LossErrors bool }