summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authormbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-01 18:18:52 +0000
committermbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-01 18:18:52 +0000
commit18c53aea21c7d839f3c39f499a2faf2c613a3fa2 (patch)
tree55cd0308aa1943d9903263043bcbe0a6ec83156c /net
parentbead2db06a0acf9ff82a735e8afcaef7ee601b57 (diff)
downloadchromium_src-18c53aea21c7d839f3c39f499a2faf2c613a3fa2.zip
chromium_src-18c53aea21c7d839f3c39f499a2faf2c613a3fa2.tar.gz
chromium_src-18c53aea21c7d839f3c39f499a2faf2c613a3fa2.tar.bz2
Two features:
- Enable FLIP over SSL. - Rework the X-Associated-Content. The server can send us a list of subresources that it plans to push. The client will keep track of these in a pending list. If the client tries to request the resource before the server pushes it, the client will not issue the request, and will wait until the push stream arrives. Conversely, if the pushed stream arrives before the client makes a request for the resource, the stream is added to the pushed_streams list and waits for a FlipNetworkTransaction to arrive that wants it (this part of the logic was already in place). BUG=none TEST=none Review URL: http://codereview.chromium.org/249046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27746 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/flip/flip_network_transaction_unittest.cc3
-rw-r--r--net/flip/flip_session.cc112
-rw-r--r--net/flip/flip_session.h13
-rw-r--r--net/flip/flip_session_pool.cc2
4 files changed, 116 insertions, 14 deletions
diff --git a/net/flip/flip_network_transaction_unittest.cc b/net/flip/flip_network_transaction_unittest.cc
index 29db36c..0d2e97d 100644
--- a/net/flip/flip_network_transaction_unittest.cc
+++ b/net/flip/flip_network_transaction_unittest.cc
@@ -98,8 +98,7 @@ class FlipNetworkTransactionTest : public PlatformTest {
SessionDependencies session_deps;
scoped_ptr<FlipNetworkTransaction> trans(
- new FlipNetworkTransaction(
- CreateSession(&session_deps)));
+ new FlipNetworkTransaction(CreateSession(&session_deps)));
HttpRequestInfo request;
request.method = "GET";
diff --git a/net/flip/flip_session.cc b/net/flip/flip_session.cc
index 16cd491..1a8b1c6 100644
--- a/net/flip/flip_session.cc
+++ b/net/flip/flip_session.cc
@@ -17,8 +17,17 @@
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/ssl_client_socket.h"
#include "net/tools/dump_cache/url_to_filename_encoder.h"
+namespace {
+
+// True if FLIP should run over SSL.
+static bool use_ssl_flip = true;
+
+} // namespace
+
namespace net {
// static
@@ -77,7 +86,7 @@ class FlipStreamImpl {
};
FlipSession* FlipSession::GetFlipSession(
- const net::HostResolver::RequestInfo& info,
+ const HostResolver::RequestInfo& info,
HttpNetworkSession* session) {
if (!session_pool_.get())
session_pool_.reset(new FlipSessionPool());
@@ -86,7 +95,9 @@ FlipSession* FlipSession::GetFlipSession(
FlipSession::FlipSession(std::string host, HttpNetworkSession* session)
: ALLOW_THIS_IN_INITIALIZER_LIST(
- connect_callback_(this, &FlipSession::OnSocketConnect)),
+ connect_callback_(this, &FlipSession::OnTCPConnect)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ ssl_connect_callback_(this, &FlipSession::OnSSLConnect)),
ALLOW_THIS_IN_INITIALIZER_LIST(
read_callback_(this, &FlipSession::OnReadComplete)),
ALLOW_THIS_IN_INITIALIZER_LIST(
@@ -94,6 +105,7 @@ FlipSession::FlipSession(std::string host, HttpNetworkSession* session)
domain_(host),
session_(session),
connection_started_(false),
+ connection_ready_(false),
delayed_write_pending_(false),
write_pending_(false),
read_buffer_(new IOBuffer(kReadBufferSize)),
@@ -104,6 +116,8 @@ FlipSession::FlipSession(std::string host, HttpNetworkSession* session)
stream_hi_water_mark_ = 1;
flip_framer_.set_visitor(this);
+
+ session_->ssl_config_service()->GetSSLConfig(&ssl_config_);
}
FlipSession::~FlipSession() {
@@ -212,6 +226,16 @@ int FlipSession::CreateStream(FlipDelegate* delegate) {
}
}
+ // Check if we have a pending push stream for this url.
+ std::string url_path = delegate->request()->url.PathForRequest();
+ std::map<std::string, FlipDelegate*>::iterator it;
+ it = pending_streams_.find(url_path);
+ if (it != pending_streams_.end()) {
+ DCHECK(it->second == NULL);
+ it->second = delegate;
+ return 0; // TODO(mbelshe): this is overloaded with the fail case.
+ }
+
// If we still don't have a stream, activate one now.
stream = ActivateStream(stream_id, delegate);
if (!stream)
@@ -288,7 +312,7 @@ LoadState FlipSession::GetLoadState() const {
return LOAD_STATE_CONNECTING;
}
-void FlipSession::OnSocketConnect(int result) {
+void FlipSession::OnTCPConnect(int result) {
LOG(INFO) << "Flip socket connected (result=" << result << ")";
if (result != net::OK) {
@@ -307,6 +331,35 @@ void FlipSession::OnSocketConnect(int result) {
connection_.socket()->SetReceiveBufferSize(kSocketBufferSize);
connection_.socket()->SetSendBufferSize(kSocketBufferSize);
+ if (use_ssl_flip) {
+ // Add a SSL socket on top of our existing transport socket.
+ ClientSocket* socket = connection_.release_socket();
+ // TODO(mbelshe): Fix the hostname. This is BROKEN without having
+ // a real hostname.
+ socket = session_->socket_factory()->CreateSSLClientSocket(
+ socket, "" /* request_->url.HostNoBrackets() */ , ssl_config_);
+ connection_.set_socket(socket);
+ int status = connection_.socket()->Connect(&ssl_connect_callback_);
+ CHECK(status == net::ERR_IO_PENDING);
+ } else {
+ connection_ready_ = true;
+
+ // Make sure we get any pending data sent.
+ WriteSocketLater();
+ // Start reading
+ ReadSocket();
+ }
+}
+
+void FlipSession::OnSSLConnect(int result) {
+ // TODO(mbelshe): We need to replicate the functionality of
+ // HttpNetworkTransaction::DoSSLConnectComplete here, where it calls
+ // HandleCertificateError() and such.
+ if (IsCertificateError(result))
+ result = OK; // TODO(mbelshe): pretend we're happy anyway.
+
+ connection_ready_ = true;
+
// After we've connected, send any data to the server, and then issue
// our read.
WriteSocketLater();
@@ -391,7 +444,7 @@ void FlipSession::WriteSocketLater() {
delayed_write_pending_ = true;
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &net::FlipSession::WriteSocket));
+ this, &FlipSession::WriteSocket));
}
void FlipSession::WriteSocket() {
@@ -401,7 +454,7 @@ void FlipSession::WriteSocket() {
// If the socket isn't connected yet, just wait; we'll get called
// again when the socket connection completes.
- if (!connection_.is_initialized())
+ if (!connection_ready_)
return;
if (write_pending_) // Another write is in progress still.
@@ -465,6 +518,7 @@ void FlipSession::CloseAllStreams(net::Error code) {
// Issue the aborts.
for (--index; index >= 0; index--) {
+ LOG(ERROR) << "ABANDONED: " << list[index]->path();
list[index]->OnAbort();
delete list[index];
}
@@ -535,7 +589,7 @@ FlipStreamImpl* FlipSession::GetPushStream(std::string path) {
void FlipSession::OnError(flip::FlipFramer* framer) {
LOG(ERROR) << "FlipSession error!";
CloseAllStreams(net::ERR_UNEXPECTED);
- this->Release();
+ Release();
}
void FlipSession::OnStreamFrameData(flip::FlipStreamId stream_id,
@@ -562,18 +616,21 @@ void FlipSession::OnSyn(const flip::FlipSynStreamControlFrame* frame,
// Server-initiated streams should have odd sequence numbers.
if ((stream_id & 0x1) != 0) {
- LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id;
+ LOG(ERROR) << "Received invalid OnSyn stream id " << stream_id;
return;
}
if (IsStreamActive(stream_id)) {
- LOG(WARNING) << "Received OnSyn for active stream " << stream_id;
+ LOG(ERROR) << "Received OnSyn for active stream " << stream_id;
return;
}
+ // Activate a stream and parse the headers.
FlipStreamImpl* stream = ActivateStream(stream_id, NULL);
stream->OnReply(headers);
+ // TODO(mbelshe): DCHECK that this is a GET method?
+
// Verify that the response had a URL for us.
DCHECK(stream->path().length() != 0);
if (stream->path().length() == 0) {
@@ -582,7 +639,20 @@ void FlipSession::OnSyn(const flip::FlipSynStreamControlFrame* frame,
delete stream;
return;
}
- pushed_streams_.push_back(stream);
+
+ // Check if we already have a delegate awaiting this stream.
+ std::map<std::string, FlipDelegate*>::iterator it;
+ it = pending_streams_.find(stream->path());
+ if (it != pending_streams_.end()) {
+ FlipDelegate* delegate = it->second;
+ pending_streams_.erase(it);
+ if (delegate)
+ stream->AttachDelegate(delegate);
+ else
+ pushed_streams_.push_back(stream);
+ } else {
+ pushed_streams_.push_back(stream);
+ }
LOG(INFO) << "Got pushed stream for " << stream->path();
@@ -600,6 +670,30 @@ void FlipSession::OnSynReply(const flip::FlipSynReplyControlFrame* frame,
return;
}
+ // We record content declared as being pushed so that we don't
+ // request a duplicate stream which is already scheduled to be
+ // sent to us.
+ flip::FlipHeaderBlock::const_iterator it;
+ it = headers->find("X-Associated-Content");
+ if (it != headers->end()) {
+ const std::string& content = it->second;
+ std::string::size_type start = 0;
+ std::string::size_type end = 0;
+ do {
+ end = content.find("||", start);
+ if (end == -1)
+ end = content.length();
+ std::string url = content.substr(start, end - start);
+ std::string::size_type pos = url.find("??");
+ if (pos == -1)
+ break;
+ url = url.substr(pos+2);
+ GURL gurl(url);
+ pending_streams_[gurl.PathForRequest()] = NULL;
+ start = end + 2;
+ } while (end < content.length());
+ }
+
FlipStreamImpl* stream = active_streams_[stream_id];
stream->OnReply(headers);
}
diff --git a/net/flip/flip_session.h b/net/flip/flip_session.h
index 61a5d07..9f21b27 100644
--- a/net/flip/flip_session.h
+++ b/net/flip/flip_session.h
@@ -15,6 +15,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_states.h"
#include "net/base/net_errors.h"
+#include "net/base/ssl_config_service.h"
#include "net/base/upload_data_stream.h"
#include "net/flip/flip_framer.h"
#include "net/flip/flip_protocol.h"
@@ -141,7 +142,8 @@ class FlipSession : public base::RefCounted<FlipSession>,
void OnFin(const flip::FlipFinStreamControlFrame* frame);
// IO Callbacks
- void OnSocketConnect(int result);
+ void OnTCPConnect(int result);
+ void OnSSLConnect(int result);
void OnReadComplete(int result);
void OnWriteComplete(int result);
@@ -166,17 +168,21 @@ class FlipSession : public base::RefCounted<FlipSession>,
// Callbacks for the Flip session.
CompletionCallbackImpl<FlipSession> connect_callback_;
+ CompletionCallbackImpl<FlipSession> ssl_connect_callback_;
CompletionCallbackImpl<FlipSession> read_callback_;
CompletionCallbackImpl<FlipSession> write_callback_;
// The domain this session is connected to.
std::string domain_;
+ SSLConfig ssl_config_;
+
scoped_refptr<HttpNetworkSession> session_;
// The socket handle for this session.
ClientSocketHandle connection_;
- bool connection_started_;
+ bool connection_started_; // Is the connect process started.
+ bool connection_ready_; // Is the connection ready for use.
// The read buffer used to read data from the socket.
enum { kReadBufferSize = (4 * 1024) };
@@ -190,6 +196,9 @@ class FlipSession : public base::RefCounted<FlipSession>,
ActiveStreamMap active_streams_;
ActiveStreamList pushed_streams_;
+ // List of streams declared in X-Associated-Content headers.
+ // The key is a string representing the path of the URI being pushed.
+ std::map<std::string, FlipDelegate*> pending_streams_;
// As we gather data to be sent, we put it into the output queue.
typedef std::priority_queue<PrioritizedIOBuffer> OutputQueue;
diff --git a/net/flip/flip_session_pool.cc b/net/flip/flip_session_pool.cc
index 2aef13a..69d4a8c 100644
--- a/net/flip/flip_session_pool.cc
+++ b/net/flip/flip_session_pool.cc
@@ -81,7 +81,7 @@ void FlipSessionPool::RemoveSessionList(std::string domain) {
// static
void FlipSessionPool::CloseAllSessions() {
- while (sessions_->size()) {
+ while (sessions_.get() && sessions_->size()) {
FlipSessionList* list = sessions_->begin()->second;
DCHECK(list);
sessions_->erase(sessions_->begin()->first);