15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_websocket_stream.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/net_errors.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_protocol.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyWebSocketStream::SpdyWebSocketStream( 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const base::WeakPtr<SpdySession>& spdy_session, Delegate* delegate) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : spdy_session_(spdy_session), 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pending_send_data_length_(0), 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delegate_(delegate), 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_ptr_factory_(this) { 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(spdy_session_.get()); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyWebSocketStream::~SpdyWebSocketStream() { 31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) delegate_ = NULL; 32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Close(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyWebSocketStream::InitializeStream(const GURL& url, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestPriority request_priority, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) { 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!spdy_session_) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = stream_request_.StartRequest( 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url, request_priority, net_log, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == OK) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = stream_request_.ReleaseStream(); 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(stream_.get()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_->SetDelegate(this); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyWebSocketStream::SendRequest(scoped_ptr<SpdyHeaderBlock> headers) { 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!stream_.get()) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int result = stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < OK && result != ERR_IO_PENDING) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyWebSocketStream::SendData(const char* data, int length) { 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!stream_.get()) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(length, 0); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pending_send_data_length_ = static_cast<size_t>(length); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<IOBuffer> buf(new IOBuffer(length)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf->data(), data, length); 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream_->SendData(buf.get(), length, MORE_DATA_TO_SEND); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyWebSocketStream::Close() { 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (stream_.get()) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_->Close(); 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!stream_.get()); 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpdyWebSocketStream::OnRequestHeadersSent() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delegate_->OnSentSpdyHeaders(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdyResponseHeadersStatus SpdyWebSocketStream::OnResponseHeadersUpdated( 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SpdyHeaderBlock& response_headers) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->OnSpdyResponseHeadersUpdated(response_headers); 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return RESPONSE_HEADERS_ARE_COMPLETE; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SpdyWebSocketStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delegate_->OnReceivedSpdyData(buffer.Pass()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpdyWebSocketStream::OnDataSent() { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) delegate_->OnSentSpdyData(pending_send_data_length_); 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pending_send_data_length_ = 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyWebSocketStream::OnClose(int status) { 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream_.reset(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Destruction without Close() call OnClose() with delegate_ being NULL. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!delegate_) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate = delegate_; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = NULL; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate->OnCloseSpdyStream(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyWebSocketStream::OnSpdyStreamCreated(int result) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ERR_IO_PENDING, result); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == OK) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = stream_request_.ReleaseStream(); 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(stream_.get()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_->SetDelegate(this); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnCreatedSpdyStream(result); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 131