// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file implements a simple HTTP server. It can exhibit odd behavior
// that's useful for testing. For example, it's useful to test that
// the updater can continue a connection if it's dropped, or that it
// handles very slow data transfers.

// To use this, simply make an HTTP connection to localhost:port and
// GET a url.

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <algorithm>
#include <string>
#include <vector>
#include "base/logging.h"

using std::min;
using std::string;
using std::vector;

namespace chromeos_update_engine {

struct HttpRequest {
  HttpRequest() : offset(0), return_code(200) {}
  string url;
  off_t offset;
  int return_code;
};

namespace {
const int kPort = 8080;  // hardcoded to 8080 for now
const int kBigLength = 100000;
}

bool ParseRequest(int fd, HttpRequest* request) {
  string headers;
  while(headers.find("\r\n\r\n") == string::npos) {
    vector<char> buf(1024);
    memset(&buf[0], 0, buf.size());
    ssize_t r = read(fd, &buf[0], buf.size() - 1);
    if (r < 0) {
      perror("read");
      exit(1);
    }
    buf.resize(r);

    headers.insert(headers.end(), buf.begin(), buf.end());
  }
  LOG(INFO) << "got headers: " << headers;

  string::size_type url_start, url_end;
  CHECK_NE(headers.find("GET "), string::npos);
  url_start = headers.find("GET ") + strlen("GET ");
  url_end = headers.find(' ', url_start);
  CHECK_NE(string::npos, url_end);
  string url = headers.substr(url_start, url_end - url_start);
  LOG(INFO) << "URL: " << url;

  string::size_type range_start, range_end;
  if (headers.find("\r\nRange: ") == string::npos) {
    request->offset = 0;
  } else {
    range_start = headers.find("\r\nRange: ") + strlen("\r\nRange: ");
    range_end = headers.find('\r', range_start);
    CHECK_NE(string::npos, range_end);
    string range_header = headers.substr(range_start, range_end - range_start);

    LOG(INFO) << "Range: " << range_header;
    CHECK(*range_header.rbegin() == '-');
    request->offset = atoll(range_header.c_str() + strlen("bytes="));
    request->return_code = 206;  // Success for Range: request
    LOG(INFO) << "Offset: " << request->offset;
  }
  request->url = url;
  return true;
}

void WriteString(int fd, const string& str) {
  unsigned int bytes_written = 0;
  while (bytes_written < str.size()) {
    ssize_t r = write(fd, str.c_str() + bytes_written,
                      str.size() - bytes_written);
    LOG(INFO) << "write() wrote " << r << " bytes";
    if (r < 0) {
      perror("write");
      return;
    }
    bytes_written += r;
  }
  LOG(INFO) << "WriteString wrote " << bytes_written << " bytes";
}

string Itoa(off_t num) {
  char buf[100] = {0};
  snprintf(buf, sizeof(buf), "%" PRIi64, num);
  return buf;
}

void WriteHeaders(int fd, bool support_range, off_t full_size,
                  off_t start_offset, int return_code) {
  LOG(INFO) << "writing headers";
  WriteString(fd, string("HTTP/1.1 ") + Itoa(return_code) + " OK\r\n");
  WriteString(fd, "Content-Type: application/octet-stream\r\n");
  if (support_range) {
    WriteString(fd, "Accept-Ranges: bytes\r\n");
    WriteString(fd, string("Content-Range: bytes ") + Itoa(start_offset) +
                "-" + Itoa(full_size - 1) + "/" + Itoa(full_size) + "\r\n");
  }
  off_t content_length = full_size;
  if (support_range)
    content_length -= start_offset;
  WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n");
  WriteString(fd, "\r\n");
}

void HandleQuitQuitQuit(int fd) {
  WriteHeaders(fd, true, 0, 0, 200);
  exit(0);
}

void HandleBig(int fd, const HttpRequest& request) {
  const off_t full_length = kBigLength;
  WriteHeaders(fd, true, full_length, request.offset, request.return_code);
  const off_t content_length = full_length - request.offset;
  int i = request.offset;
  for (; i % 10; i++)
    WriteString(fd, string(1, 'a' + (i % 10)));
  CHECK_EQ(i % 10, 0);
  for (; i < content_length; i += 10)
    WriteString(fd, "abcdefghij");
  CHECK_EQ(i, full_length);
}

// This is like /big, but it writes at most 9000 bytes. Also,
// half way through it sleeps for 70 seconds
// (technically, when (offset % (9000 * 7)) == 0).
void HandleFlaky(int fd, const HttpRequest& request) {
  const off_t full_length = kBigLength;
  WriteHeaders(fd, true, full_length, request.offset, request.return_code);
  const off_t content_length =
      min(static_cast<off_t>(9000), full_length - request.offset);
  const bool should_sleep = (request.offset % (9000 * 7)) == 0;

  string buf;

  for (int i = request.offset; i % 10; i++)
    buf.append(1, 'a' + (i % 10));
  while (static_cast<off_t>(buf.size()) < content_length)
    buf.append("abcdefghij");
  buf.resize(content_length);

  if (!should_sleep) {
    LOG(INFO) << "writing data blob of size " << buf.size();
    WriteString(fd, buf);
  } else {
    string::size_type half_way_point = buf.size() / 2;
    LOG(INFO) << "writing small data blob of size " << half_way_point;
    WriteString(fd, buf.substr(0, half_way_point));
    sleep(10);
    LOG(INFO) << "writing small data blob of size "
              << (buf.size() - half_way_point);
    WriteString(fd, buf.substr(half_way_point, buf.size() - half_way_point));
  }
}

void HandleDefault(int fd, const HttpRequest& request) {
  const string data("unhandled path");
  WriteHeaders(fd, true, data.size(), request.offset, request.return_code);
  const string data_to_write(data.substr(request.offset,
                                         data.size() - request.offset));
  WriteString(fd, data_to_write);
}

void HandleConnection(int fd) {
  HttpRequest request;
  ParseRequest(fd, &request);

  if (request.url == "/quitquitquit")
    HandleQuitQuitQuit(fd);
  else if (request.url == "/big")
    HandleBig(fd, request);
  else if (request.url == "/flaky")
    HandleFlaky(fd, request);
  else
    HandleDefault(fd, request);

  close(fd);
}

}  // namespace chromeos_update_engine

using namespace chromeos_update_engine;

int main(int argc, char** argv) {
  socklen_t clilen;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  memset(&server_addr, 0, sizeof(server_addr));
  memset(&client_addr, 0, sizeof(client_addr));

  int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (listen_fd < 0)
    LOG(FATAL) << "socket() failed";

  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = INADDR_ANY;
  server_addr.sin_port = htons(kPort);

  {
    // Get rid of "Address in use" error
    int tr = 1;
    if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &tr,
                   sizeof(int)) == -1) {
      perror("setsockopt");
      exit(1);
    }
  }

  if (bind(listen_fd, reinterpret_cast<struct sockaddr *>(&server_addr),
           sizeof(server_addr)) < 0) {
    perror("bind");
    exit(1);
  }
  CHECK_EQ(listen(listen_fd,5), 0);
  while (1) {
    clilen = sizeof(client_addr);
    int client_fd = accept(listen_fd,
                           (struct sockaddr *) &client_addr,
                           &clilen);
    LOG(INFO) << "got past accept";
    if (client_fd < 0)
      LOG(FATAL) << "ERROR on accept";
    HandleConnection(client_fd);
  }
  return 0;
}
