spdy_websocket_stream.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/spdy/spdy_websocket_stream.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/compiler_specific.h" 10#include "googleurl/src/gurl.h" 11#include "net/base/io_buffer.h" 12#include "net/base/net_errors.h" 13#include "net/spdy/spdy_framer.h" 14#include "net/spdy/spdy_protocol.h" 15#include "net/spdy/spdy_session.h" 16#include "net/spdy/spdy_stream.h" 17 18namespace net { 19 20SpdyWebSocketStream::SpdyWebSocketStream( 21 SpdySession* spdy_session, Delegate* delegate) 22 : weak_ptr_factory_(this), 23 spdy_session_(spdy_session), 24 delegate_(delegate) { 25 DCHECK(spdy_session_); 26 DCHECK(delegate_); 27} 28 29SpdyWebSocketStream::~SpdyWebSocketStream() { 30 delegate_ = NULL; 31 Close(); 32} 33 34int SpdyWebSocketStream::InitializeStream(const GURL& url, 35 RequestPriority request_priority, 36 const BoundNetLog& net_log) { 37 if (spdy_session_->IsClosed()) 38 return ERR_SOCKET_NOT_CONNECTED; 39 40 int rv = stream_request_.StartRequest( 41 spdy_session_, url, request_priority, net_log, 42 base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated, 43 weak_ptr_factory_.GetWeakPtr())); 44 45 if (rv == OK) { 46 stream_ = stream_request_.ReleaseStream(); 47 DCHECK(stream_); 48 stream_->SetDelegate(this); 49 } 50 return rv; 51} 52 53int SpdyWebSocketStream::SendRequest(scoped_ptr<SpdyHeaderBlock> headers) { 54 if (!stream_) { 55 NOTREACHED(); 56 return ERR_UNEXPECTED; 57 } 58 stream_->set_spdy_headers(headers.Pass()); 59 int result = stream_->SendRequest(true); 60 if (result < OK && result != ERR_IO_PENDING) 61 Close(); 62 return result; 63} 64 65int SpdyWebSocketStream::SendData(const char* data, int length) { 66 if (!stream_) { 67 NOTREACHED(); 68 return ERR_UNEXPECTED; 69 } 70 scoped_refptr<IOBuffer> buf(new IOBuffer(length)); 71 memcpy(buf->data(), data, length); 72 stream_->QueueStreamData(buf.get(), length, DATA_FLAG_NONE); 73 return ERR_IO_PENDING; 74} 75 76void SpdyWebSocketStream::Close() { 77 if (stream_) { 78 stream_->Close(); 79 DCHECK(!stream_); 80 } 81} 82 83SpdySendStatus SpdyWebSocketStream::OnSendHeadersComplete() { 84 DCHECK(delegate_); 85 delegate_->OnSentSpdyHeaders(); 86 return NO_MORE_DATA_TO_SEND; 87} 88 89int SpdyWebSocketStream::OnSendBody() { 90 NOTREACHED(); 91 return ERR_UNEXPECTED; 92} 93 94SpdySendStatus SpdyWebSocketStream::OnSendBodyComplete(size_t bytes_sent) { 95 NOTREACHED(); 96 return NO_MORE_DATA_TO_SEND; 97} 98 99int SpdyWebSocketStream::OnResponseReceived( 100 const SpdyHeaderBlock& response, 101 base::Time response_time, int status) { 102 DCHECK(delegate_); 103 return delegate_->OnReceivedSpdyResponseHeader(response, status); 104} 105 106void SpdyWebSocketStream::OnHeadersSent() { 107 // This will be called when WebSocket over SPDY supports new framing. 108 NOTREACHED(); 109} 110 111int SpdyWebSocketStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { 112 DCHECK(delegate_); 113 delegate_->OnReceivedSpdyData(buffer.Pass()); 114 return OK; 115} 116 117void SpdyWebSocketStream::OnDataSent(size_t bytes_sent) { 118 DCHECK(delegate_); 119 delegate_->OnSentSpdyData(bytes_sent); 120} 121 122void SpdyWebSocketStream::OnClose(int status) { 123 stream_.reset(); 124 125 // Destruction without Close() call OnClose() with delegate_ being NULL. 126 if (!delegate_) 127 return; 128 Delegate* delegate = delegate_; 129 delegate_ = NULL; 130 delegate->OnCloseSpdyStream(); 131} 132 133void SpdyWebSocketStream::OnSpdyStreamCreated(int result) { 134 DCHECK_NE(ERR_IO_PENDING, result); 135 if (result == OK) { 136 stream_ = stream_request_.ReleaseStream(); 137 DCHECK(stream_); 138 stream_->SetDelegate(this); 139 } 140 DCHECK(delegate_); 141 delegate_->OnCreatedSpdyStream(result); 142} 143 144} // namespace net 145