gfe-relnote: Update QuicConnection's SendMessage to allow specifying if the message
being sent is retransmittable.

PiperOrigin-RevId: 281363715
Change-Id: I81966b19cda8405adb6e6f5d7804c3f042fa4ba8
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index d077196..479cfaf 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -3864,7 +3864,8 @@
 }
 
 MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
-                                          QuicMemSliceSpan message) {
+                                          QuicMemSliceSpan message,
+                                          bool flush) {
   if (!VersionSupportsMessageFrames(transport_version())) {
     QUIC_BUG << "MESSAGE frame is not supported for version "
              << transport_version();
@@ -3873,7 +3874,7 @@
   if (message.total_length() > GetCurrentLargestMessagePayload()) {
     return MESSAGE_STATUS_TOO_LARGE;
   }
-  if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
+  if (!connected_ || (!flush && !CanWrite(HAS_RETRANSMITTABLE_DATA))) {
     return MESSAGE_STATUS_BLOCKED;
   }
   ScopedPacketFlusher flusher(this);
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 90369fc..de26b3c 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -758,8 +758,11 @@
   void SetTransmissionType(TransmissionType type);
 
   // Tries to send |message| and returns the message status.
+  // If |flush| is false, this will return a MESSAGE_STATUS_BLOCKED
+  // when the connection is deemed unwritable.
   virtual MessageStatus SendMessage(QuicMessageId message_id,
-                                    QuicMemSliceSpan message);
+                                    QuicMemSliceSpan message,
+                                    bool flush);
 
   // Returns the largest payload that will fit into a single MESSAGE frame.
   // Because overhead can vary during a connection, this method should be
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 9c2a1c8..f5f1287 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -8737,33 +8737,36 @@
     // get sent, one contains stream frame, and the other only contains the
     // message frame.
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
-    EXPECT_EQ(
-        MESSAGE_STATUS_SUCCESS,
-        connection_.SendMessage(
-            1, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
-                        QuicStringPiece(
-                            message_data.data(),
-                            connection_.GetCurrentLargestMessagePayload()),
-                        &storage)));
+    EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
+              connection_.SendMessage(
+                  1,
+                  MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+                           QuicStringPiece(
+                               message_data.data(),
+                               connection_.GetCurrentLargestMessagePayload()),
+                           &storage),
+                  false));
   }
   // Fail to send a message if connection is congestion control blocked.
   EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
-  EXPECT_EQ(
-      MESSAGE_STATUS_BLOCKED,
-      connection_.SendMessage(
-          2, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
-                      "message", &storage)));
+  EXPECT_EQ(MESSAGE_STATUS_BLOCKED,
+            connection_.SendMessage(
+                2,
+                MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+                         "message", &storage),
+                false));
 
   // Always fail to send a message which cannot fit into one packet.
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
-  EXPECT_EQ(
-      MESSAGE_STATUS_TOO_LARGE,
-      connection_.SendMessage(
-          3, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
-                      QuicStringPiece(
-                          message_data.data(),
-                          connection_.GetCurrentLargestMessagePayload() + 1),
-                      &storage)));
+  EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
+            connection_.SendMessage(
+                3,
+                MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+                         QuicStringPiece(
+                             message_data.data(),
+                             connection_.GetCurrentLargestMessagePayload() + 1),
+                         &storage),
+                false));
 }
 
 // Test to check that the path challenge/path response logic works
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 3ec2401..1c85430 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1894,11 +1894,15 @@
 }
 
 MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
+  return SendMessage(message, /*flush=*/false);
+}
+
+MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
   if (!IsEncryptionEstablished()) {
     return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
   }
   MessageStatus result =
-      connection_->SendMessage(last_message_id_ + 1, message);
+      connection_->SendMessage(last_message_id_ + 1, message, flush);
   if (result == MESSAGE_STATUS_SUCCESS) {
     return {result, ++last_message_id_};
   }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 03090d8..2d0f252 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -199,6 +199,10 @@
   // callback.
   MessageResult SendMessage(QuicMemSliceSpan message);
 
+  // Same as above SendMessage, except caller can specify if the given |message|
+  // should be flushed even if the underlying connection is deemed unwritable.
+  MessageResult SendMessage(QuicMemSliceSpan message, bool flush);
+
   // Called when message with |message_id| gets acked.
   virtual void OnMessageAcked(QuicMessageId message_id,
                               QuicTime receive_timestamp);
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 4ee1230..16a9917 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -2343,21 +2343,21 @@
   EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
 
   QuicStringPiece message;
-  EXPECT_CALL(*connection_, SendMessage(1, _))
+  EXPECT_CALL(*connection_, SendMessage(1, _, false))
       .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
   EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
             session_.SendMessage(
                 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
                          message, &storage)));
   // Verify message_id increases.
-  EXPECT_CALL(*connection_, SendMessage(2, _))
+  EXPECT_CALL(*connection_, SendMessage(2, _, false))
       .WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
   EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
             session_.SendMessage(
                 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
                          message, &storage)));
   // Verify unsent message does not consume a message_id.
-  EXPECT_CALL(*connection_, SendMessage(2, _))
+  EXPECT_CALL(*connection_, SendMessage(2, _, false))
       .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
   EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
             session_.SendMessage(
diff --git a/quic/qbone/qbone_session_base.cc b/quic/qbone/qbone_session_base.cc
index 9c8479c..c3e7731 100644
--- a/quic/qbone/qbone_session_base.cc
+++ b/quic/qbone/qbone_session_base.cc
@@ -141,7 +141,7 @@
     QuicMemSlice slice(connection()->helper()->GetStreamSendBufferAllocator(),
                        packet.size());
     memcpy(const_cast<char*>(slice.data()), packet.data(), packet.size());
-    switch (SendMessage(QuicMemSliceSpan(&slice)).status) {
+    switch (SendMessage(QuicMemSliceSpan(&slice), /*flush=*/true).status) {
       case MESSAGE_STATUS_SUCCESS:
         break;
       case MESSAGE_STATUS_TOO_LARGE: {
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index f428e87..544d1fb 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -534,7 +534,8 @@
 
   MOCK_METHOD2(OnStreamReset, void(QuicStreamId, QuicRstStreamErrorCode));
   MOCK_METHOD1(SendControlFrame, bool(const QuicFrame& frame));
-  MOCK_METHOD2(SendMessage, MessageStatus(QuicMessageId, QuicMemSliceSpan));
+  MOCK_METHOD3(SendMessage,
+               MessageStatus(QuicMessageId, QuicMemSliceSpan, bool));
   MOCK_METHOD3(OnConnectionClosed,
                void(QuicErrorCode error,
                     const std::string& error_details,