Merge pull request #12 from vasilvv/mouseover-flag
Make the zoom level required for packet info display configurable
diff --git a/lib/quic_trace.proto b/lib/quic_trace.proto
index 66e3e56..9924634 100644
--- a/lib/quic_trace.proto
+++ b/lib/quic_trace.proto
@@ -1,11 +1,11 @@
// Copyright 2018 Google LLC
-//
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
-//
+//
// https://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -117,6 +117,7 @@
ENCRYPTION_INITIAL = 1;
ENCRYPTION_0RTT = 2;
ENCRYPTION_1RTT = 3;
+ ENCRYPTION_HANDSHAKE = 4;
};
enum EventType {
diff --git a/tools/render/processed_trace.cc b/tools/render/processed_trace.cc
index 81a6645..9f74677 100644
--- a/tools/render/processed_trace.cc
+++ b/tools/render/processed_trace.cc
@@ -16,6 +16,7 @@
#include "absl/algorithm/container.h"
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
#include "tools/render/layout_constants.h"
namespace quic_trace {
@@ -232,6 +233,37 @@
return "???";
}
}
+
+constexpr int kMaxAckBlocksShown = 3;
+std::string AckSummary(const AckInfo& ack) {
+ if (ack.acked_packets_size() == 0) {
+ return "";
+ }
+
+ bool overflow = false;
+ int blocks_to_show = ack.acked_packets_size();
+ if (blocks_to_show > kMaxAckBlocksShown) {
+ blocks_to_show = kMaxAckBlocksShown;
+ overflow = true;
+ }
+
+ std::vector<std::string> ack_ranges;
+ for (int i = 0; i < blocks_to_show; i++) {
+ const AckBlock& block = ack.acked_packets(i);
+ if (block.first_packet() == block.last_packet()) {
+ ack_ranges.push_back(absl::StrCat(block.first_packet()));
+ } else {
+ ack_ranges.push_back(
+ absl::StrCat(block.first_packet(), ":", block.last_packet()));
+ }
+ }
+
+ std::string result = absl::StrJoin(ack_ranges, ", ");
+ if (overflow) {
+ absl::StrAppend(&result, "...");
+ }
+ return result;
+}
} // namespace
void ProcessedTrace::FillTableForPacket(Table* table,
@@ -276,7 +308,7 @@
absl::StrCat("#", frame.stream_frame_info().stream_id(), ": ",
frame.stream_frame_info().offset(), "-",
frame.stream_frame_info().offset() +
- frame.stream_frame_info().length(),
+ frame.stream_frame_info().length(),
" (", frame.stream_frame_info().length(), ")"));
break;
case RESET_STREAM:
@@ -299,6 +331,9 @@
table->AddRow("Stream blocked",
absl::StrCat(frame.flow_control_info().stream_id()));
break;
+ case ACK:
+ table->AddRow("Ack", AckSummary(frame.ack_info()));
+ break;
default:
table->AddRow("Unknown", "");
break;
diff --git a/tools/render/sdl_util.h b/tools/render/sdl_util.h
index f5380f8..a465418 100644
--- a/tools/render/sdl_util.h
+++ b/tools/render/sdl_util.h
@@ -21,6 +21,8 @@
#include <GL/glew.h>
#include <SDL.h>
+#include <memory>
+
#include <glog/logging.h>
#include <glog/stl_logging.h>
#include "absl/memory/memory.h"
@@ -39,25 +41,22 @@
};
// A helper class to automatically delete SDL objects once they go out of scope.
-template <typename T, void (*D)(T)>
+template <typename T, void (*D)(T*)>
class ScopedSdlType {
public:
- ScopedSdlType(T value) : value_(value) {}
- ~ScopedSdlType() { D(value_); }
+ ScopedSdlType() : value_(nullptr, D) {}
+ ScopedSdlType(T* value) : value_(value, D) {}
- ScopedSdlType(const ScopedSdlType&) = delete;
- ScopedSdlType& operator=(const ScopedSdlType&) = delete;
-
- T get() const { return value_; }
- T operator*() const { return value_; }
- T operator->() const { return value_; }
+ T* get() const { return value_.get(); }
+ T* operator*() const { return value_.get(); }
+ T* operator->() const { return value_.get(); }
private:
- T value_;
+ std::unique_ptr<T, void (*)(T*)> value_;
};
-using ScopedSdlWindow = ScopedSdlType<SDL_Window*, SDL_DestroyWindow>;
-using ScopedSdlSurface = ScopedSdlType<SDL_Surface*, SDL_FreeSurface>;
+using ScopedSdlWindow = ScopedSdlType<SDL_Window, SDL_DestroyWindow>;
+using ScopedSdlSurface = ScopedSdlType<SDL_Surface, SDL_FreeSurface>;
class OpenGlContext {
public:
diff --git a/tools/render/text.cc b/tools/render/text.cc
index 6cf45ad..577ea25 100644
--- a/tools/render/text.cc
+++ b/tools/render/text.cc
@@ -119,14 +119,24 @@
return cache_it->second.text;
}
- // Render the text.
if (TTF_GetFontStyle(font_) != style) {
TTF_SetFontStyle(font_, style);
}
- ScopedSdlSurface surface(
- TTF_RenderUTF8_Blended(font_, text.c_str(), SDL_Color{0, 0, 0}));
+
+ // Render the text.
+ ScopedSdlSurface surface;
+ if (text.empty()) {
+ // SDL2_ttf returns error when asked to render an empty string. Return a
+ // 1x1 white square instead.
+ surface = ScopedSdlSurface(
+ SDL_CreateRGBSurfaceWithFormat(0, 1, 1, 32, SDL_PIXELFORMAT_RGBA32));
+ CHECK(!SDL_MUSTLOCK(*surface));
+ memset(surface->pixels, 0xff, surface->h * surface->pitch);
+ } else {
+ surface = TTF_RenderUTF8_Blended(font_, text.c_str(), SDL_Color{0, 0, 0});
+ }
if (*surface == nullptr) {
- LOG(FATAL) << "Failed to render text: " << text;
+ LOG(FATAL) << "Failed to render text: \"" << text.size() << "\"";
}
std::unique_ptr<Text> result(new Text(this));