Introduce BYPASS_PROXY_CONSTMETHOD0.

This allows const getters that query const state to be called without
marshalling calls between threads. This must not be used to
return pointers/references etc.

I'm starting by using this macro with the data channel which has a
few of these getters, as well as changing things a bit to make more
parts of the implementation, const.

Change-Id: I6ec7a3774cd8f7be2ef122fb7c7fc5919afee600
Bug: webrtc:11547
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176846
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31489}
diff --git a/api/proxy.h b/api/proxy.h
index 385992e..b1ebe31 100644
--- a/api/proxy.h
+++ b/api/proxy.h
@@ -55,6 +55,7 @@
 #include <memory>
 #include <string>
 #include <tuple>
+#include <type_traits>
 #include <utility>
 
 #include "api/scoped_refptr.h"
@@ -396,6 +397,16 @@
     return call.Marshal(RTC_FROM_HERE, worker_thread_);                   \
   }
 
+// For use when returning purely const state (set during construction).
+// Use with caution. This method should only be used when the return value will
+// always be the same.
+#define BYPASS_PROXY_CONSTMETHOD0(r, method)                            \
+  r method() const override {                                           \
+    static_assert(!std::is_pointer<r>::value, "Type is a pointer");     \
+    static_assert(!std::is_reference<r>::value, "Type is a reference"); \
+    return c_->method();                                                \
+  }
+
 }  // namespace webrtc
 
 #endif  //  API_PROXY_H_
diff --git a/pc/data_channel.cc b/pc/data_channel.cc
index 0b9af37..795bf8d 100644
--- a/pc/data_channel.cc
+++ b/pc/data_channel.cc
@@ -139,9 +139,9 @@
     const std::string& label,
     const InternalDataChannelInit& config) {
   rtc::scoped_refptr<DataChannel> channel(
-      new rtc::RefCountedObject<DataChannel>(provider, dct, label));
-  if (!channel->Init(config)) {
-    return NULL;
+      new rtc::RefCountedObject<DataChannel>(config, provider, dct, label));
+  if (!channel->Init()) {
+    return nullptr;
   }
   return channel;
 }
@@ -152,11 +152,13 @@
          type == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP;
 }
 
