Home | History | Annotate | Download | only in spdy
      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 "net/base/io_buffer.h"
     11 #include "net/base/net_errors.h"
     12 #include "net/spdy/spdy_framer.h"
     13 #include "net/spdy/spdy_protocol.h"
     14 #include "net/spdy/spdy_session.h"
     15 #include "net/spdy/spdy_stream.h"
     16 #include "url/gurl.h"
     17 
     18 namespace net {
     19 
     20 SpdyWebSocketStream::SpdyWebSocketStream(
     21     const base::WeakPtr<SpdySession>& spdy_session, Delegate* delegate)
     22     : spdy_session_(spdy_session),
     23       pending_send_data_length_(0),
     24       delegate_(delegate),
     25       weak_ptr_factory_(this) {
     26   DCHECK(spdy_session_.get());
     27   DCHECK(delegate_);
     28 }
     29 
     30 SpdyWebSocketStream::~SpdyWebSocketStream() {
     31   delegate_ = NULL;
     32   Close();
     33 }
     34 
     35 int SpdyWebSocketStream::InitializeStream(const GURL& url,
     36                                           RequestPriority request_priority,
     37                                           const BoundNetLog& net_log) {
     38   if (!spdy_session_)
     39     return ERR_SOCKET_NOT_CONNECTED;
     40 
     41   int rv = stream_request_.StartRequest(
     42       SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url, request_priority, net_log,
     43       base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated,
     44                  weak_ptr_factory_.GetWeakPtr()));
     45 
     46   if (rv == OK) {
     47     stream_ = stream_request_.ReleaseStream();
     48     DCHECK(stream_.get());
     49     stream_->SetDelegate(this);
     50   }
     51   return rv;
     52 }
     53 
     54 int SpdyWebSocketStream::SendRequest(scoped_ptr<SpdyHeaderBlock> headers) {
     55   if (!stream_.get()) {
     56     NOTREACHED();
     57     return ERR_UNEXPECTED;
     58   }
     59   int result = stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND);
     60   if (result < OK && result != ERR_IO_PENDING)
     61     Close();
     62   return result;
     63 }
     64 
     65 int SpdyWebSocketStream::SendData(const char* data, int length) {
     66   if (!stream_.get()) {
     67     NOTREACHED();
     68     return ERR_UNEXPECTED;
     69   }
     70   DCHECK_GE(length, 0);
     71   pending_send_data_length_ = static_cast<size_t>(length);
     72   scoped_refptr<IOBuffer> buf(new IOBuffer(length));
     73   memcpy(buf->data(), data, length);
     74   stream_->SendData(buf.get(), length, MORE_DATA_TO_SEND);
     75   return ERR_IO_PENDING;
     76 }
     77 
     78 void SpdyWebSocketStream::Close() {
     79   if (stream_.get()) {
     80     stream_->Close();
     81     DCHECK(!stream_.get());
     82   }
     83 }
     84 
     85 void SpdyWebSocketStream::OnRequestHeadersSent() {
     86   DCHECK(delegate_);
     87   delegate_->OnSentSpdyHeaders();
     88 }
     89 
     90 SpdyResponseHeadersStatus SpdyWebSocketStream::OnResponseHeadersUpdated(
     91     const SpdyHeaderBlock& response_headers) {
     92   DCHECK(delegate_);
     93   delegate_->OnSpdyResponseHeadersUpdated(response_headers);
     94   return RESPONSE_HEADERS_ARE_COMPLETE;
     95 }
     96 
     97 void SpdyWebSocketStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
     98   DCHECK(delegate_);
     99   delegate_->OnReceivedSpdyData(buffer.Pass());
    100 }
    101 
    102 void SpdyWebSocketStream::OnDataSent() {
    103   DCHECK(delegate_);
    104   delegate_->OnSentSpdyData(pending_send_data_length_);
    105   pending_send_data_length_ = 0;
    106 }
    107 
    108 void SpdyWebSocketStream::OnClose(int status) {
    109   stream_.reset();
    110 
    111   // Destruction without Close() call OnClose() with delegate_ being NULL.
    112   if (!delegate_)
    113     return;
    114   Delegate* delegate = delegate_;
    115   delegate_ = NULL;
    116   delegate->OnCloseSpdyStream();
    117 }
    118 
    119 void SpdyWebSocketStream::OnSpdyStreamCreated(int result) {
    120   DCHECK_NE(ERR_IO_PENDING, result);
    121   if (result == OK) {
    122     stream_ = stream_request_.ReleaseStream();
    123     DCHECK(stream_.get());
    124     stream_->SetDelegate(this);
    125   }
    126   DCHECK(delegate_);
    127   delegate_->OnCreatedSpdyStream(result);
    128 }
    129 
    130 }  // namespace net
    131