// 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/dial/dial_udp_server.h"

#if defined(OS_STARBOARD)
#include "starboard/client_porting/poem/inet_poem.h"
#else
#include <arpa/inet.h>
#endif
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/hash.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_string_util.h"
#include "net/dial/dial_system_config.h"
#include "net/dial/dial_udp_socket_factory.h"
#include "net/server/http_server.h"
#include "net/server/http_server_request_info.h"

namespace net {

namespace {  // anonymous

const char* kDialStRequest = "urn:dial-multiscreen-org:service:dial:1";
const int kReadBufferSize = 500 * 1024;

// Get the INADDR_ANY address.
IPEndPoint GetAddressForAllInterfaces(unsigned short port) {
#if defined(OS_STARBOARD)
  return IPEndPoint::GetForAllInterfaces(port);
#else
  SockaddrStorage any_addr;
  struct sockaddr_in* in = (struct sockaddr_in*)any_addr.addr;
  in->sin_family = AF_INET;
  in->sin_port = htons(port);
  in->sin_addr.s_addr = INADDR_ANY;

  IPEndPoint addr;
  ignore_result(addr.FromSockAddr(any_addr.addr, any_addr.addr_len));
  return addr;
#endif  // !defined(OS_STARBOARD)
}

}  // namespace

DialUdpServer::DialUdpServer(const std::string& location_url,
                             const std::string& server_agent)
    : factory_(new DialUdpSocketFactory()),
      location_url_(location_url),
      server_agent_(server_agent),
      thread_("dial_udp_server"),
      is_running_(false),
      read_buf_(new IOBuffer(kReadBufferSize)) {
  DCHECK(!location_url_.empty());
  DETACH_FROM_THREAD(thread_checker_);
  thread_.StartWithOptions(
      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
  Start();
}

DialUdpServer::~DialUdpServer() {
  Stop();
}

void DialUdpServer::CreateAndBind() {
  DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current());
  // The thread_checker_ will bind to thread_ from this point on.
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  socket_ = factory_->CreateAndBind(GetAddressForAllInterfaces(1900));
  if (!socket_) {
    DLOG(WARNING) << "Failed to bind socket for Dial UDP Server";
    return;
  }

  thread_.message_loop()->task_runner()->PostTask(
      FROM_HERE, base::Bind(&DialUdpServer::AcceptAndProcessConnection,
                            base::Unretained(this)));
}

void DialUdpServer::Shutdown() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  location_url_.clear();
  socket_.reset();
  factory_.reset();
  is_running_ = false;
}

void DialUdpServer::Start() {
  DCHECK(!is_running_);
  is_running_ = true;
  thread_.message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&DialUdpServer::CreateAndBind, base::Unretained(this)));
}

void DialUdpServer::Stop() {
  DCHECK(is_running_);
  thread_.message_loop()->task_runner()->PostBlockingTask(
      FROM_HERE, base::Bind(&DialUdpServer::Shutdown,
                            base::Unretained(this)));
  thread_.Stop();
}

void DialUdpServer::AcceptAndProcessConnection() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!is_running_ || !socket_.get()) {
    return;
  }
  if (socket_->RecvFrom(
          read_buf_.get(), kReadBufferSize, &client_address_,
          base::Bind(&DialUdpServer::DidRead, base::Unretained(this))) == OK) {
    DidRead(net::OK);
  }
}

void DialUdpServer::DidClose(UDPSocket* server) {}

void DialUdpServer::DidRead(int bytes_read) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!socket_ || !read_buf_.get() || !read_buf_->data()) {
    return;
  }
  if (bytes_read <= 0) {
    LOG(WARNING) << "Dial server socket read error: " << bytes_read;
    return;
  }
  // If M-Search request was valid, send response. Else, keep quiet.
  if (ParseSearchRequest(std::string(read_buf_->data()))) {
    auto response = std::make_unique<std::string>();
    *response = ConstructSearchResponse();
    // Using the fake IOBuffer to avoid another copy.
    scoped_refptr<WrappedIOBuffer> fake_buffer =
        new WrappedIOBuffer(response->data());
    // After optimization, some compiler will dereference and get response size
    // later than passing response.
    auto response_size = response->size();
    socket_->SendTo(fake_buffer.get(), response_size, client_address_,
                    base::Bind([](scoped_refptr<WrappedIOBuffer>,
                                  std::unique_ptr<std::string>, int /*rv*/) {},
                               fake_buffer, base::Passed(&response)));
  }
  // Now post another RecvFrom to the MessageLoop to take the next request.
  thread_.message_loop()->task_runner()->PostTask(
      FROM_HERE, base::Bind(&DialUdpServer::AcceptAndProcessConnection,
                            base::Unretained(this)));
}

// Parse a request to make sure it is a M-Search.
bool DialUdpServer::ParseSearchRequest(const std::string& request) {
  HttpServerRequestInfo info;
  if (!HttpServer::ParseHeaders(request, &info)) {
    DVLOG(1) << "Failed parsing SSDP headers: " << request;
    return false;
  }

  if (!IsValidMSearchRequest(info)) {
    return false;
  }

  // TODO[Starboard]: verify that this st header is present in dial search
  // request. The header name used to be "ST".
  std::string st_request = info.GetHeaderValue("st");
  ignore_result(TrimWhitespaceASCII(st_request, base::TRIM_ALL, &st_request));

  if (st_request != kDialStRequest) {
    DVLOG(1) << "Received incorrect ST headers: " << st_request;
    return false;
  }

  DVLOG(1) << "Dial User-Agent: " << info.GetHeaderValue("user-agent");

  return true;
}

bool DialUdpServer::IsValidMSearchRequest(const HttpServerRequestInfo& info) {
  if (info.method != "M-SEARCH") {
    DVLOG(1) << "Invalid M-Search: SSDP method incorrect.";
    return false;
  }

  if (info.path != "*") {
    DVLOG(1) << "Invalid M-Search: SSDP path incorrect.";
    return false;
  }

  if (!info.data.empty()) {
    DVLOG(1) << "Invalid M-Search: SSDP request contains a body.";
    return false;
  }

  return true;
}

// Since we are constructing a response from user-generated string,
// ensure all user-generated strings pass through StringPrintf.
const std::string DialUdpServer::ConstructSearchResponse() const {
  DCHECK(!location_url_.empty());

  std::string ret("HTTP/1.1 200 OK\r\n");
  ret.append(base::StringPrintf("LOCATION: %s\r\n", location_url_.c_str()));
  ret.append("CACHE-CONTROL: max-age=1800\r\n");
  ret.append("EXT:\r\n");
  ret.append("BOOTID.UPNP.ORG: 1\r\n");
  // CONFIGID represents the state of the device description. Can be any
  // non-negative integer from 0 to 2^24 - 1.
  // DIAL clients like the Cast extension will cache the response based on this,
  // so we ensure each location change has a different config id.
  // This way when the app restarts with a new IP or port, the client updates
  // its cache of DIAL devices accordingly.
  uint32 location_hash = base::Hash(location_url_) >> 8;
  ret.append(base::StringPrintf("CONFIGID.UPNP.ORG: %u\r\n", location_hash));
  ret.append(base::StringPrintf("SERVER: %s\r\n", server_agent_.c_str()));
  ret.append(base::StringPrintf("ST: %s\r\n", kDialStRequest));
  ret.append(base::StringPrintf("USN: uuid:%s::%s\r\n",
                                DialSystemConfig::GetInstance()->model_uuid(),
                                kDialStRequest));
  ret.append("\r\n");
  return ret;
}

}  // namespace net
