1 /*
2  * libjingle
3  * Copyright 2012 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 // This file contains structures used for retrieving statistics from an ongoing
29 // libjingle session.
30 
31 #ifndef TALK_APP_WEBRTC_STATSTYPES_H_
32 #define TALK_APP_WEBRTC_STATSTYPES_H_
33 
34 #include <algorithm>
35 #include <list>
36 #include <map>
37 #include <string>
38 
39 #include "webrtc/base/basictypes.h"
40 #include "webrtc/base/common.h"
41 #include "webrtc/base/refcount.h"
42 #include "webrtc/base/scoped_ptr.h"
43 #include "webrtc/base/linked_ptr.h"
44 #include "webrtc/base/scoped_ref_ptr.h"
45 #include "webrtc/base/stringencode.h"
46 #include "webrtc/base/thread_checker.h"
47 
48 namespace webrtc {
49 
50 class StatsReport {
51  public:
52   // Indicates whether a track is for sending or receiving.
53   // Used in reports for audio/video tracks.
54   enum Direction {
55     kSend = 0,
56     kReceive,
57   };
58 
59   enum StatsType {
60     // StatsReport types.
61     // A StatsReport of |type| = "googSession" contains overall information
62     // about the thing libjingle calls a session (which may contain one
63     // or more RTP sessions.
64     kStatsReportTypeSession,
65 
66     // A StatsReport of |type| = "googTransport" contains information
67     // about a libjingle "transport".
68     kStatsReportTypeTransport,
69 
70     // A StatsReport of |type| = "googComponent" contains information
71     // about a libjingle "channel" (typically, RTP or RTCP for a transport).
72     // This is intended to be the same thing as an ICE "Component".
73     kStatsReportTypeComponent,
74 
75     // A StatsReport of |type| = "googCandidatePair" contains information
76     // about a libjingle "connection" - a single source/destination port pair.
77     // This is intended to be the same thing as an ICE "candidate pair".
78     kStatsReportTypeCandidatePair,
79 
80     // A StatsReport of |type| = "VideoBWE" is statistics for video Bandwidth
81     // Estimation, which is global per-session.  The |id| field is "bweforvideo"
82     // (will probably change in the future).
83     kStatsReportTypeBwe,
84 
85     // A StatsReport of |type| = "ssrc" is statistics for a specific rtp stream.
86     // The |id| field is the SSRC in decimal form of the rtp stream.
87     kStatsReportTypeSsrc,
88 
89     // A StatsReport of |type| = "remoteSsrc" is statistics for a specific
90     // rtp stream, generated by the remote end of the connection.
91     kStatsReportTypeRemoteSsrc,
92 
93     // A StatsReport of |type| = "googTrack" is statistics for a specific media
94     // track. The |id| field is the track id.
95     kStatsReportTypeTrack,
96 
97     // A StatsReport of |type| = "localcandidate" or "remotecandidate" is
98     // attributes on a specific ICE Candidate. It links to its connection pair
99     // by candidate id. The string value is taken from
100     // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
101     kStatsReportTypeIceLocalCandidate,
102     kStatsReportTypeIceRemoteCandidate,
103 
104     // A StatsReport of |type| = "googCertificate" contains an SSL certificate
105     // transmitted by one of the endpoints of this connection.  The |id| is
106     // controlled by the fingerprint, and is used to identify the certificate in
107     // the Channel stats (as "googLocalCertificateId" or
108     // "googRemoteCertificateId") and in any child certificates (as
109     // "googIssuerId").
110     kStatsReportTypeCertificate,
111 
112     // A StatsReport of |type| = "datachannel" with statistics for a
113     // particular DataChannel.
114     kStatsReportTypeDataChannel,
115   };
116 
117   enum StatsValueName {
118     kStatsValueNameActiveConnection,
119     kStatsValueNameAudioInputLevel,
120     kStatsValueNameAudioOutputLevel,
121     kStatsValueNameBytesReceived,
122     kStatsValueNameBytesSent,
123     kStatsValueNameCodecImplementationName,
124     kStatsValueNameDataChannelId,
125     kStatsValueNamePacketsLost,
126     kStatsValueNamePacketsReceived,
127     kStatsValueNamePacketsSent,
128     kStatsValueNameProtocol,
129     kStatsValueNameReceiving,
130     kStatsValueNameSelectedCandidatePairId,
131     kStatsValueNameSsrc,
132     kStatsValueNameState,
133     kStatsValueNameTransportId,
134 
135     // Internal StatsValue names.
136     kStatsValueNameAccelerateRate,
137     kStatsValueNameActualEncBitrate,
138     kStatsValueNameAdaptationChanges,
139     kStatsValueNameAvailableReceiveBandwidth,
140     kStatsValueNameAvailableSendBandwidth,
141     kStatsValueNameAvgEncodeMs,
142     kStatsValueNameBandwidthLimitedResolution,
143     kStatsValueNameBucketDelay,
144     kStatsValueNameCaptureStartNtpTimeMs,
145     kStatsValueNameCandidateIPAddress,
146     kStatsValueNameCandidateNetworkType,
147     kStatsValueNameCandidatePortNumber,
148     kStatsValueNameCandidatePriority,
149     kStatsValueNameCandidateTransportType,
150     kStatsValueNameCandidateType,
151     kStatsValueNameChannelId,
152     kStatsValueNameCodecName,
153     kStatsValueNameComponent,
154     kStatsValueNameContentName,
155     kStatsValueNameCpuLimitedResolution,
156     kStatsValueNameCurrentDelayMs,
157     kStatsValueNameDecodeMs,
158     kStatsValueNameDecodingCNG,
159     kStatsValueNameDecodingCTN,
160     kStatsValueNameDecodingCTSG,
161     kStatsValueNameDecodingNormal,
162     kStatsValueNameDecodingPLC,
163     kStatsValueNameDecodingPLCCNG,
164     kStatsValueNameDer,
165     kStatsValueNameDtlsCipher,
166     kStatsValueNameEchoCancellationQualityMin,
167     kStatsValueNameEchoDelayMedian,
168     kStatsValueNameEchoDelayStdDev,
169     kStatsValueNameEchoReturnLoss,
170     kStatsValueNameEchoReturnLossEnhancement,
171     kStatsValueNameEncodeUsagePercent,
172     kStatsValueNameExpandRate,
173     kStatsValueNameFingerprint,
174     kStatsValueNameFingerprintAlgorithm,
175     kStatsValueNameFirsReceived,
176     kStatsValueNameFirsSent,
177     kStatsValueNameFrameHeightInput,
178     kStatsValueNameFrameHeightReceived,
179     kStatsValueNameFrameHeightSent,
180     kStatsValueNameFrameRateDecoded,
181     kStatsValueNameFrameRateInput,
182     kStatsValueNameFrameRateOutput,
183     kStatsValueNameFrameRateReceived,
184     kStatsValueNameFrameRateSent,
185     kStatsValueNameFrameWidthInput,
186     kStatsValueNameFrameWidthReceived,
187     kStatsValueNameFrameWidthSent,
188     kStatsValueNameInitiator,
189     kStatsValueNameIssuerId,
190     kStatsValueNameJitterBufferMs,
191     kStatsValueNameJitterReceived,
192     kStatsValueNameLabel,
193     kStatsValueNameLocalAddress,
194     kStatsValueNameLocalCandidateId,
195     kStatsValueNameLocalCandidateType,
196     kStatsValueNameLocalCertificateId,
197     kStatsValueNameMaxDecodeMs,
198     kStatsValueNameMinPlayoutDelayMs,
199     kStatsValueNameNacksReceived,
200     kStatsValueNameNacksSent,
201     kStatsValueNamePlisReceived,
202     kStatsValueNamePlisSent,
203     kStatsValueNamePreemptiveExpandRate,
204     kStatsValueNamePreferredJitterBufferMs,
205     kStatsValueNameRemoteAddress,
206     kStatsValueNameRemoteCandidateId,
207     kStatsValueNameRemoteCandidateType,
208     kStatsValueNameRemoteCertificateId,
209     kStatsValueNameRenderDelayMs,
210     kStatsValueNameRetransmitBitrate,
211     kStatsValueNameRtt,
212     kStatsValueNameSecondaryDecodedRate,
213     kStatsValueNameSendPacketsDiscarded,
214     kStatsValueNameSpeechExpandRate,
215     kStatsValueNameSrtpCipher,
216     kStatsValueNameTargetDelayMs,
217     kStatsValueNameTargetEncBitrate,
218     kStatsValueNameTrackId,
219     kStatsValueNameTransmitBitrate,
220     kStatsValueNameTransportType,
221     kStatsValueNameTypingNoiseState,
222     kStatsValueNameViewLimitedResolution,
223     kStatsValueNameWritable,
224   };
225 
226   class IdBase : public rtc::RefCountInterface {
227    public:
228     ~IdBase() override;
229     StatsType type() const;
230 
231     // Users of IdBase will be using the Id typedef, which is compatible with
232     // this Equals() function.  It simply calls the protected (and overridden)
233     // Equals() method.
Equals(const rtc::scoped_refptr<IdBase> & other)234     bool Equals(const rtc::scoped_refptr<IdBase>& other) const {
235       return Equals(*other.get());
236     }
237 
238     virtual std::string ToString() const = 0;
239 
240    protected:
241     // Protected since users of the IdBase type will be using the Id typedef.
242     virtual bool Equals(const IdBase& other) const;
243 
244     IdBase(StatsType type);  // Only meant for derived classes.
245     const StatsType type_;
246 
247     static const char kSeparator = '_';
248   };
249 
250   typedef rtc::scoped_refptr<IdBase> Id;
251 
252   struct Value {
253     enum Type {
254       kInt,           // int.
255       kInt64,         // int64_t.
256       kFloat,         // float.
257       kString,        // std::string
258       kStaticString,  // const char*.
259       kBool,          // bool.
260       kId,            // Id.
261     };
262 
263     Value(StatsValueName name, int64_t value, Type int_type);
264     Value(StatsValueName name, float f);
265     Value(StatsValueName name, const std::string& value);
266     Value(StatsValueName name, const char* value);
267     Value(StatsValueName name, bool b);
268     Value(StatsValueName name, const Id& value);
269 
270     ~Value();
271 
272     // TODO(tommi): This compares name as well as value...
273     // I think we should only need to compare the value part and
274     // move the name part into a hash map.
275     bool Equals(const Value& other) const;
276 
277     // Comparison operators. Return true iff the current instance is of the
278     // correct type and holds the same value.  No conversion is performed so
279     // a string value of "123" is not equal to an int value of 123 and an int
280     // value of 123 is not equal to a float value of 123.0f.
281     // One exception to this is that types kInt and kInt64 can be compared and
282     // kString and kStaticString too.
283     bool operator==(const std::string& value) const;
284     bool operator==(const char* value) const;
285     bool operator==(int64_t value) const;
286     bool operator==(bool value) const;
287     bool operator==(float value) const;
288     bool operator==(const Id& value) const;
289 
290     // Getters that allow getting the native value directly.
291     // The caller must know the type beforehand or else hit a check.
292     int int_val() const;
293     int64_t int64_val() const;
294     float float_val() const;
295     const char* static_string_val() const;
296     const std::string& string_val() const;
297     bool bool_val() const;
298     const Id& id_val() const;
299 
300     // Returns the string representation of |name|.
301     const char* display_name() const;
302 
303     // Converts the native value to a string representation of the value.
304     std::string ToString() const;
305 
typeValue306     Type type() const { return type_; }
307 
308     // TODO(tommi): Move |name| and |display_name| out of the Value struct.
309     const StatsValueName name;
310 
311    private:
312     const Type type_;
313     // TODO(tommi): Use C++ 11 union and make value_ const.
314     union InternalType {
315       int int_;
316       int64_t int64_;
317       float float_;
318       bool bool_;
319       std::string* string_;
320       const char* static_string_;
321       Id* id_;
322     } value_;
323 
324    private:
325     RTC_DISALLOW_COPY_AND_ASSIGN(Value);
326   };
327 
328   // TODO(tommi): Consider using a similar approach to how we store Ids using
329   // scoped_refptr for values.
330   typedef rtc::linked_ptr<Value> ValuePtr;
331   typedef std::map<StatsValueName, ValuePtr> Values;
332 
333   // Ownership of |id| is passed to |this|.
334   explicit StatsReport(const Id& id);
335 
336   // Factory functions for various types of stats IDs.
337   static Id NewBandwidthEstimationId();
338   static Id NewTypedId(StatsType type, const std::string& id);
339   static Id NewTypedIntId(StatsType type, int id);
340   static Id NewIdWithDirection(
341       StatsType type, const std::string& id, Direction direction);
342   static Id NewCandidateId(bool local, const std::string& id);
343   static Id NewComponentId(
344       const std::string& content_name, int component);
345   static Id NewCandidatePairId(
346       const std::string& content_name, int component, int index);
347 
id()348   const Id& id() const { return id_; }
type()349   StatsType type() const { return id_->type(); }
timestamp()350   double timestamp() const { return timestamp_; }
set_timestamp(double t)351   void set_timestamp(double t) { timestamp_ = t; }
empty()352   bool empty() const { return values_.empty(); }
values()353   const Values& values() const { return values_; }
354 
355   const char* TypeToString() const;
356 
357   void AddString(StatsValueName name, const std::string& value);
358   void AddString(StatsValueName name, const char* value);
359   void AddInt64(StatsValueName name, int64_t value);
360   void AddInt(StatsValueName name, int value);
361   void AddFloat(StatsValueName name, float value);
362   void AddBoolean(StatsValueName name, bool value);
363   void AddId(StatsValueName name, const Id& value);
364 
365   const Value* FindValue(StatsValueName name) const;
366 
367  private:
368   // The unique identifier for this object.
369   // This is used as a key for this report in ordered containers,
370   // so it must never be changed.
371   const Id id_;
372   double timestamp_;  // Time since 1970-01-01T00:00:00Z in milliseconds.
373   Values values_;
374 
375   RTC_DISALLOW_COPY_AND_ASSIGN(StatsReport);
376 };
377 
378 // Typedef for an array of const StatsReport pointers.
379 // Ownership of the pointers held by this implementation is assumed to lie
380 // elsewhere and lifetime guarantees are made by the implementation that uses
381 // this type.  In the StatsCollector, object ownership lies with the
382 // StatsCollection class.
383 typedef std::vector<const StatsReport*> StatsReports;
384 
385 // A map from the report id to the report.
386 // This class wraps an STL container and provides a limited set of
387 // functionality in order to keep things simple.
388 class StatsCollection {
389  public:
390   StatsCollection();
391   ~StatsCollection();
392 
393   typedef std::list<StatsReport*> Container;
394   typedef Container::iterator iterator;
395   typedef Container::const_iterator const_iterator;
396 
397   const_iterator begin() const;
398   const_iterator end() const;
399   size_t size() const;
400 
401   // Creates a new report object with |id| that does not already
402   // exist in the list of reports.
403   StatsReport* InsertNew(const StatsReport::Id& id);
404   StatsReport* FindOrAddNew(const StatsReport::Id& id);
405   StatsReport* ReplaceOrAddNew(const StatsReport::Id& id);
406 
407   // Looks for a report with the given |id|.  If one is not found, NULL
408   // will be returned.
409   StatsReport* Find(const StatsReport::Id& id);
410 
411  private:
412   Container list_;
413   rtc::ThreadChecker thread_checker_;
414 };
415 
416 }  // namespace webrtc
417 
418 #endif  // TALK_APP_WEBRTC_STATSTYPES_H_
419