summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/net.gyp9
-rw-r--r--net/quic/quic_client_session.cc50
-rw-r--r--net/quic/quic_client_session.h42
-rw-r--r--net/quic/quic_client_session_test.cc70
-rw-r--r--net/quic/quic_crypto_client_stream.cc34
-rw-r--r--net/quic/quic_crypto_client_stream.h29
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc67
-rw-r--r--net/quic/quic_reliable_client_stream.cc39
-rw-r--r--net/quic/quic_reliable_client_stream.h75
-rw-r--r--net/quic/quic_reliable_client_stream_test.cc70
10 files changed, 485 insertions, 0 deletions
diff --git a/net/net.gyp b/net/net.gyp
index d2cbb7307..98bc7ad 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -655,6 +655,10 @@
'quic/crypto/quic_decrypter.cc',
'quic/crypto/quic_encrypter.h',
'quic/crypto/quic_encrypter.cc',
+ 'quic/quic_client_session.cc',
+ 'quic/quic_client_session.h',
+ 'quic/quic_crypto_client_stream.cc',
+ 'quic/quic_crypto_client_stream.h',
'quic/quic_crypto_stream.cc',
'quic/quic_crypto_stream.h',
'quic/quic_clock.cc',
@@ -673,6 +677,8 @@
'quic/quic_packet_creator.h',
'quic/quic_protocol.cc',
'quic/quic_protocol.h',
+ 'quic/quic_reliable_client_stream.cc',
+ 'quic/quic_reliable_client_stream.h',
'quic/quic_session.cc',
'quic/quic_session.h',
'quic/quic_stream_sequencer.cc',
@@ -1415,11 +1421,14 @@
'quic/test_tools/mock_clock.h',
'quic/test_tools/quic_test_utils.cc',
'quic/test_tools/quic_test_utils.h',
+ 'quic/quic_client_session_test.cc',
'quic/quic_connection_test.cc',
+ 'quic/quic_crypto_client_stream_test.cc',
'quic/quic_crypto_stream_test.cc',
'quic/quic_fec_group_test.cc',
'quic/quic_framer_test.cc',
'quic/quic_packet_creator_test.cc',
+ 'quic/quic_reliable_client_stream_test.cc',
'quic/quic_session_test.cc',
'quic/quic_stream_sequencer_test.cc',
'socket/buffered_write_stream_socket_unittest.cc',
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
new file mode 100644
index 0000000..cf101c6
--- /dev/null
+++ b/net/quic/quic_client_session.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_client_session.h"
+
+namespace net {
+
+QuicClientSession::QuicClientSession(QuicConnection* connection)
+ : QuicSession(connection, false),
+ crypto_stream_(this) {
+}
+
+QuicClientSession::~QuicClientSession() {
+}
+
+QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() {
+ if (!crypto_stream_.handshake_complete()) {
+ DLOG(INFO) << "Crypto handshake not complete, no outgoing stream created.";
+ return NULL;
+ }
+ if (GetNumOpenStreams() >= get_max_open_streams()) {
+ DLOG(INFO) << "Failed to create a new outgoing stream. "
+ << "Already " << GetNumOpenStreams() << " open.";
+ return NULL;
+ }
+ QuicReliableClientStream* stream =
+ new QuicReliableClientStream(GetNextStreamId(), this);
+
+ ActivateStream(stream);
+ return stream;
+}
+
+QuicCryptoClientStream* QuicClientSession::GetCryptoStream() {
+ return &crypto_stream_;
+};
+
+void QuicClientSession::CryptoConnect() {
+ CryptoHandshakeMessage message;
+ message.tag = kCHLO;
+ crypto_stream_.SendHandshakeMessage(message);
+}
+
+ReliableQuicStream* QuicClientSession::CreateIncomingReliableStream(
+ QuicStreamId id) {
+ DLOG(ERROR) << "Server push not supported";
+ return NULL;
+}
+
+} // namespace net
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
new file mode 100644
index 0000000..08e6c65
--- /dev/null
+++ b/net/quic/quic_client_session.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A client specific QuicSession subclass.
+
+#ifndef NET_QUIC_QUIC_CLIENT_SESSION_H_
+#define NET_QUIC_QUIC_CLIENT_SESSION_H_
+
+#include "net/quic/quic_crypto_client_stream.h"
+#include "net/quic/quic_reliable_client_stream.h"
+#include "net/quic/quic_session.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
+ public:
+ explicit QuicClientSession(QuicConnection* connection);
+
+ virtual ~QuicClientSession();
+
+ // QuicSession methods:
+ virtual QuicReliableClientStream* CreateOutgoingReliableStream() OVERRIDE;
+ virtual QuicCryptoClientStream* GetCryptoStream() OVERRIDE;
+
+ // Perform a crypto handshake with the server.
+ void CryptoConnect();
+
+ protected:
+ // QuicSession methods:
+ virtual ReliableQuicStream* CreateIncomingReliableStream(
+ QuicStreamId id) OVERRIDE;
+
+ private:
+ QuicCryptoClientStream crypto_stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicClientSession);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CLIENT_SESSION_H_
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
new file mode 100644
index 0000000..3f3ad04
--- /dev/null
+++ b/net/quic/quic_client_session_test.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_client_session.h"
+
+#include <vector>
+
+#include "base/stl_util.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using testing::_;
+
+namespace net {
+namespace test {
+namespace {
+
+class QuicClientSessionTest : public ::testing::Test {
+ protected:
+ QuicClientSessionTest()
+ : guid_(1),
+ connection_(new PacketSavingConnection(guid_, IPEndPoint())),
+ session_(connection_) {
+ }
+
+ protected:
+ QuicGuid guid_;
+ PacketSavingConnection* connection_;
+ QuicClientSession session_;
+ QuicConnectionVisitorInterface* visitor_;
+};
+
+TEST_F(QuicClientSessionTest, CryptoConnect) {
+ session_.CryptoConnect();
+ ASSERT_EQ(1u, connection_->packets_.size());
+ scoped_ptr<QuicPacket> chlo(ConstructHandshakePacket(guid_, kCHLO));
+ CompareQuicDataWithHexError("CHLO", connection_->packets_[0], chlo.get());
+}
+
+TEST_F(QuicClientSessionTest, MaxNumConnections) {
+ // Initialize crypto before the client session will create a stream.
+ session_.CryptoConnect();
+ ASSERT_EQ(1u, connection_->packets_.size());
+ scoped_ptr<QuicPacket> chlo(ConstructHandshakePacket(guid_, kCHLO));
+ CompareQuicDataWithHexError("CHLO", connection_->packets_[0], chlo.get());
+ // Simulate the server crypto handshake.
+ CryptoHandshakeMessage server_message;
+ server_message.tag = kSHLO;
+ session_.GetCryptoStream()->OnHandshakeMessage(server_message);
+
+ std::vector<QuicReliableClientStream*> streams;
+ for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
+ QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream();
+ streams.push_back(stream);
+ EXPECT_TRUE(stream);
+ }
+ EXPECT_FALSE(session_.CreateOutgoingReliableStream());
+
+ // Close a stream and ensure I can now open a new one.
+ session_.CloseStream(streams[0]->id());
+ scoped_ptr<QuicReliableClientStream> stream(
+ session_.CreateOutgoingReliableStream());
+ EXPECT_TRUE(stream.get());
+ STLDeleteElements(&streams);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
new file mode 100644
index 0000000..d0ace80
--- /dev/null
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_crypto_client_stream.h"
+
+#include "net/quic/quic_session.h"
+
+namespace net {
+
+QuicCryptoClientStream::QuicCryptoClientStream(QuicSession* session)
+ : QuicCryptoStream(session) {
+}
+
+
+void QuicCryptoClientStream::OnHandshakeMessage(
+ const CryptoHandshakeMessage& message) {
+ // Do not process handshake messages after the handshake is complete.
+ if (handshake_complete()) {
+ CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
+ return;
+ }
+
+ if (message.tag != kSHLO) {
+ CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
+ return;
+ }
+
+ // TODO(rch): correctly validate the message
+ set_handshake_complete(true);
+ return;
+}
+
+} // namespace net
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
new file mode 100644
index 0000000..8f94884
--- /dev/null
+++ b/net/quic/quic_crypto_client_stream.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
+#define NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
+
+#include "net/quic/quic_crypto_stream.h"
+
+namespace net {
+
+class QuicSession;
+
+class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
+
+ public:
+ explicit QuicCryptoClientStream(QuicSession* session);
+
+ // CryptoFramerVisitorInterface implementation
+ virtual void OnHandshakeMessage(
+ const CryptoHandshakeMessage& message) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
new file mode 100644
index 0000000..2dfa430
--- /dev/null
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_crypto_client_stream.h"
+
+#include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class QuicCryptoClientStreamTest : public ::testing::Test {
+ public:
+ QuicCryptoClientStreamTest()
+ : connection_(new MockConnection(1, addr_)),
+ session_(connection_, true),
+ stream_(&session_) {
+ message_.tag = kSHLO;
+ message_.tag_value_map[1] = "abc";
+ message_.tag_value_map[2] = "def";
+ ConstructHandshakeMessage();
+ }
+
+ void ConstructHandshakeMessage() {
+ CryptoFramer framer;
+ message_data_.reset(framer.ConstructHandshakeMessage(message_));
+ }
+
+ IPEndPoint addr_;
+ MockConnection* connection_;
+ MockSession session_;
+ QuicCryptoClientStream stream_;
+ CryptoHandshakeMessage message_;
+ scoped_ptr<QuicData> message_data_;
+};
+
+TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
+ EXPECT_FALSE(stream_.handshake_complete());
+}
+
+TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+ EXPECT_TRUE(stream_.handshake_complete());
+}
+
+TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+
+ EXPECT_CALL(*connection_, SendConnectionClose(
+ QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+}
+
+TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
+ message_.tag = kCHLO;
+ ConstructHandshakeMessage();
+
+ EXPECT_CALL(*connection_,
+ SendConnectionClose(QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc
new file mode 100644
index 0000000..09fb01e
--- /dev/null
+++ b/net/quic/quic_reliable_client_stream.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_reliable_client_stream.h"
+
+#include "net/base/net_errors.h"
+
+namespace net {
+
+QuicReliableClientStream::QuicReliableClientStream(QuicStreamId id,
+ QuicSession* session)
+ : ReliableQuicStream(id, session) {
+}
+
+QuicReliableClientStream::~QuicReliableClientStream() {
+}
+
+uint32 QuicReliableClientStream::ProcessData(const char* data,
+ uint32 data_len) {
+ int rv = delegate_->OnDataReceived(data, data_len);
+ if (rv != OK) {
+ DLOG(ERROR) << "Delegate refused data, rv: " << rv;
+ Close(QUIC_BAD_APPLICATION_PAYLOAD);
+ return 0;
+ }
+ return data_len;
+}
+
+void QuicReliableClientStream::TerminateFromPeer(bool half_close) {
+ delegate_->OnClose(error());
+}
+
+void QuicReliableClientStream::SetDelegate(
+ QuicReliableClientStream::Delegate* delegate) {
+ delegate_ = delegate;
+}
+
+} // namespace net
diff --git a/net/quic/quic_reliable_client_stream.h b/net/quic/quic_reliable_client_stream.h
new file mode 100644
index 0000000..7c5986d
--- /dev/null
+++ b/net/quic/quic_reliable_client_stream.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// NOTE: This code is not shared between Google and Chrome.
+
+#ifndef NET_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
+#define NET_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
+
+#include "net/base/upload_data_stream.h"
+#include "net/http/http_request_info.h"
+#include "net/http/http_response_info.h"
+#include "net/http/http_stream.h"
+#include "net/quic/reliable_quic_stream.h"
+
+namespace net {
+
+class QuicClientSession;
+
+class NET_EXPORT_PRIVATE QuicReliableClientStream : public ReliableQuicStream {
+ public:
+ // Delegate handles protocol specific behavior of a quic stream.
+ class Delegate {
+ public:
+ Delegate() {}
+
+ // Called when stream is ready to send data.
+ // Returns network error code. OK when it successfully sent data.
+ // ERR_IO_PENDING when performing operation asynchronously.
+ virtual int OnSendData() = 0;
+
+ // Called when data has been sent. |status| indicates network error
+ // or number of bytes that has been sent. On return, |eof| is set to true
+ // if no more data is available to send.
+ // Returns network error code. OK when it successfully sent data.
+ virtual int OnSendDataComplete(int status, bool* eof) = 0;
+
+ // Called when data is received.
+ // Returns network error code. OK when it successfully receives data.
+ virtual int OnDataReceived(const char* data, int length) = 0;
+
+ // Called when the stream is closed by the peer.
+ virtual void OnClose(QuicErrorCode error) = 0;
+
+ protected:
+ virtual ~Delegate() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ QuicReliableClientStream(QuicStreamId id,
+ QuicSession* session);
+
+ virtual ~QuicReliableClientStream();
+
+ // ReliableQuicStream
+ virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE;
+ virtual void TerminateFromPeer(bool half_close) OVERRIDE;
+
+ // Set new |delegate|. |delegate| must not be NULL.
+ // If this stream has already received data, OnDataReceived() will be
+ // called on the delegate.
+ void SetDelegate(Delegate* delegate);
+ Delegate* GetDelegate() { return delegate_; }
+
+ private:
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicReliableClientStream);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
diff --git a/net/quic/quic_reliable_client_stream_test.cc b/net/quic/quic_reliable_client_stream_test.cc
new file mode 100644
index 0000000..66c3bb7
--- /dev/null
+++ b/net/quic/quic_reliable_client_stream_test.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_reliable_client_stream.h"
+
+#include "net/base/net_errors.h"
+#include "net/quic/quic_client_session.h"
+#include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::Return;
+using testing::StrEq;
+
+namespace net {
+namespace test {
+namespace {
+
+class MockDelegate : public QuicReliableClientStream::Delegate {
+ public:
+ MockDelegate() {}
+
+ MOCK_METHOD0(OnSendData, int());
+ MOCK_METHOD2(OnSendDataComplete, int(int, bool*));
+ MOCK_METHOD2(OnDataReceived, int(const char*, int));
+ MOCK_METHOD1(OnClose, void(QuicErrorCode));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDelegate);
+};
+
+class QuicReliableClientStreamTest : public ::testing::Test {
+ public:
+ QuicReliableClientStreamTest()
+ : session_(new MockConnection(1, IPEndPoint()), false),
+ stream_(1, &session_) {
+ stream_.SetDelegate(&delegate_);
+ }
+
+ testing::StrictMock<MockDelegate> delegate_;
+ MockSession session_;
+ QuicReliableClientStream stream_;
+};
+
+TEST_F(QuicReliableClientStreamTest, TerminateFromPeer) {
+ EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
+
+ stream_.TerminateFromPeer(true);
+}
+
+TEST_F(QuicReliableClientStreamTest, ProcessData) {
+ const char data[] = "hello world!";
+ EXPECT_CALL(delegate_, OnDataReceived(StrEq(data), arraysize(data)));
+
+ EXPECT_EQ(arraysize(data), stream_.ProcessData(data, arraysize(data)));
+}
+
+TEST_F(QuicReliableClientStreamTest, ProcessDataWithError) {
+ const char data[] = "hello world!";
+ EXPECT_CALL(delegate_,
+ OnDataReceived(StrEq(data),
+ arraysize(data))).WillOnce(Return(ERR_UNEXPECTED));
+
+ EXPECT_EQ(0u, stream_.ProcessData(data, arraysize(data)));
+}
+
+} // namespace
+} // namespace test
+} // namespace net