I use this code to capture Ehternet packet:
var snapshotLen int32 = 102400
var promiscuous bool = true
var timeout time.Duration = 1 * time.Second
var handle *pcap.Handle
handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
err = handle.SetBPFFilter(filter)
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
}
Problem is packetSource.Packets() is blocking: if no packet received, there is an infinite loop. How can I do to set a timeout?
From the docs:
func (p *PacketSource) Packets() chan Packet
Packets returns a channel of packets, allowing easy iterating over packets. Packets will be asynchronously read in from the underlying PacketDataSource and written to the returned channel. If the underlying
PacketDataSource
returns anio.EOF
error, the channel will be closed. If any other error is encountered, it is ignored.for packet := range packetSource.Packets() { handlePacket(packet) // Do something with each packet. }
If called more than once, returns the same channel.
So, since gopacket.PacketSource.Packets()
returns a channel, you can employ the usual tactic of select
ing on two channels—an operation on one of which is controlled by a timeout.
In the simplest case, something like this would do:
timer := time.NewTicker(2 * time.Second)
defer timer.Stop()
src := gopacket.NewPacketSource(handle, handle.LinkType())
for {
select {
case pkt := <- src.Packets():
// process a packet in pkt
case <- timer.C:
// timed out waiting for 2 seconds
}
}
Depending on the exact use case, the second channel can come from another source—such as a context.