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