#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_crypto_stream.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/epoll_server/epoll_server.h"
explicit TestDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), eps) {
+ : QuicDispatcher(config,
+ crypto_config,
+ QuicSupportedVersions(),
+ eps,
+ kInitialFlowControlWindowForTest) {
}
MOCK_METHOD3(CreateQuicSession, QuicSession*(
const IPEndPoint& server_address,
const IPEndPoint& client_address));
using QuicDispatcher::write_blocked_list;
+
+ using QuicDispatcher::current_server_address;
+ using QuicDispatcher::current_client_address;
};
// A Connection class which unregisters the session from the dispatcher
QuicSession* CreateSession(QuicDispatcher* dispatcher,
QuicConnectionId connection_id,
- const IPEndPoint& addr,
+ const IPEndPoint& client_address,
MockSession** session) {
MockServerConnection* connection =
new MockServerConnection(connection_id, dispatcher);
WithoutArgs(Invoke(
connection, &MockServerConnection::UnregisterOnConnectionClosed)));
EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
- ProcessUdpPacket(_, addr, _));
+ ProcessUdpPacket(_, client_address, _));
return *session;
}
return reinterpret_cast<MockConnection*>(session2_->connection());
}
- void ProcessPacket(IPEndPoint addr,
+ void ProcessPacket(IPEndPoint client_address,
QuicConnectionId connection_id,
bool has_version_flag,
const string& data) {
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
connection_id, has_version_flag, false, 1, data));
data_ = string(packet->data(), packet->length());
- dispatcher_.ProcessPacket(IPEndPoint(), addr, *packet.get());
+ dispatcher_.ProcessPacket(server_address_, client_address, *packet.get());
}
void ValidatePacket(const QuicEncryptedPacket& packet) {
EpollServer eps_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
+ IPEndPoint server_address_;
TestDispatcher dispatcher_;
MockSession* session1_;
MockSession* session2_;
};
TEST_F(QuicDispatcherTest, ProcessPackets) {
- IPEndPoint addr(net::test::Loopback4(), 1);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
+ IPAddressNumber any4;
+ CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
+ server_address_ = IPEndPoint(any4, 5);
- EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_)));
- ProcessPacket(addr, 1, true, "foo");
+ &dispatcher_, 1, client_address, &session1_)));
+ ProcessPacket(client_address, 1, true, "foo");
+ EXPECT_EQ(client_address, dispatcher_.current_client_address());
+ EXPECT_EQ(server_address_, dispatcher_.current_server_address());
+
- EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 2, addr, &session2_)));
- ProcessPacket(addr, 2, true, "bar");
+ &dispatcher_, 2, client_address, &session2_)));
+ ProcessPacket(client_address, 2, true, "bar");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _)).Times(1).
WillOnce(testing::WithArgs<2>(Invoke(
this, &QuicDispatcherTest::ValidatePacket)));
- ProcessPacket(addr, 1, false, "eep");
+ ProcessPacket(client_address, 1, false, "eep");
}
TEST_F(QuicDispatcherTest, Shutdown) {
- IPEndPoint addr(net::test::Loopback4(), 1);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_)));
+ &dispatcher_, 1, client_address, &session1_)));
- ProcessPacket(addr, 1, true, "foo");
+ ProcessPacket(client_address, 1, true, "foo");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
SendConnectionClose(QUIC_PEER_GOING_AWAY));
: QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
}
- MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
+ MOCK_METHOD5(ProcessPacket, void(const IPEndPoint& server_address,
const IPEndPoint& client_address,
QuicConnectionId connection_id,
- QuicPacketSequenceNumber sequence_number));
+ QuicPacketSequenceNumber sequence_number,
+ const QuicEncryptedPacket& packet));
};
TEST_F(QuicDispatcherTest, TimeWaitListManager) {
QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
time_wait_list_manager);
// Create a new session.
- IPEndPoint addr(net::test::Loopback4(), 1);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
- EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, connection_id, addr, &session1_)));
- ProcessPacket(addr, connection_id, true, "foo");
+ &dispatcher_, connection_id, client_address, &session1_)));
+ ProcessPacket(client_address, connection_id, true, "foo");
// Close the connection by sending public reset packet.
QuicPublicResetPacket packet;
.WillOnce(Invoke(
reinterpret_cast<MockConnection*>(session1_->connection()),
&MockConnection::ReallyProcessUdpPacket));
- dispatcher_.ProcessPacket(IPEndPoint(), addr, *encrypted);
+ dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
EXPECT_TRUE(time_wait_list_manager->IsConnectionIdInTimeWait(connection_id));
// Dispatcher forwards subsequent packets for this connection_id to the time
// wait list manager.
EXPECT_CALL(*time_wait_list_manager,
- ProcessPacket(_, _, connection_id, _)).Times(1);
- ProcessPacket(addr, connection_id, true, "foo");
+ ProcessPacket(_, _, connection_id, _, _)).Times(1);
+ ProcessPacket(client_address, connection_id, true, "foo");
}
TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
time_wait_list_manager);
- IPEndPoint addr(net::test::Loopback4(), 1);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
// Dispatcher forwards all packets for this connection_id to the time wait
// list manager.
EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager,
- ProcessPacket(_, _, connection_id, _)).Times(1);
+ ProcessPacket(_, _, connection_id, _, _)).Times(1);
string data = "foo";
- ProcessPacket(addr, connection_id, false, "foo");
+ ProcessPacket(client_address, connection_id, false, "foo");
+}
+
+TEST(QuicDispatcherFlowControlTest, NoNewVersion17ConnectionsIfFlagDisabled) {
+ // If FLAGS_enable_quic_stream_flow_control_2 is disabled
+ // then the dispatcher should stop creating connections that support
+ // QUIC_VERSION_17 (existing connections will stay alive).
+ // TODO(rjshade): Remove once
+ // FLAGS_enable_quic_stream_flow_control_2 is removed.
+
+ EpollServer eps;
+ QuicConfig config;
+ QuicCryptoServerConfig server_config(QuicCryptoServerConfig::TESTING,
+ QuicRandom::GetInstance());
+ IPEndPoint client(net::test::Loopback4(), 1);
+ IPEndPoint server(net::test::Loopback4(), 1);
+ QuicConnectionId kCID = 1234;
+
+ QuicVersion kTestQuicVersions[] = {QUIC_VERSION_17,
+ QUIC_VERSION_16,
+ QUIC_VERSION_15};
+ QuicVersionVector kTestVersions;
+ for (size_t i = 0; i < arraysize(kTestQuicVersions); ++i) {
+ kTestVersions.push_back(kTestQuicVersions[i]);
+ }
+
+ QuicDispatcher dispatcher(config, server_config, kTestVersions, &eps,
+ kInitialFlowControlWindowForTest);
+ dispatcher.Initialize(0);
+
+ // When flag is enabled, new connections should support QUIC_VERSION_17.
+ FLAGS_enable_quic_stream_flow_control_2 = true;
+ scoped_ptr<QuicConnection> connection_1(
+ QuicDispatcherPeer::CreateQuicConnection(
+ &dispatcher, kCID, client, server, kInitialFlowControlWindowForTest));
+ EXPECT_EQ(QUIC_VERSION_17, connection_1->version());
+
+
+ // When flag is disabled, new connections should not support QUIC_VERSION_17.
+ FLAGS_enable_quic_stream_flow_control_2 = false;
+ scoped_ptr<QuicConnection> connection_2(
+ QuicDispatcherPeer::CreateQuicConnection(
+ &dispatcher, kCID, client, server, kInitialFlowControlWindowForTest));
+ EXPECT_EQ(QUIC_VERSION_16, connection_2->version());
}
class BlockingWriter : public QuicPacketWriterWrapper {
virtual WriteResult WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) OVERRIDE {
+ const IPAddressNumber& self_client_address,
+ const IPEndPoint& peer_client_address) OVERRIDE {
if (write_blocked_) {
return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
} else {
return QuicPacketWriterWrapper::WritePacket(
- buffer, buf_len, self_address, peer_address);
+ buffer, buf_len, self_client_address, peer_client_address);
}
}
writer_ = new BlockingWriter;
QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
- IPEndPoint addr(net::test::Loopback4(), 1);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_)));
- ProcessPacket(addr, 1, true, "foo");
+ &dispatcher_, 1, client_address, &session1_)));
+ ProcessPacket(client_address, 1, true, "foo");
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 2, addr, &session2_)));
- ProcessPacket(addr, 2, true, "bar");
+ &dispatcher_, 2, client_address, &session2_)));
+ ProcessPacket(client_address, 2, true, "bar");
blocked_list_ = dispatcher_.write_blocked_list();
}