tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rtc_error.h (12370B)


      1 /*
      2 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #ifndef API_RTC_ERROR_H_
     12 #define API_RTC_ERROR_H_
     13 
     14 #include <stdint.h>
     15 
     16 #include <optional>
     17 #include <string>
     18 #include <type_traits>
     19 #include <utility>  // For std::move.
     20 
     21 #include "absl/strings/str_cat.h"
     22 #include "absl/strings/string_view.h"
     23 #include "rtc_base/checks.h"
     24 #include "rtc_base/logging.h"
     25 #include "rtc_base/system/rtc_export.h"
     26 
     27 namespace webrtc {
     28 
     29 // Enumeration to represent distinct classes of errors that an application
     30 // may wish to act upon differently. These roughly map to DOMExceptions or
     31 // RTCError "errorDetailEnum" values in the web API, as described in the
     32 // comments below.
     33 enum class RTCErrorType {
     34  // No error.
     35  NONE,
     36 
     37  // An operation is valid, but currently unsupported.
     38  // Maps to OperationError DOMException.
     39  UNSUPPORTED_OPERATION,
     40 
     41  // A supplied parameter is valid, but currently unsupported.
     42  // Maps to OperationError DOMException.
     43  UNSUPPORTED_PARAMETER,
     44 
     45  // General error indicating that a supplied parameter is invalid.
     46  // Maps to InvalidAccessError or TypeError DOMException depending on context.
     47  INVALID_PARAMETER,
     48 
     49  // Slightly more specific than INVALID_PARAMETER; a parameter's value was
     50  // outside the allowed range.
     51  // Maps to RangeError DOMException.
     52  INVALID_RANGE,
     53 
     54  // Slightly more specific than INVALID_PARAMETER; an error occurred while
     55  // parsing string input.
     56  // Maps to SyntaxError DOMException.
     57  SYNTAX_ERROR,
     58 
     59  // The object does not support this operation in its current state.
     60  // Maps to InvalidStateError DOMException.
     61  INVALID_STATE,
     62 
     63  // An attempt was made to modify the object in an invalid way.
     64  // Maps to InvalidModificationError DOMException.
     65  INVALID_MODIFICATION,
     66 
     67  // An error occurred within an underlying network protocol.
     68  // Maps to NetworkError DOMException.
     69  NETWORK_ERROR,
     70 
     71  // Some resource has been exhausted; file handles, hardware resources, ports,
     72  // etc.
     73  // Maps to OperationError DOMException.
     74  RESOURCE_EXHAUSTED,
     75 
     76  // The operation failed due to an internal error.
     77  // Maps to OperationError DOMException.
     78  INTERNAL_ERROR,
     79 
     80  // An error occured that has additional data.
     81  // The additional data is specified in
     82  // https://w3c.github.io/webrtc-pc/#rtcerror-interface
     83  // Maps to RTCError DOMException.
     84  OPERATION_ERROR_WITH_DATA,
     85 };
     86 
     87 // Detail information, showing what further information should be present.
     88 // https://w3c.github.io/webrtc-pc/#rtcerrordetailtype-enum
     89 enum class RTCErrorDetailType {
     90  NONE,
     91  DATA_CHANNEL_FAILURE,
     92  DTLS_FAILURE,
     93  FINGERPRINT_FAILURE,
     94  SCTP_FAILURE,
     95  SDP_SYNTAX_ERROR,
     96  HARDWARE_ENCODER_NOT_AVAILABLE,
     97  HARDWARE_ENCODER_ERROR,
     98 };
     99 
    100 // Outputs the error as a friendly string. Update this method when adding a new
    101 // error type.
    102 //
    103 // Only intended to be used for logging/diagnostics. The returned char* points
    104 // to literal strings that live for the whole duration of the program.
    105 RTC_EXPORT absl::string_view ToString(RTCErrorType error);
    106 RTC_EXPORT absl::string_view ToString(RTCErrorDetailType error);
    107 
    108 template <typename Sink>
    109 void AbslStringify(Sink& sink, RTCErrorType error) {
    110  sink.Append(ToString(error));
    111 }
    112 
    113 template <typename Sink>
    114 void AbslStringify(Sink& sink, RTCErrorDetailType error_detail) {
    115  sink.Append(ToString(error_detail));
    116 }
    117 
    118 // Roughly corresponds to RTCError in the web api. Holds an error type, a
    119 // message, and possibly additional information specific to that error.
    120 //
    121 // Doesn't contain anything beyond a type and message now, but will in the
    122 // future as more errors are implemented.
    123 class RTC_EXPORT RTCError {
    124 public:
    125  // Constructors.
    126 
    127  // Creates a "no error" error.
    128  RTCError() {}
    129  explicit RTCError(RTCErrorType type) : type_(type) {}
    130 
    131  RTCError(RTCErrorType type, absl::string_view message)
    132      : type_(type), message_(message) {}
    133 
    134  // In many use cases, it is better to use move than copy,
    135  // but copy and assignment are provided for those cases that need it.
    136  // Note that this has extra overhead because it copies strings.
    137  RTCError(const RTCError& other) = default;
    138  RTCError(RTCError&&) = default;
    139  RTCError& operator=(const RTCError& other) = default;
    140  RTCError& operator=(RTCError&&) = default;
    141 
    142  // Identical to default constructed error.
    143  //
    144  // Preferred over the default constructor for code readability.
    145  static RTCError OK();
    146 
    147  // Error type.
    148  RTCErrorType type() const { return type_; }
    149  void set_type(RTCErrorType type) { type_ = type; }
    150 
    151  // Human-readable message describing the error. Shouldn't be used for
    152  // anything but logging/diagnostics, since messages are not guaranteed to be
    153  // stable.
    154  const char* message() const;
    155 
    156  void set_message(absl::string_view message);
    157 
    158  RTCErrorDetailType error_detail() const { return error_detail_; }
    159  void set_error_detail(RTCErrorDetailType detail) { error_detail_ = detail; }
    160  std::optional<uint16_t> sctp_cause_code() const { return sctp_cause_code_; }
    161  void set_sctp_cause_code(uint16_t cause_code) {
    162    sctp_cause_code_ = cause_code;
    163  }
    164 
    165  // Convenience method for situations where you only care whether or not an
    166  // error occurred.
    167  bool ok() const { return type_ == RTCErrorType::NONE; }
    168 
    169  template <typename Sink>
    170  friend void AbslStringify(Sink& sink, const RTCError& error) {
    171    sink.Append(ToString(error.type_));
    172    if (!error.message_.empty()) {
    173      sink.Append(" with message: \"");
    174      sink.Append(error.message_);
    175      sink.Append("\"");
    176    }
    177  }
    178 
    179 private:
    180  RTCErrorType type_ = RTCErrorType::NONE;
    181  std::string message_;
    182  RTCErrorDetailType error_detail_ = RTCErrorDetailType::NONE;
    183  std::optional<uint16_t> sctp_cause_code_;
    184 };
    185 
    186 // Helper macro that can be used by implementations to create an error with a
    187 // message and log it. `message` should be a string literal or movable
    188 // std::string.
    189 #define LOG_AND_RETURN_ERROR_EX(type, message, severity)                     \
    190  {                                                                          \
    191    RTC_DCHECK(type != RTCErrorType::NONE);                                  \
    192    RTC_LOG(severity) << message << " (" << ::webrtc::ToString(type) << ")"; \
    193    return ::webrtc::RTCError(type, message);                                \
    194  }
    195 
    196 #define LOG_AND_RETURN_ERROR(type, message) \
    197  LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR)
    198 
    199 // RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr
    200 // models the concept of an object that is either a usable value, or an error
    201 // Status explaining why such a value is not present. To this end RTCErrorOr<T>
    202 // does not allow its RTCErrorType value to be RTCErrorType::NONE. This is
    203 // enforced by a debug check in most cases.
    204 //
    205 // The primary use-case for RTCErrorOr<T> is as the return value of a function
    206 // which may fail. For example, CreateRtpSender will fail if the parameters
    207 // could not be successfully applied at the media engine level, but if
    208 // successful will return a unique_ptr to an RtpSender.
    209 //
    210 // Example client usage for a RTCErrorOr<std::unique_ptr<T>>:
    211 //
    212 //  RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
    213 //  if (result.ok()) {
    214 //    std::unique_ptr<Foo> foo = result.ConsumeValue();
    215 //    foo->DoSomethingCool();
    216 //  } else {
    217 //    RTC_LOG(LS_ERROR) << result.error();
    218 //  }
    219 //
    220 // Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>:
    221 //
    222 //  RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) {
    223 //    if (arg <= 0) {
    224 //      return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive");
    225 //    } else {
    226 //      return std::unique_ptr<Foo>(new Foo(arg));
    227 //    }
    228 //  }
    229 //
    230 template <typename T>
    231 class RTCErrorOr {
    232  // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit
    233  // conversion from Foo to Bar exists.
    234  template <typename U>
    235  friend class RTCErrorOr;
    236 
    237 public:
    238  typedef T element_type;
    239 
    240  // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This
    241  // is marked 'explicit' to try to catch cases like 'return {};', where people
    242  // think RTCErrorOr<std::vector<int>> will be initialized with an empty
    243  // vector, instead of a RTCErrorType::INTERNAL_ERROR error.
    244  RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {}
    245 
    246  // Constructs a new RTCErrorOr with the given non-ok error. After calling
    247  // this constructor, calls to value() will DCHECK-fail.
    248  //
    249  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return
    250  // value, so it is convenient and sensible to be able to do 'return
    251  // RTCError(...)' when the return type is RTCErrorOr<T>.
    252  //
    253  // REQUIRES: !error.ok(). This requirement is DCHECKed.
    254  RTCErrorOr(RTCError&& error) : error_(std::move(error)) {  // NOLINT
    255    RTC_DCHECK(!error_.ok());
    256  }
    257 
    258  // Constructs a new RTCErrorOr with the given value. After calling this
    259  // constructor, calls to value() will succeed, and calls to error() will
    260  // return a default-constructed RTCError.
    261  //
    262  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
    263  // so it is convenient and sensible to be able to do 'return T()'
    264  // when the return type is RTCErrorOr<T>.
    265  RTCErrorOr(const T& value) : value_(value) {}        // NOLINT
    266  RTCErrorOr(T&& value) : value_(std::move(value)) {}  // NOLINT
    267 
    268  // Delete the copy constructor and assignment operator; there aren't any use
    269  // cases where you should need to copy an RTCErrorOr, as opposed to moving
    270  // it. Can revisit this decision if use cases arise in the future.
    271  RTCErrorOr(const RTCErrorOr& other) = delete;
    272  RTCErrorOr& operator=(const RTCErrorOr& other) = delete;
    273 
    274  // Move constructor and move-assignment operator.
    275  //
    276  // Visual Studio doesn't support "= default" with move constructors or
    277  // assignment operators (even though they compile, they segfault), so define
    278  // them explicitly.
    279  RTCErrorOr(RTCErrorOr&& other)
    280      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
    281  RTCErrorOr& operator=(RTCErrorOr&& other) {
    282    error_ = std::move(other.error_);
    283    value_ = std::move(other.value_);
    284    return *this;
    285  }
    286 
    287  // Conversion constructor and assignment operator; T must be copy or move
    288  // constructible from U.
    289  template <typename U>
    290  RTCErrorOr(RTCErrorOr<U> other)  // NOLINT
    291      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
    292  template <typename U>
    293  RTCErrorOr& operator=(RTCErrorOr<U> other) {
    294    error_ = std::move(other.error_);
    295    value_ = std::move(other.value_);
    296    return *this;
    297  }
    298 
    299  // Returns a reference to our error. If this contains a T, then returns
    300  // default-constructed RTCError.
    301  const RTCError& error() const { return error_; }
    302 
    303  // Moves the error. Can be useful if, say "CreateFoo" returns an
    304  // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an
    305  // RTCErrorOr<Bar>, and wants to forward the error up the stack.
    306  RTCError MoveError() { return std::move(error_); }
    307 
    308  // Returns this->error().ok()
    309  bool ok() const { return error_.ok(); }
    310 
    311  // Returns a reference to our current value, or DCHECK-fails if !this->ok().
    312  //
    313  // Can be convenient for the implementation; for example, a method may want
    314  // to access the value in some way before returning it to the next method on
    315  // the stack.
    316  const T& value() const {
    317    RTC_DCHECK(ok());
    318    return *value_;
    319  }
    320  T& value() {
    321    RTC_DCHECK(ok());
    322    return *value_;
    323  }
    324 
    325  // Moves our current value out of this object and returns it, or DCHECK-fails
    326  // if !this->ok().
    327  T MoveValue() {
    328    RTC_DCHECK(ok());
    329    return std::move(*value_);
    330  }
    331 
    332  template <typename Sink>
    333  friend void AbslStringify(Sink& sink, const RTCErrorOr<T>& error_or) {
    334    if (error_or.ok()) {
    335      sink.Append("OK");
    336      if constexpr (std::is_convertible_v<T, absl::AlphaNum>) {
    337        sink.Append(" with value: ");
    338        sink.Append(absl::StrCat(error_or.value()));
    339      }
    340    } else {
    341      sink.Append(absl::StrCat(error_or.error()));
    342    }
    343  }
    344 
    345 private:
    346  RTCError error_;
    347  std::optional<T> value_;
    348 };
    349 
    350 }  // namespace webrtc
    351 
    352 #endif  // API_RTC_ERROR_H_