// Copyright (c) 2009 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/tools/flip_server/streamer_interface.h"

#include <string>

#include "net/tools/balsa/balsa_frame.h"
#include "net/tools/flip_server/constants.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"

namespace net {

std::string StreamerSM::forward_ip_header_;

StreamerSM::StreamerSM(SMConnection* connection,
                       SMInterface* sm_other_interface,
                       EpollServer* epoll_server,
                       FlipAcceptor* acceptor)
    : connection_(connection),
      sm_other_interface_(sm_other_interface),
      epoll_server_(epoll_server),
      acceptor_(acceptor),
      is_request_(false),
      http_framer_(new BalsaFrame) {
  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Creating StreamerSM object";
  http_framer_->set_balsa_visitor(this);
  http_framer_->set_balsa_headers(&headers_);
  http_framer_->set_is_request(false);
}

StreamerSM::~StreamerSM() {
  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Destroying StreamerSM object";
  Reset();
  delete http_framer_;
}

void StreamerSM::set_is_request() {
  is_request_ = true;
  http_framer_->set_is_request(true);
}

void StreamerSM::InitSMInterface(SMInterface* sm_other_interface,
                                 int32 server_idx) {
  sm_other_interface_ = sm_other_interface;
}

void StreamerSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
                                  SMInterface* sm_interface,
                                  EpollServer* epoll_server,
                                  int fd,
                                  std::string server_ip,
                                  std::string server_port,
                                  std::string remote_ip,
                                  bool use_ssl) {
  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
          << "connection.";
  connection_->InitSMConnection(connection_pool,
                                sm_interface,
                                epoll_server,
                                fd,
                                server_ip,
                                server_port,
                                remote_ip,
                                use_ssl);
}

size_t StreamerSM::ProcessReadInput(const char* data, size_t len) {
  // For now we only want to parse http requests. Just stream responses
  if (is_request_) {
    return http_framer_->ProcessInput(data, len);
  } else {
    return sm_other_interface_->ProcessWriteInput(data, len);
  }
}

size_t StreamerSM::ProcessWriteInput(const char* data, size_t len) {
  char* dataPtr = new char[len];
  memcpy(dataPtr, data, len);
  DataFrame* df = new DataFrame;
  df->data = (const char*)dataPtr;
  df->size = len;
  df->delete_when_done = true;
  connection_->EnqueueDataFrame(df);
  return len;
}

bool StreamerSM::Error() const { return false; }

const char* StreamerSM::ErrorAsString() const { return "(none)"; }

bool StreamerSM::MessageFullyRead() const {
  if (is_request_) {
    return http_framer_->MessageFullyRead();
  } else {
    return false;
  }
}

void StreamerSM::Reset() {
  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Reset";
  connection_->Cleanup("Server Reset");
  http_framer_->Reset();
}

void StreamerSM::ResetForNewConnection() {
  http_framer_->Reset();
  sm_other_interface_->Reset();
}

void StreamerSM::Cleanup() {
  if (is_request_)
    http_framer_->Reset();
}

int StreamerSM::PostAcceptHook() {
  if (!sm_other_interface_) {
    SMConnection* server_connection = SMConnection::NewSMConnection(
        epoll_server_, NULL, NULL, acceptor_, "server_conn: ");
    if (server_connection == NULL) {
      LOG(ERROR) << "StreamerSM: Could not create server conenction.";
      return 0;
    }
    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Creating new server "
            << "connection.";
    sm_other_interface_ =
        new StreamerSM(server_connection, this, epoll_server_, acceptor_);
    sm_other_interface_->InitSMInterface(this, 0);
  }
  // The Streamer interface is used to stream HTTPS connections, so we
  // will always use the https_server_ip/port here.
  sm_other_interface_->InitSMConnection(NULL,
                                        sm_other_interface_,
                                        epoll_server_,
                                        -1,
                                        acceptor_->https_server_ip_,
                                        acceptor_->https_server_port_,
                                        std::string(),
                                        false);

  return 1;
}

size_t StreamerSM::SendSynStream(uint32 stream_id,
                                 const BalsaHeaders& headers) {
  return 0;
}

size_t StreamerSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
  return 0;
}

void StreamerSM::ProcessBodyInput(const char* input, size_t size) {
  VLOG(2) << ACCEPTOR_CLIENT_IDENT
          << "StreamerHttpSM: Process Body Input Data: "
          << "size " << size;
  sm_other_interface_->ProcessWriteInput(input, size);
}

void StreamerSM::MessageDone() {
  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerHttpSM: MessageDone.";
    // TODO(kelindsay): anything need to be done ehre?
  } else {
    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StraemerHttpSM: MessageDone.";
  }
}

void StreamerSM::ProcessHeaders(const BalsaHeaders& headers) {
  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpStreamerSM: Process Headers";
  BalsaHeaders mod_headers;
  mod_headers.CopyFrom(headers);
  if (forward_ip_header_.length()) {
    LOG(INFO) << "Adding forward header: " << forward_ip_header_;
    mod_headers.ReplaceOrAppendHeader(forward_ip_header_,
                                      connection_->client_ip());
  } else {
    LOG(INFO) << "NOT adding forward header.";
  }
  SimpleBuffer sb;
  char* buffer;
  int size;
  mod_headers.WriteHeaderAndEndingToBuffer(&sb);
  sb.GetReadablePtr(&buffer, &size);
  sm_other_interface_->ProcessWriteInput(buffer, size);
}

void StreamerSM::HandleHeaderError(BalsaFrame* framer) { HandleError(); }

void StreamerSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); }

void StreamerSM::HandleBodyError(BalsaFrame* framer) { HandleError(); }

void StreamerSM::HandleError() {
  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
}

}  // namespace net
