diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/flip/flip_network_transaction_unittest.cc | 3 | ||||
-rw-r--r-- | net/flip/flip_session.cc | 112 | ||||
-rw-r--r-- | net/flip/flip_session.h | 13 | ||||
-rw-r--r-- | net/flip/flip_session_pool.cc | 2 |
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); |