// receiver calls OnRead every time a packet is received // OnRead returns true, if the roundtrip estimate has changed func (t *receiverRoundtripEstimator) OnRead(ff *dccp.FeedforwardHeader) bool { // Read RoundtripReportOption // Currently RoundtripReportOption is allowed on any packet type var report *RoundtripReportOption for _, opt := range ff.Options { if report = DecodeRoundtripReportOption(opt); report != nil { break } } if report == nil { t.amb.E(dccp.EventWarn, "Missing roundtrip report opt", ff) return false } // Sanity checks rtt := dccp.NanoFromTenMicro(report.Roundtrip) if rtt <= 0 || rtt > 30e9 { t.amb.E(dccp.EventWarn, "Invalid roundtrip report opt", ff) return false } // Update RTT estimate t.rtt, t.rttTime = rtt, ff.Time t.amb.E(dccp.EventMatch, fmt.Sprintf("Report —> RTT=%s", dccp.Nstoa(t.rtt)), ff, RoundtripSample(RoundtripReportSample, t.rtt), RoundtripReportCheckpoint) return true }
// htmlize orders a slice of logPipes by time and prints them to standard output with the // surrounding HTML boilerplate func htmlize(records []*logPipe, srt bool, includeEmits bool) { if srt { sort.Sort(logPipeTimeSort(records)) } fmt.Println(htmlHeader) var last int64 var sec int64 var sflag rune = ' ' var series SeriesSweeper series.Init() for _, r := range records { series.Add(r.Log) r.Pipe.Time = fmt.Sprintf("%15s %c", dccp.Nstoa(r.Log.Time-last), sflag) r.Pipe.TimeAbs = fmt.Sprintf("%c %-15s", sflag, dccp.Nstoa(r.Log.Time)) sflag = ' ' last = r.Log.Time if last/1e9 > sec { sflag = '*' sec = last / 1e9 } if includeEmits { fmt.Println(htmlizePipe(r.Pipe)) } } if includeEmits { // TODO: The spacer row is a hack to prevent TDs from collapsing their width subSpacer := emitSubPipe{ State: "", Detail: "", Left: " ", Right: " ", } spacer := &emitPipe{ Client: subSpacer, Pipe: subSpacer, Server: subSpacer, Event: "spacer", } fmt.Println(htmlizePipe(spacer)) } fmt.Println(htmlFooterPreSeries) printGraphJavaScript(os.Stdout, &series) fmt.Println(htmlFooterPostSeries) }
// Sender calls OnRead for every arriving Ack packet. // OnRead returns true if the RTT estimate has changed. func (t *senderRoundtripEstimator) OnRead(fb *dccp.FeedbackHeader) bool { // Read ElapsedTimeOption if fb.Type != dccp.Ack && fb.Type != dccp.DataAck { return false } var elapsed *dccp.ElapsedTimeOption for _, opt := range fb.Options { if elapsed = dccp.DecodeElapsedTimeOption(opt); elapsed != nil { break } } if elapsed == nil { t.amb.E(dccp.EventWarn, "Missing elapsed opt", fb) return false } // Update RTT estimate s := t.find(fb.AckNo) if s == nil { return false } elapsedNS := dccp.NanoFromTenMicro(elapsed.Elapsed) // Elapsed time at receiver in nanoseconds if elapsedNS < 0 { t.amb.E(dccp.EventWarn, "Invalid elapsed opt", fb) return false } est := (fb.Time - s.Time - elapsedNS) if est <= 0 { t.amb.E(dccp.EventWarn, "Invalid elapsed opt", fb) return false } est_old := t.estimate if est_old == 0 { t.estimate = est } else { t.estimate = (est*SenderRoundtripWeightNew + est_old*SenderRoundtripWeightOld) / (SenderRoundtripWeightNew + SenderRoundtripWeightOld) } t.amb.E(dccp.EventMatch, fmt.Sprintf("Elapsed —> RTT=%s", dccp.Nstoa(t.estimate)), fb, RoundtripSample(RoundtripElapsedSample, t.estimate), RoundtripElapsedCheckpoint) return true }
// Print orders a sequence of print recors by time and prints them to standard output func Print(records []*PrintRecord, srt bool) { if srt { sort.Sort(PrintTimeSort(records)) } var last int64 var sec int64 var sflag rune = ' ' for _, r := range records { if r.Log != nil { fmt.Printf("%15s %c %s %18s:%-3d\n", dccp.Nstoa(r.Log.Time-last), sflag, r.Text, r.Log.SourceFile, r.Log.SourceLine) sflag = ' ' last = r.Log.Time if last/1e9 > sec { sflag = '*' sec = last / 1e9 } } else { fmt.Printf(" %s\n", r.Text) sflag = ' ' last = 0 } } }