// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/spdy/spdy_websocket_stream.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
#include "url/gurl.h"

namespace net {

SpdyWebSocketStream::SpdyWebSocketStream(
    const base::WeakPtr<SpdySession>& spdy_session, Delegate* delegate)
    : weak_ptr_factory_(this),
      spdy_session_(spdy_session),
      pending_send_data_length_(0),
      delegate_(delegate) {
  DCHECK(spdy_session_.get());
  DCHECK(delegate_);
}

SpdyWebSocketStream::~SpdyWebSocketStream() {
  delegate_ = NULL;
  Close();
}

int SpdyWebSocketStream::InitializeStream(const GURL& url,
                                          RequestPriority request_priority,
                                          const BoundNetLog& net_log) {
  if (!spdy_session_)
    return ERR_SOCKET_NOT_CONNECTED;

  int rv = stream_request_.StartRequest(
      SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url, request_priority, net_log,
      base::Bind(&SpdyWebSocketStream::OnSpdyStreamCreated,
                 weak_ptr_factory_.GetWeakPtr()));

  if (rv == OK) {
    stream_ = stream_request_.ReleaseStream();
    DCHECK(stream_.get());
    stream_->SetDelegate(this);
  }
  return rv;
}

int SpdyWebSocketStream::SendRequest(scoped_ptr<SpdyHeaderBlock> headers) {
  if (!stream_.get()) {
    NOTREACHED();
    return ERR_UNEXPECTED;
  }
  int result = stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND);
  if (result < OK && result != ERR_IO_PENDING)
    Close();
  return result;
}

int SpdyWebSocketStream::SendData(const char* data, int length) {
  if (!stream_.get()) {
    NOTREACHED();
    return ERR_UNEXPECTED;
  }
  DCHECK_GE(length, 0);
  pending_send_data_length_ = static_cast<size_t>(length);
  scoped_refptr<IOBuffer> buf(new IOBuffer(length));
  memcpy(buf->data(), data, length);
  stream_->SendData(buf.get(), length, MORE_DATA_TO_SEND);
  return ERR_IO_PENDING;
}

void SpdyWebSocketStream::Close() {
  if (stream_.get()) {
    stream_->Close();
    DCHECK(!stream_.get());
  }
}

void SpdyWebSocketStream::OnRequestHeadersSent() {
  DCHECK(delegate_);
  delegate_->OnSentSpdyHeaders();
}

SpdyResponseHeadersStatus SpdyWebSocketStream::OnResponseHeadersUpdated(
    const SpdyHeaderBlock& response_headers) {
  DCHECK(delegate_);
  delegate_->OnSpdyResponseHeadersUpdated(response_headers);
  return RESPONSE_HEADERS_ARE_COMPLETE;
}

void SpdyWebSocketStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
  DCHECK(delegate_);
  delegate_->OnReceivedSpdyData(buffer.Pass());
}

void SpdyWebSocketStream::OnDataSent() {
  DCHECK(delegate_);
  delegate_->OnSentSpdyData(pending_send_data_length_);
  pending_send_data_length_ = 0;
}

void SpdyWebSocketStream::OnClose(int status) {
  stream_.reset();

  // Destruction without Close() call OnClose() with delegate_ being NULL.
  if (!delegate_)
    return;
  Delegate* delegate = delegate_;
  delegate_ = NULL;
  delegate->OnCloseSpdyStream();
}

void SpdyWebSocketStream::OnSpdyStreamCreated(int result) {
  DCHECK_NE(ERR_IO_PENDING, result);
  if (result == OK) {
    stream_ = stream_request_.ReleaseStream();
    DCHECK(stream_.get());
    stream_->SetDelegate(this);
  }
  DCHECK(delegate_);
  delegate_->OnCreatedSpdyStream(result);
}

}  // namespace net
