/*
 * Copyright (C) 2015 by the University of Southern California
 * $Id: main.cc 24638 2015-11-09 20:24:08Z 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 <string>
#include <algorithm>
#include <unistd.h>
#include "global_var.h"
#include "client_proxy.hh"
using namespace std;

#define DEFAULT_SERVER_PORT 853
#define DEFAULT_SERVER_CONN "TLS"
#define DEFAULT_LISTEN_PORT 53

int log_level = LOG_DEBUG;
void usage(const char *comm) {
  cerr << " Usage:\n " << comm << "[-alpsth]\n"
    " -a IP            listening address, default is 127.0.0.1\n"
    " -l PORT          listening port, default is port " << DEFAULT_LISTEN_PORT << "\n"
    " -s SERV_IP       server address\n"
    " -p SERV_PORT     server port, default is port " << DEFAULT_SERVER_PORT << "\n"
    " -t CONNECTION    upstream over TCP/TLS/STARTTLS\n"
    "                  default is " << DEFAULT_SERVER_CONN << "\n"
    " -h               print this help message\n";
  exit(1);
}

void str_upper(string &s)
{
  for (unsigned int i=0; i<s.length(); i++)
    s[i] = toupper(s[i]);
}

int main(int argc, char *argv[])
{
  const char *comm = argv[0];
  if (argc == 1) usage(comm);
  
  string svr_ip, lis_ip = "127.0.0.1", conn = DEFAULT_SERVER_CONN;
  int svr_port = DEFAULT_SERVER_PORT, lis_port = DEFAULT_LISTEN_PORT, conn_type = CONN_TLS;
  int opt = -1;
  while ((opt = getopt(argc, argv, "a:l:p:s:t: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;
    default:
      usage(comm);
    }
  }

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

  if (svr_port <= 0) {
    warnx("[warn] use default server port %d!", DEFAULT_SERVER_PORT);
    svr_port = DEFAULT_SERVER_PORT;
  }

  if (conn.length() == 0) {
    warnx("[warn] connection type is not given, use default STARTTLS");
    conn = DEFAULT_SERVER_CONN;
  }

  str_upper(conn);
  
  if (conn == "TCP") {
    DBG("start proxy as TCP\n");
    conn_type = CONN_TCP;
  } else if (conn == "TLS") {
    DBG("start proxy as direct TLS\n");
    conn_type = CONN_TLS;
  } else if (conn == "STARTTLS") {
    DBG("start proxy as STARTTLS\n");
    conn_type = CONN_STARTTLS;
  } else
    errx(1, "[error] unknow connection type[%s]", conn.c_str());

  if (lis_port <= 0) {
    lis_port = DEFAULT_LISTEN_PORT;
    warnx("[warn] use default listening port %d!", DEFAULT_LISTEN_PORT);
  }

  DBG("listen ip [%s], port [%d]\n", lis_ip.c_str(), lis_port);
  DBG("server ip [%s], port [%d], upstream [%s]\n", svr_ip.c_str(), svr_port, conn.c_str());
  client_proxy clt_pxy(svr_ip.c_str(), svr_port, 
		       lis_ip.c_str(), lis_port, conn_type);
  clt_pxy.start();
  DBG("ends\n");
  return 0;
}