-DataChannel::DataChannel(DataChannelProviderInterface* provider,
+DataChannel::DataChannel(const InternalDataChannelInit& config,
+                         DataChannelProviderInterface* provider,
                          cricket::DataChannelType dct,
                          const std::string& label)
     : internal_id_(GenerateUniqueId()),
       label_(label),
+      config_(config),
       observer_(nullptr),
       state_(kConnecting),
       messages_sent_(0),
@@ -174,29 +176,28 @@
       send_ssrc_(0),
       receive_ssrc_(0) {}
 
-bool DataChannel::Init(const InternalDataChannelInit& config) {
+bool DataChannel::Init() {
   if (data_channel_type_ == cricket::DCT_RTP) {
-    if (config.reliable || config.id != -1 || config.maxRetransmits ||
-        config.maxRetransmitTime) {
+    if (config_.reliable || config_.id != -1 || config_.maxRetransmits ||
+        config_.maxRetransmitTime) {
       RTC_LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to "
                            "invalid DataChannelInit.";
       return false;
     }
     handshake_state_ = kHandshakeReady;
   } else if (IsSctpLike(data_channel_type_)) {
-    if (config.id < -1 ||
-        (config.maxRetransmits && *config.maxRetransmits < 0) ||
-        (config.maxRetransmitTime && *config.maxRetransmitTime < 0)) {
+    if (config_.id < -1 ||
+        (config_.maxRetransmits && *config_.maxRetransmits < 0) ||
+        (config_.maxRetransmitTime && *config_.maxRetransmitTime < 0)) {
       RTC_LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
                            "invalid DataChannelInit.";
       return false;
     }
-    if (config.maxRetransmits && config.maxRetransmitTime) {
+    if (config_.maxRetransmits && config_.maxRetransmitTime) {
       RTC_LOG(LS_ERROR)
           << "maxRetransmits and maxRetransmitTime should not be both set.";
       return false;
     }
-    config_ = config;
 
     switch (config_.open_handshake_role) {
       case webrtc::InternalDataChannelInit::kNone:  // pre-negotiated
@@ -323,7 +324,7 @@
     return;
   }
 
-  config_.id = sid;
+  const_cast<InternalDataChannelInit&>(config_).id = sid;
   provider_->AddSctpDataStream(sid);
 }
 
diff --git a/pc/data_channel.h b/pc/data_channel.h
index 9a0a0aa..1ee2679 100644
--- a/pc/data_channel.h
+++ b/pc/data_channel.h
@@ -54,6 +54,8 @@
   virtual ~DataChannelProviderInterface() {}
 };
 
+// TODO(tommi): Change to not inherit from DataChannelInit but to have it as
+// a const member. Block access to the 'id' member since it cannot be const.
 struct InternalDataChannelInit : public DataChannelInit {
   enum OpenHandshakeRole { kOpener, kAcker, kNone };
   // The default role is kOpener because the default |negotiated| is false.
@@ -229,7 +231,8 @@
   static void ResetInternalIdAllocatorForTesting(int new_value);
 
  protected:
-  DataChannel(DataChannelProviderInterface* client,
+  DataChannel(const InternalDataChannelInit& config,
+              DataChannelProviderInterface* client,
               cricket::DataChannelType dct,
               const std::string& label);
   virtual ~DataChannel();
@@ -266,7 +269,7 @@
     kHandshakeReady
   };
 
-  bool Init(const InternalDataChannelInit& config);
+  bool Init();
   void UpdateState();
   void SetState(DataState state);
   void DisconnectFromProvider();
@@ -282,8 +285,8 @@
   bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
 
   const int internal_id_;
-  std::string label_;
-  InternalDataChannelInit config_;
+  const std::string label_;
+  const InternalDataChannelInit config_;
   DataChannelObserver* observer_;
   DataState state_;
   RTCError error_;
@@ -294,7 +297,7 @@
   // Number of bytes of data that have been queued using Send(). Increased
   // before each transport send and decreased after each successful send.
   uint64_t buffered_amount_;
-  cricket::DataChannelType data_channel_type_;
+  const cricket::DataChannelType data_channel_type_;
   DataChannelProviderInterface* provider_;
   HandshakeState handshake_state_;
   bool connected_to_provider_;
@@ -318,17 +321,18 @@
 PROXY_SIGNALING_THREAD_DESTRUCTOR()
 PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
 PROXY_METHOD0(void, UnregisterObserver)
-PROXY_CONSTMETHOD0(std::string, label)
-PROXY_CONSTMETHOD0(bool, reliable)
-PROXY_CONSTMETHOD0(bool, ordered)
-PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
-PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
-PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt)
-PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime)
-PROXY_CONSTMETHOD0(std::string, protocol)
-PROXY_CONSTMETHOD0(bool, negotiated)
+BYPASS_PROXY_CONSTMETHOD0(std::string, label)
+BYPASS_PROXY_CONSTMETHOD0(bool, reliable)
+BYPASS_PROXY_CONSTMETHOD0(bool, ordered)
+BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
+BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
+BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt)
+BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime)
+BYPASS_PROXY_CONSTMETHOD0(std::string, protocol)
+BYPASS_PROXY_CONSTMETHOD0(bool, negotiated)
+// Can't bypass the proxy since the id may change.
 PROXY_CONSTMETHOD0(int, id)
-PROXY_CONSTMETHOD0(Priority, priority)
+BYPASS_PROXY_CONSTMETHOD0(Priority, priority)
 PROXY_CONSTMETHOD0(DataState, state)
 PROXY_CONSTMETHOD0(RTCError, error)
 PROXY_CONSTMETHOD0(uint32_t, messages_sent)
diff --git a/pc/test/mock_data_channel.h b/pc/test/mock_data_channel.h
index 9ca018a..63f0e6c 100644
--- a/pc/test/mock_data_channel.h
+++ b/pc/test/mock_data_channel.h
@@ -22,15 +22,20 @@
  public:
   MockDataChannel(int id, DataState state)
       : MockDataChannel(id, "MockDataChannel", state, "udp", 0, 0, 0, 0) {}
-  MockDataChannel(int id,
-                  const std::string& label,
-                  DataState state,
-                  const std::string& protocol,
-                  uint32_t messages_sent,
-                  uint64_t bytes_sent,
-                  uint32_t messages_received,
-                  uint64_t bytes_received)
-      : rtc::RefCountedObject<DataChannel>(nullptr, cricket::DCT_NONE, label) {
+  MockDataChannel(
+      int id,
+      const std::string& label,
+      DataState state,
+      const std::string& protocol,
+      uint32_t messages_sent,
+      uint64_t bytes_sent,
+      uint32_t messages_received,
+      uint64_t bytes_received,
+      const InternalDataChannelInit& config = InternalDataChannelInit())
+      : rtc::RefCountedObject<DataChannel>(config,
+                                           nullptr,
+                                           cricket::DCT_NONE,
+                                           label) {
     EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id));
     EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state));
     EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol));