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.
5 #include "net/spdy/spdy_websocket_stream.h"
8 #include "base/bind_helpers.h"
9 #include "googleurl/src/gurl.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/io_buffer.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"
19 SpdyWebSocketStream::SpdyWebSocketStream(
20 SpdySession
* spdy_session
, Delegate
* delegate
)
22 spdy_session_(spdy_session
),
24 DCHECK(spdy_session_
);
28 SpdyWebSocketStream::~SpdyWebSocketStream() {
30 // If Close() has not already been called, DetachDelegate() will send a
31 // SPDY RST_STREAM. Deleting SpdyWebSocketStream is good enough to initiate
32 // graceful shutdown, so we call Close() to avoid sending a RST_STREAM.
33 // For safe, we should eliminate |delegate_| for OnClose() calback.
39 int SpdyWebSocketStream::InitializeStream(const GURL
& url
,
40 RequestPriority request_priority
,
41 const BoundNetLog
& net_log
) {
42 if (spdy_session_
->IsClosed())
43 return ERR_SOCKET_NOT_CONNECTED
;
45 int result
= spdy_session_
->CreateStream(
46 url
, request_priority
, &stream_
, net_log
,
47 base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated
,
48 base::Unretained(this)));
52 stream_
->SetDelegate(this);
57 int SpdyWebSocketStream::SendRequest(scoped_ptr
<SpdyHeaderBlock
> headers
) {
60 return ERR_UNEXPECTED
;
62 stream_
->set_spdy_headers(headers
.Pass());
63 int result
= stream_
->SendRequest(true);
64 if (result
< OK
&& result
!= ERR_IO_PENDING
)
69 int SpdyWebSocketStream::SendData(const char* data
, int length
) {
72 return ERR_UNEXPECTED
;
74 scoped_refptr
<IOBuffer
> buf(new IOBuffer(length
));
75 memcpy(buf
->data(), data
, length
);
76 return stream_
->WriteStreamData(buf
.get(), length
, DATA_FLAG_NONE
);
79 void SpdyWebSocketStream::Close() {
81 spdy_session_
->CancelPendingCreateStreams(&stream_
);
86 bool SpdyWebSocketStream::OnSendHeadersComplete(int status
) {
88 delegate_
->OnSentSpdyHeaders(status
);
92 int SpdyWebSocketStream::OnSendBody() {
94 return ERR_UNEXPECTED
;
97 int SpdyWebSocketStream::OnSendBodyComplete(int status
, bool* eof
) {
100 return ERR_UNEXPECTED
;
103 int SpdyWebSocketStream::OnResponseReceived(
104 const SpdyHeaderBlock
& response
,
105 base::Time response_time
, int status
) {
107 return delegate_
->OnReceivedSpdyResponseHeader(response
, status
);
110 void SpdyWebSocketStream::OnHeadersSent() {
111 // This will be called when WebSocket over SPDY supports new framing.
115 int SpdyWebSocketStream::OnDataReceived(const char* data
, int length
) {
117 delegate_
->OnReceivedSpdyData(data
, length
);
121 void SpdyWebSocketStream::OnDataSent(int length
) {
123 delegate_
->OnSentSpdyData(length
);
126 void SpdyWebSocketStream::OnClose(int status
) {
129 // Destruction without Close() call OnClose() with delegate_ being NULL.
132 Delegate
* delegate
= delegate_
;
134 delegate
->OnCloseSpdyStream();
137 void SpdyWebSocketStream::OnSpdyStreamCreated(int result
) {
138 DCHECK_NE(ERR_IO_PENDING
, result
);
141 stream_
->SetDelegate(this);
144 delegate_
->OnCreatedSpdyStream(result
);