1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
18 #define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
19 
20 #include <stddef.h>
21 #include <memory>
22 #include <tuple>
23 
24 #include "perfetto/base/export.h"
25 #include "perfetto/base/logging.h"
26 #include "perfetto/ext/tracing/core/slice.h"
27 
28 namespace perfetto {
29 
30 // A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
31 // (see trace_packet.proto). The TracePacket is decoded only if the Consumer
32 // requests that. This is to allow Consumer(s) to just stream the packet over
33 // the network or save it to a file without wasting time decoding it and without
34 // needing to depend on libprotobuf or the trace_packet.pb.h header.
35 // If the packets are saved / streamed and not just consumed locally, consumers
36 // should ensure to preserve the unknown fields in the proto. A consumer, in
37 // fact, might have an older version .proto which is newer on the producer.
38 class PERFETTO_EXPORT TracePacket {
39  public:
40   using const_iterator = Slices::const_iterator;
41 
42   // The field id of protos::Trace::packet, static_assert()-ed in the unittest.
43   static constexpr uint32_t kPacketFieldNumber = 1;
44 
45   // Maximum size of the preamble returned by GetProtoPreamble().
46   static constexpr size_t kMaxPreambleBytes = 8;
47 
48   TracePacket();
49   ~TracePacket();
50   TracePacket(TracePacket&&) noexcept;
51   TracePacket& operator=(TracePacket&&);
52 
53   // Accesses all the raw slices in the packet, for saving them to file/network.
slices()54   const Slices& slices() const { return slices_; }
55 
56   // Mutator, used only by the service and tests.
57   void AddSlice(Slice);
58 
59   // Does not copy / take ownership of the memory of the slice. The TracePacket
60   // will be valid only as long as the original buffer is valid.
61   void AddSlice(const void* start, size_t size);
62 
63   // Total size of all slices.
size()64   size_t size() const { return size_; }
65 
66   // Generates a protobuf preamble suitable to represent this packet as a
67   // repeated field within a root trace.proto message.
68   // Returns a pointer to a buffer, owned by this class, containing the preamble
69   // and its size.
70   std::tuple<char*, size_t> GetProtoPreamble();
71 
72   // Returns the raw protobuf bytes of the slices, all stitched together into
73   // a string. Only for testing.
74   std::string GetRawBytesForTesting();
75 
76  private:
77   TracePacket(const TracePacket&) = delete;
78   TracePacket& operator=(const TracePacket&) = delete;
79 
80   Slices slices_;     // Not owned.
81   size_t size_ = 0;   // SUM(slice.size for slice in slices_).
82   char preamble_[kMaxPreambleBytes];  // Deliberately not initialized.
83 
84   // Remember to update the move operators and their unittest if adding new
85   // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on
86   // std::move(TracePacket) to clear up the moved-from instance.
87 };
88 
89 }  // namespace perfetto
90 
91 #endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
92