diff --git a/pcap/reader.go b/pcap/reader.go index 85f6aa3..1d07312 100644 --- a/pcap/reader.go +++ b/pcap/reader.go @@ -27,6 +27,9 @@ type Reader struct { r io.Reader order binary.ByteOrder tmult int64 + + pkt *Packet + err error } // Packet is one raw packet and its metadata. @@ -94,8 +97,26 @@ func NewReader(r io.Reader) (*Reader, error) { return ret, nil } -// Next returns the next packet in r. -func (r *Reader) Next() (*Packet, error) { +// Packet returns the packet read by the last call to Next. +func (r *Reader) Packet() *Packet { + return r.pkt +} + +// Err returns the first non-EOF error encountered by the Reader. +func (r *Reader) Err() error { + if r.err == io.EOF { + return nil + } + return r.err +} + +// Next advances the Reader to the next packet in the input, which +// will then be available through the Packet method. It returns false +// when the Reader stops, either by reaching the end of the input or +// an error. After Next returns false, the Err method will return any +// error that occured while reading, except that if it was io.EOF, Err +// will return nil. +func (r *Reader) Next() bool { hdr := struct { Sec uint32 SubSec uint32 @@ -104,17 +125,20 @@ func (r *Reader) Next() (*Packet, error) { }{} if err := binary.Read(r.r, r.order, &hdr); err != nil { - return nil, err + r.err = err + return false } bs := make([]byte, hdr.Len) if _, err := io.ReadFull(r.r, bs); err != nil { - return nil, err + r.err = err + return false } - return &Packet{ + r.pkt = &Packet{ Timestamp: time.Unix(int64(hdr.Sec), r.tmult*int64(hdr.SubSec)), Length: int(hdr.OrigLen), Bytes: bs, - }, nil + } + return true } diff --git a/pcap/reader_test.go b/pcap/reader_test.go index 34cc1d4..9fc09e0 100644 --- a/pcap/reader_test.go +++ b/pcap/reader_test.go @@ -2,7 +2,6 @@ package pcap import ( "fmt" - "io" "io/ioutil" "os" "testing" @@ -23,18 +22,15 @@ func TestFiles(t *testing.T) { if r.LinkType != LinkEthernet { t.Errorf("Expected link type %d, got %d", LinkEthernet, r.LinkType) } + pkts := []*Packet{} - ReadLoop: - for { - pkt, err := r.Next() - if err != nil { - if err == io.EOF { - break ReadLoop - } - t.Fatalf("Unexpected error reading packets: %s", err) - } - pkts = append(pkts, pkt) + for r.Next() { + pkts = append(pkts, r.Packet()) } + if r.Err() != nil { + t.Fatalf("Reading packets from %s.pcap: %s", fname, r.Err()) + } + res := pretty.Sprintf("%# v", pkts) expectedFile := fmt.Sprintf("testdata/%s.parsed", fname) expected, err := ioutil.ReadFile(expectedFile) diff --git a/pcap/writer_test.go b/pcap/writer_test.go index 1d38b60..5f99364 100644 --- a/pcap/writer_test.go +++ b/pcap/writer_test.go @@ -3,7 +3,6 @@ package pcap import ( "bytes" "encoding/binary" - "io" "reflect" "testing" "time" @@ -63,16 +62,11 @@ func TestReadback(t *testing.T) { t.Fatalf("Wrote link type %d, read back %d", LinkEthernet, r.LinkType) } - ReadLoop: - for { - pkt, err := r.Next() - if err != nil { - if err == io.EOF { - break ReadLoop - } - t.Fatalf("Unexpected error reading packets: %s", err) - } - readBack = append(readBack, pkt) + for r.Next() { + readBack = append(readBack, r.Packet()) + } + if r.Err() != nil { + t.Fatalf("Reading packets back: %s", r.Err()) } if !reflect.DeepEqual(pkts, readBack) {