/*
 *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/rtc_base/socketstream.h"

#include "webrtc/rtc_base/checks.h"

namespace rtc {

SocketStream::SocketStream(AsyncSocket* socket) : socket_(nullptr) {
  Attach(socket);
}

SocketStream::~SocketStream() {
  delete socket_;
}

void SocketStream::Attach(AsyncSocket* socket) {
  if (socket_)
    delete socket_;
  socket_ = socket;
  if (socket_) {
    socket_->SignalConnectEvent.connect(this, &SocketStream::OnConnectEvent);
    socket_->SignalReadEvent.connect(this,    &SocketStream::OnReadEvent);
    socket_->SignalWriteEvent.connect(this,   &SocketStream::OnWriteEvent);
    socket_->SignalCloseEvent.connect(this,   &SocketStream::OnCloseEvent);
  }
}

AsyncSocket* SocketStream::Detach() {
  AsyncSocket* socket = socket_;
  if (socket_) {
    socket_->SignalConnectEvent.disconnect(this);
    socket_->SignalReadEvent.disconnect(this);
    socket_->SignalWriteEvent.disconnect(this);
    socket_->SignalCloseEvent.disconnect(this);
    socket_ = nullptr;
  }
  return socket;
}

StreamState SocketStream::GetState() const {
  RTC_DCHECK(socket_ != nullptr);
  switch (socket_->GetState()) {
    case Socket::CS_CONNECTED:
      return SS_OPEN;
    case Socket::CS_CONNECTING:
      return SS_OPENING;
    case Socket::CS_CLOSED:
    default:
      return SS_CLOSED;
  }
}

StreamResult SocketStream::Read(void* buffer, size_t buffer_len,
                                size_t* read, int* error) {
  RTC_DCHECK(socket_ != nullptr);
  int result = socket_->Recv(buffer, buffer_len, nullptr);
  if (result < 0) {
    if (socket_->IsBlocking())
      return SR_BLOCK;
    if (error)
      *error = socket_->GetError();
    return SR_ERROR;
  }
  if ((result > 0) || (buffer_len == 0)) {
    if (read)
      *read = result;
    return SR_SUCCESS;
  }
  return SR_EOS;
}

StreamResult SocketStream::Write(const void* data, size_t data_len,
                                 size_t* written, int* error) {
  RTC_DCHECK(socket_ != nullptr);
  int result = socket_->Send(data, data_len);
  if (result < 0) {
    if (socket_->IsBlocking())
      return SR_BLOCK;
    if (error)
      *error = socket_->GetError();
    return SR_ERROR;
  }
  if (written)
    *written = result;
  return SR_SUCCESS;
}

void SocketStream::Close() {
  RTC_DCHECK(socket_ != nullptr);
  socket_->Close();
}

void SocketStream::OnConnectEvent(AsyncSocket* socket) {
  RTC_DCHECK(socket == socket_);
  SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
}

void SocketStream::OnReadEvent(AsyncSocket* socket) {
  RTC_DCHECK(socket == socket_);
  SignalEvent(this, SE_READ, 0);
}

void SocketStream::OnWriteEvent(AsyncSocket* socket) {
  RTC_DCHECK(socket == socket_);
  SignalEvent(this, SE_WRITE, 0);
}

void SocketStream::OnCloseEvent(AsyncSocket* socket, int err) {
  RTC_DCHECK(socket == socket_);
  SignalEvent(this, SE_CLOSE, err);
}


}  // namespace rtc
