summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
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);