summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_websocket_stream.cc
diff options
context:
space:
mode:
authortoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-27 11:50:29 +0000
committertoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-27 11:50:29 +0000
commit675fa7d9f1c979b04a4606afcc5ad947a64440a7 (patch)
treec296c526db9a221f11e40f2a1af3c2868cca57be /net/spdy/spdy_websocket_stream.cc
parentfe487862e3d76fa9d07bc9b9bd645b40e20a289c (diff)
downloadchromium_src-675fa7d9f1c979b04a4606afcc5ad947a64440a7.zip
chromium_src-675fa7d9f1c979b04a4606afcc5ad947a64440a7.tar.gz
chromium_src-675fa7d9f1c979b04a4606afcc5ad947a64440a7.tar.bz2
WebSocket over SPDY: SpdyWebSocketStream
SpdyWebSocketStream implementation. This class will be used by WebSocketJob to enable WebSocket over SPDY support. BUG=42320 TEST=net_unittest --gtest_filter=SpdyWebSocket\* Review URL: http://codereview.chromium.org/7089001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90555 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy/spdy_websocket_stream.cc')
-rw-r--r--net/spdy/spdy_websocket_stream.cc145
1 files changed, 145 insertions, 0 deletions
diff --git a/net/spdy/spdy_websocket_stream.cc b/net/spdy/spdy_websocket_stream.cc
new file mode 100644
index 0000000..7ae35c5
--- /dev/null
+++ b/net/spdy/spdy_websocket_stream.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 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/spdy/spdy_websocket_stream.h"
+
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "net/base/io_buffer.h"
+#include "net/spdy/spdy_framer.h"
+#include "net/spdy/spdy_protocol.h"
+#include "net/spdy/spdy_session.h"
+#include "net/spdy/spdy_stream.h"
+
+namespace net {
+
+SpdyWebSocketStream::SpdyWebSocketStream(
+ SpdySession* spdy_session, Delegate* delegate)
+ : stream_(NULL),
+ spdy_session_(spdy_session),
+ delegate_(delegate),
+ ALLOW_THIS_IN_INITIALIZER_LIST(spdy_stream_created_callback_(
+ this, &SpdyWebSocketStream::OnSpdyStreamCreated)) {
+ DCHECK(spdy_session_);
+ DCHECK(delegate_);
+}
+
+SpdyWebSocketStream::~SpdyWebSocketStream() {
+ if (stream_) {
+ // If Close() has not already been called, DetachDelegate() will send a
+ // SPDY RST_STREAM. Deleting SpdyWebSocketStream is good enough to initiate
+ // graceful shutdown, so we call Close() to avoid sending a RST_STREAM.
+ // For safe, we should eliminate |delegate_| for OnClose() calback.
+ delegate_ = NULL;
+ stream_->Close();
+ }
+}
+
+int SpdyWebSocketStream::InitializeStream(const GURL& url,
+ RequestPriority request_priority,
+ const BoundNetLog& net_log) {
+ if (spdy_session_->IsClosed())
+ return ERR_SOCKET_NOT_CONNECTED;
+
+ int result = spdy_session_->CreateStream(
+ url, request_priority, &stream_, net_log,
+ &spdy_stream_created_callback_);
+
+ if (result == OK) {
+ DCHECK(stream_);
+ stream_->SetDelegate(this);
+ }
+ return result;
+}
+
+int SpdyWebSocketStream::SendRequest(
+ const linked_ptr<spdy::SpdyHeaderBlock>& headers) {
+ if (!stream_) {
+ NOTREACHED();
+ return ERR_UNEXPECTED;
+ }
+ stream_->set_spdy_headers(headers);
+ int result = stream_->SendRequest(true);
+ if (result < OK && result != ERR_IO_PENDING)
+ Close();
+ return result;
+}
+
+int SpdyWebSocketStream::SendData(const char* data, int length) {
+ if (!stream_) {
+ NOTREACHED();
+ return ERR_UNEXPECTED;
+ }
+ IOBuffer* buf(new IOBuffer(length));
+ memcpy(buf->data(), data, length);
+ return stream_->WriteStreamData(buf, length, spdy::DATA_FLAG_NONE);
+}
+
+void SpdyWebSocketStream::Close() {
+ if (spdy_session_)
+ spdy_session_->CancelPendingCreateStreams(&stream_);
+ if (stream_)
+ stream_->Close();
+}
+
+bool SpdyWebSocketStream::OnSendHeadersComplete(int status) {
+ DCHECK(delegate_);
+ delegate_->OnSentSpdyHeaders(status);
+ return true;
+}
+
+int SpdyWebSocketStream::OnSendBody() {
+ NOTREACHED();
+ return ERR_UNEXPECTED;
+}
+
+int SpdyWebSocketStream::OnSendBodyComplete(int status, bool* eof) {
+ NOTREACHED();
+ *eof = true;
+ return ERR_UNEXPECTED;
+}
+
+int SpdyWebSocketStream::OnResponseReceived(
+ const spdy::SpdyHeaderBlock& response,
+ base::Time response_time, int status) {
+ DCHECK(delegate_);
+ return delegate_->OnReceivedSpdyResponseHeader(response, status);
+}
+
+void SpdyWebSocketStream::OnDataReceived(const char* data, int length) {
+ DCHECK(delegate_);
+ delegate_->OnReceivedSpdyData(data, length);
+}
+
+void SpdyWebSocketStream::OnDataSent(int length) {
+ DCHECK(delegate_);
+ delegate_->OnSentSpdyData(length);
+}
+
+void SpdyWebSocketStream::OnClose(int status) {
+ stream_ = NULL;
+
+ // Destruction without Close() call OnClose() with delegate_ being NULL.
+ if (!delegate_)
+ return;
+ Delegate* delegate = delegate_;
+ delegate_ = NULL;
+ delegate->OnCloseSpdyStream();
+}
+
+void SpdyWebSocketStream::set_chunk_callback(ChunkCallback* callback) {
+ // Do nothing. SpdyWebSocketStream doesn't send any chunked data.
+}
+
+void SpdyWebSocketStream::OnSpdyStreamCreated(int result) {
+ DCHECK_NE(ERR_IO_PENDING, result);
+ if (result == OK) {
+ DCHECK(stream_);
+ stream_->SetDelegate(this);
+ }
+ DCHECK(delegate_);
+ delegate_->OnCreatedSpdyStream(result);
+}
+
+} // namespace net