/*
 * Copyright (C) 2015 by the University of Southern California
 * $Id: main.cc 24227 2015-05-28 22:45:30Z liangzhu $
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#include <iostream>
#include <unistd.h>
#include <string>
#include <signal.h>
#include "global_var.h"
#include "server_proxy.hh"
using namespace std;

int log_level = LOG_DEBUG;
void usage(const char *comm) {
  cerr << " Usage:\n " << comm << "[-alpsch]\n"
    " -a IP            listening address, default is ANY\n"
    " -l PORT          listening port, tcp(tls upgrade) OR direct tls\n"
    "                  default is port 10053\n"
    " -p SERV_PORT     server port, default is 53\n"
    " -s SERV_IP       server ip addresses\n"
    " -t CONNECTION    accept TCP/TLS query, default TCP+TLS upgrade\n"
    " -k KEY_FILE      path to cert file, default is \"./key.pem\"\n"
    " -c CERT_FILE     path to key file, default is \"./cert.pem\"\n"
    " -h               print this help message\n";
  exit(1);
}

/*void sig_handler(int signum)
{
  cerr << "[" << getpid() << "] Interrupt signal (" 
       << signum << ") received, exit!\n";
  exit(signum);
}*/

int main(int argc, char *argv[])
{
  const char *comm = argv[0];
  if (argc == 1) usage(comm);
  
  string svr_ip, lis_ip = "ANY", conn;
  string key_file, cert_file;
  int svr_port = 53, lis_port = 10053, conn_type = CONN_TCP;
  int opt = -1;
  while ((opt = getopt(argc, argv, "a:l:p:s:t:k:c:h")) != -1) {
    switch(opt) {
    case 'a':
      lis_ip = optarg;
      break;
    case 'l':
      lis_port = atoi(optarg);
      break;
    case 'p':
      svr_port = atoi(optarg);
      break;
    case 's':
      svr_ip = optarg;
      break;
    case 't':
      conn = optarg;
      break;
    case 'k':
      key_file = optarg;
      break;
    case 'c':
      cert_file = optarg;
      break;
    default:
      usage(comm);
    }
  }

  if (svr_ip.length() == 0)
    errx(1, "[error] server ip is not given, abort!");

  if (key_file.length() == 0)
    errx(1, "[error] a key file is not given, abort!");

  if (cert_file.length() == 0)
    errx(1, "[error] a cert file is not given, abort!");

  if (lis_ip == "ANY")
    warnx("[warn] listen on ANY ip in this machine!");

  if (svr_port <= 0) {
    warnx("[warn] use default recursive server port 53!");
    svr_port = 53;
  }

  //signal (SIGQUIT, sig_handler);
  //signal (SIGINT, sig_handler);

  if (conn.length() == 0) {
    warnx("[warn] connection type is not given, use default TCP+TLS upgrade");
    conn = "TCP";
  }
  if (conn == "tcp" || conn == "TCP") {
    DBG("start proxy as tcp+tls upgrade\n");
    conn_type = CONN_TCP;
  } else if (conn == "tls" || conn == "TLS") {
    DBG("start proxy as direct tls\n");
    conn_type = CONN_TLS;
  } else
    errx(1, "[error] unknow connection type");

  if (lis_port <= 0) {
    lis_port = 10053;
    warnx("[warn] %s: use default port 10053!", 
	  conn_type == CONN_TLS ? "TLS" : "TCP");
  }

  DBG("%s: listen ip [%s], port [%d]\n", 
      conn.c_str(), lis_ip.c_str(), lis_port);
  DBG("server ip [%s], port [%d]\n", svr_ip.c_str(), svr_port);
  DBG("key file[%s], cert file[%s]\n", key_file.c_str(), cert_file.c_str());
  server_proxy spxy(svr_ip.c_str(), svr_port, 
		    lis_ip.c_str(), lis_port, 
		    conn_type, 
		    key_file.c_str(), cert_file.c_str());
  spxy.start();
  DBG("ends\n");
  return 0;
}
