TcpPort Reconnect should inform upper layer to start sending again.
During the reconnection phase, EWOULDBLOCK has been returned to upper layer which stops the sending of video stream.
BUG=webrtc:4930
R=pthatcher@webrtc.org
Review URL: https://codereview.webrtc.org/1288553010 .
Cr-Commit-Position: refs/heads/master@{#9767}
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index 2c122da..b0ba89f 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -226,6 +226,9 @@
conn_->SignalStateChange.connect(
this, &TestChannel::OnConnectionStateChange);
conn_->SignalDestroyed.connect(this, &TestChannel::OnDestroyed);
+ conn_->SignalReadyToSend.connect(this,
+ &TestChannel::OnConnectionReadyToSend);
+ connection_ready_to_send_ = false;
}
void OnConnectionStateChange(Connection* conn) {
if (conn->write_state() == Connection::STATE_WRITABLE) {
@@ -307,7 +310,20 @@
bool nominated() const { return nominated_; }
+ void set_connection_ready_to_send(bool ready) {
+ connection_ready_to_send_ = ready;
+ }
+ bool connection_ready_to_send() const {
+ return connection_ready_to_send_;
+ }
+
private:
+ // ReadyToSend will only issue after a Connection recovers from EWOULDBLOCK.
+ void OnConnectionReadyToSend(Connection* conn) {
+ ASSERT_EQ(conn, conn_);
+ connection_ready_to_send_ = true;
+ }
+
IceMode ice_mode_;
rtc::scoped_ptr<Port> src_;
Port* dst_;
@@ -318,6 +334,7 @@
rtc::scoped_ptr<StunMessage> remote_request_;
std::string remote_frag_;
bool nominated_;
+ bool connection_ready_to_send_ = false;
};
class PortTest : public testing::Test, public sigslot::has_slots<> {
@@ -618,6 +635,9 @@
static_cast<TCPConnection*>(ch2.conn())
->set_reconnection_timeout(kTcpReconnectTimeout);
+ EXPECT_FALSE(ch1.connection_ready_to_send());
+ EXPECT_FALSE(ch2.connection_ready_to_send());
+
// Once connected, disconnect them.
DisconnectTcpTestChannels(&ch1, &ch2);
@@ -638,11 +658,19 @@
// Verify that we could still connect channels.
ConnectStartedChannels(&ch1, &ch2);
+ EXPECT_TRUE_WAIT(ch1.connection_ready_to_send(),
+ kTcpReconnectTimeout);
+ // Channel2 is the passive one so a new connection is created during
+ // reconnect. This new connection should never have issued EWOULDBLOCK
+ // hence the connection_ready_to_send() should be false.
+ EXPECT_FALSE(ch2.connection_ready_to_send());
} else {
EXPECT_EQ(ch1.conn()->write_state(), Connection::STATE_WRITABLE);
EXPECT_TRUE_WAIT(
ch1.conn()->write_state() == Connection::STATE_WRITE_TIMEOUT,
kTcpReconnectTimeout + kTimeout);
+ EXPECT_FALSE(ch1.connection_ready_to_send());
+ EXPECT_FALSE(ch2.connection_ready_to_send());
}
// Tear down and ensure that goes smoothly.
diff --git a/webrtc/p2p/base/tcpport.cc b/webrtc/p2p/base/tcpport.cc
index 6dc66d2..7dc416f 100644
--- a/webrtc/p2p/base/tcpport.cc
+++ b/webrtc/p2p/base/tcpport.cc
@@ -354,10 +354,16 @@
void TCPConnection::OnConnectionRequestResponse(ConnectionRequest* req,
StunMessage* response) {
- // Once we receive a binding response, we are really writable, and not just
- // pretending to be writable.
- pretending_to_be_writable_ = false;
+ // Process the STUN response before we inform upper layer ready to send.
Connection::OnConnectionRequestResponse(req, response);
+
+ // If we're in the state of pretending to be writeable, we should inform the
+ // upper layer it's ready to send again as previous EWOULDLBLOCK from socket
+ // would have stopped the outgoing stream.
+ if (pretending_to_be_writable_) {
+ Connection::OnReadyToSend();
+ }
+ pretending_to_be_writable_ = false;
ASSERT(write_state() == STATE_WRITABLE);
}