Add packet timeout callback #50

This commit is contained in:
Hampton Moore 2021-08-26 22:58:26 -04:00 committed by thatmattlove
parent 779d1e9195
commit 2c3c45023c
2 changed files with 38 additions and 5 deletions

View File

@ -77,6 +77,9 @@ func main() {
fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v (DUP!)\n",
pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
}
pinger.OnTimeout = func(await *ping.AwaitingPacket) {
fmt.Printf("TIMEOUT icmp_seq=%d time=%v\n", await.Seq, await.DispatchedTime)
}
pinger.OnFinish = func(stats *ping.Statistics) {
fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr)
fmt.Printf("%d packets transmitted, %d packets received, %d duplicates, %v%% packet loss\n",

40
ping.go
View File

@ -91,11 +91,13 @@ func New(addr string) *Pinger {
var firstSequence = map[uuid.UUID]map[int]struct{}{}
firstSequence[firstUUID] = make(map[int]struct{})
return &Pinger{
Count: -1,
Interval: time.Second,
RecordRtts: true,
Size: timeSliceLength + trackerLength,
Timeout: time.Duration(math.MaxInt64),
Count: -1,
Interval: time.Second,
RecordRtts: true,
Size: timeSliceLength + trackerLength,
Timeout: time.Duration(math.MaxInt64),
PacketTimeout: time.Duration(1 * time.Second),
Tracker: r.Uint64(),
addr: addr,
done: make(chan interface{}),
@ -126,6 +128,10 @@ type Pinger struct {
// packets have been received.
Timeout time.Duration
// PacketTimeout specifies a timeout before the OnTimeout function is called
// for a packet not being received
PacketTimeout time.Duration
// Count tells pinger to stop after sending (and receiving) Count echo
// packets. If this option is not specified, pinger will operate until
// interrupted.
@ -170,6 +176,9 @@ type Pinger struct {
// OnFinish is called when Pinger exits
OnFinish func(*Statistics)
// OnTimeout is called when packet timeout
OnTimeout func(*AwaitingPacket)
// OnDuplicateRecv is called when a packet is received that has already been received.
OnDuplicateRecv func(*Packet)
@ -207,6 +216,11 @@ type Pinger struct {
TTL int
}
type AwaitingPacket struct {
DispatchedTime time.Time
Seq int
}
type packet struct {
bytes []byte
nbytes int
@ -477,6 +491,7 @@ func (p *Pinger) runLoop(
return nil
case <-timeout.C:
p.CheckAwaitingSequences()
return nil
case r := <-recvCh:
@ -487,11 +502,13 @@ func (p *Pinger) runLoop(
}
case <-interval.C:
p.CheckAwaitingSequences()
if p.Count > 0 && p.PacketsSent >= p.Count {
interval.Stop()
continue
}
err := p.sendICMP(conn)
if err != nil {
// FIXME: this logs as FATAL but continues
logger.Fatalf("sending packet: %s", err)
@ -503,6 +520,19 @@ func (p *Pinger) runLoop(
}
}
func (p *Pinger) CheckAwaitingSequences() {
// Loop through each item in map
currentTime := time.Now()
for seq, awaiting := range p.awaitingSequences {
if awaiting.DispatchedTime.Add(p.PacketTimeout).Before(currentTime) {
delete(p.awaitingSequences, seq)
if p.OnTimeout != nil {
p.OnTimeout(&awaiting)
}
}
}
}
func (p *Pinger) Stop() {
p.lock.Lock()
defer p.lock.Unlock()