// 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/stringprintf.h"
#include "base/string_util.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_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";

// 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) {
  DCHECK(!location_url_.empty());
  thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
  Start();
}

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

void DialUdpServer::CreateAndBind() {
  DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
  socket_ = factory_->CreateAndBind(GetAddressForAllInterfaces(1900), this);
  DLOG_IF(WARNING, !socket_) << "Failed to bind socket for Dial UDP Server";
}

void DialUdpServer::Shutdown() {
  DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
  location_url_.clear();
  socket_ = NULL;
}

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

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

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

void DialUdpServer::DidRead(UDPListenSocket* server,
                            const char* data,
                            int len,
                            const IPEndPoint* address) {
  DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
  if (!socket_) {
    return;
  }
  std::string st_request_id;
  // If M-Search request was valid, send response. Else, keep quiet.
  if (ParseSearchRequest(std::string(data, len))) {
    std::string response = ConstructSearchResponse();
    socket_->SendTo(*address, response);
  }
}


// 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;
  }

  std::string st_request = info.GetHeaderValue("ST");
  ignore_result(TrimWhitespaceASCII(st_request, TRIM_ALL, &st_request));

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

  // The User-Agent header is supposed to be case-insensitive, but
  // the map that holds it has a case-sensitive search.
  // I could be more careful, but hey, it's a DVLOG anyway.
  DVLOG(1) << "Dial User-Agent: " << info.GetHeaderValue("USER-AGENT");
  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
