// Copyright 2015 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 "mojo/services/network/http_server_impl.h"

#include "base/logging.h"
#include "mojo/services/network/http_connection_impl.h"
#include "mojo/services/network/net_adapters.h"
#include "mojo/services/network/net_address_type_converters.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/socket/tcp_server_socket.h"

namespace mojo {

namespace {

const int kBackLog = 10;

}  // namespace

// static
void HttpServerImpl::Create(
    NetAddressPtr local_address,
    InterfaceHandle<HttpServerDelegate> delegate,
    const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
  HttpServerImpl* http_server = new HttpServerImpl(delegate.Pass());

  int net_error = http_server->Start(local_address.Pass());
  if (net_error != net::OK) {
    callback.Run(MakeNetworkError(net_error), nullptr);
    delete http_server;
    return;
  }
  callback.Run(MakeNetworkError(net::OK), http_server->GetLocalAddress());
}

HttpServerImpl::HttpServerImpl(InterfaceHandle<HttpServerDelegate> delegate)
    : delegate_(HttpServerDelegatePtr::Create(delegate.Pass())) {
  DCHECK(delegate_);
  delegate_.set_connection_error_handler([this]() { delete this; });
}

HttpServerImpl::~HttpServerImpl() {}

int HttpServerImpl::Start(NetAddressPtr local_address) {
  DCHECK(local_address);

  scoped_ptr<net::ServerSocket> socket(
      new net::TCPServerSocket(nullptr, net::NetLog::Source()));
  int net_result = socket->Listen(local_address.To<net::IPEndPoint>(),
                                  kBackLog);
  if (net_result != net::OK)
    return net_result;

  server_.reset(new net::HttpServer(socket.Pass(), this));

  return net::OK;
}

NetAddressPtr HttpServerImpl::GetLocalAddress() const {
  if (!server_)
    return nullptr;

  net::IPEndPoint address;
  int net_result = server_->GetLocalAddress(&address);
  if (net_result != net::OK)
    return nullptr;

  return NetAddress::From(address);
}

void HttpServerImpl::OnConnect(int connection_id) {
  DCHECK(connections_.find(connection_id) == connections_.end());

  InterfaceHandle<HttpConnection> connection;
  HttpConnectionDelegatePtr connection_delegate;
  InterfaceRequest<HttpConnectionDelegate> delegate_request =
      GetProxy(&connection_delegate);
  linked_ptr<HttpConnectionImpl> connection_impl(
      new HttpConnectionImpl(connection_id, this, connection_delegate.Pass(),
                             &connection));

  connections_[connection_id] = connection_impl;

  delegate_->OnConnected(connection.Pass(), delegate_request.Pass());
}

void HttpServerImpl::OnHttpRequest(int connection_id,
                                   const net::HttpServerRequestInfo& info) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedHttpRequest(info);
}

void HttpServerImpl::OnWebSocketRequest(
    int connection_id,
    const net::HttpServerRequestInfo& info) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedWebSocketRequest(info);
}

void HttpServerImpl::OnWebSocketMessage(int connection_id,
                                        const std::string& data) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_[connection_id]->OnReceivedWebSocketMessage(data);
}

void HttpServerImpl::OnClose(int connection_id) {
  DCHECK(connections_.find(connection_id) != connections_.end());
  connections_.erase(connection_id);
}

}  // namespace mojo
