/***************************************************************************
 *   Copyright (C) 2006 - 2008 Robert Hogan                                *
 *   robert@roberthogan.net                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/
#include "torkconfig.h"

TorkConfig* torkcon = TorkConfig::self();

/** Enumeration of types which option values can take */
typedef enum config_type_t {
  CONFIG_TYPE_STRING = 0,   /**< An arbitrary string. */
  CONFIG_TYPE_UINT,         /**< A non-negative integer less than MAX_INT */
  CONFIG_TYPE_BOOL,         /**< A boolean value, expressed as 0 or 1. */
  CONFIG_TYPE_DUO,         /**< two values from torkconfig required */
  CONFIG_TYPE_LINELIST,     /**< Uninterpreted config lines */
} config_type_t;


/** A variable allowed in the configuration file or on the command line. */
typedef struct config_t {
  bool (*groupcondition)(); /**<Group condition for config value */
  int (*configvalue)(); /**<Value in torkconfig */
  int (*configvaluetwo)(); /**<Second Value in torkconfig (in case of DUOs) */
  config_type_t type;  /**< The type of the value. */
  const char *text; /**< Text for value. */
  const char *suffix; /**< Text for value. */
} config_t;


/** An entry for config_vars: "The option <b>name</b> has type
 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
 * or_options_t.<b>member</b>"
 */
#define MSG(groupcond, configval, configvaltwo, type, text, suffix)                             \
  { groupcond, configval, configvaltwo, type, text, suffix }

/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
static config_t _tor_config[] = {
    MSG((&TorkConfig::defaultMaxMinOptions),
        (&TorkConfig::bandwidthBurst),
        (&TorkConfig::bandwidthBurst),
        CONFIG_TYPE_UINT,
        "BandwidthBurst",
        "KB"),
    MSG((&TorkConfig::defaultMaxMinOptions), 
        (&TorkConfig::bandwidthRate),
        NULL,
        CONFIG_TYPE_UINT,
        "BandwidthRate",
        "KB"),
    MSG((&TorkConfig::defaultMaxMinOptions), 
        (&TorkConfig::maxAdvertisedBandwidth),
        NULL,
        CONFIG_TYPE_UINT,
        "MaxAdvertisedBandwidth",
        "GB"),
    MSG((&TorkConfig::defaultMaxMinOptions), 
        (&TorkConfig::maxCircuitDirtiness),
        NULL,
        CONFIG_TYPE_UINT,
        "MaxCircuitDirtiness",
        ""),
    MSG((&TorkConfig::defaultMaxMinOptions), 
        (&TorkConfig::maxConn),
        NULL,
        CONFIG_TYPE_UINT,
        "ConnLimit",
        ""),

    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::user),
        NULL,
        CONFIG_TYPE_STRING,
        "User",
        ""),
    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::group),
        NULL,
        CONFIG_TYPE_STRING,
        "Group",
        ""),
    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::outboundBindAddress),
        NULL,
        CONFIG_TYPE_STRING,
        "OutboundBindAddress",
        ""),
    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::dataDirectory),
        NULL,
        CONFIG_TYPE_STRING,
        "dataDirectory",
        ""),
    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::hashedControlPassword),
        NULL,
        CONFIG_TYPE_STRING,
        "hashedControlPassword",
        ""),
    MSG((&TorkConfig::defaultRunningNormalOptions), 
        (&TorkConfig::cookieAuthentication),
        NULL,
        CONFIG_TYPE_STRING,
        "cookieAuthentication",
        ""),

    MSG((&TorkConfig::defaultServerIP), 
        (&TorkConfig::oRBindAddress),
        NULL,
        CONFIG_TYPE_STRING,
        "oRBindAddress",
        ""),

/*    MSG(NULL, 
        (&TorkConfig::oRPort),
        NULL,
        CONFIG_TYPE_UINT,
        "ORPort",
        ""),

    MSG((&TorkConfig::defaultServerPerformance), 
        (&TorkConfig::numCPUs),
        NULL,
        CONFIG_TYPE_UINT,
        "numCPUs",
        ""),
    MSG((&TorkConfig::defaultServerPerformance), 
        (&TorkConfig::maxOnionsPending),
        NULL,
        CONFIG_TYPE_UINT,
        "maxOnionsPending",
        ""),
    MSG((&TorkConfig::defaultServerPerformance), 
        (&TorkConfig::accountingMax),
        NULL,
        CONFIG_TYPE_UINT,
        "accountingMax",
        "bytes"),*/
/*    MSG((&TorkConfig::defaultServerPerformance), 
        (&TorkConfig::accountingStart),
        NULL,
        CONFIG_TYPE_STRING,
        "accountingStart",
        ""),*/
/*    MSG((&TorkConfig::defaultServerPerformance), 
        (&TorkConfig::shutDownWaitLength),
        NULL,
        CONFIG_TYPE_UINT,
        "ShutDownWaitLength",
        ""),

    MSG((NULL), 
        (&TorkConfig::newCircuitPeriod),
        NULL,
        CONFIG_TYPE_UINT,
        "NewCircuitPeriod",
        ""),
    MSG((NULL), 
        (&TorkConfig::dirFetchPeriod),
        NULL,
        CONFIG_TYPE_UINT,
        "DirFetchPeriod",
        ""),*/
    MSG((NULL), 
        (&TorkConfig::dirServer),
        NULL,
        CONFIG_TYPE_STRING,
        "DirServer",
        ""),
    MSG((NULL), 
        (&TorkConfig::entryNodes),
        NULL,
        CONFIG_TYPE_LINELIST,
        "EntryNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::excludeNodes),
        NULL,
        CONFIG_TYPE_LINELIST,
        "ExcludeNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::exitNodes),
        NULL,
        CONFIG_TYPE_STRING,
        "ExitNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::entryNodes),
        NULL,
        CONFIG_TYPE_STRING,
        "EntryNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::httpProxyPort),
        (&TorkConfig::httpProxyHost),
        CONFIG_TYPE_DUO,
        "HttpProxy",
        ""),
    MSG((NULL), 
        (&TorkConfig::httpsProxyPort),
        (&TorkConfig::httpsProxyHost),
        CONFIG_TYPE_DUO,
        "HttpsProxy",
        ""),
    MSG((NULL), 
        (&TorkConfig::httpProxyAuthenticatorUserName),
        (&TorkConfig::httpProxyAuthenticatorPassword),
        CONFIG_TYPE_DUO,
        "HttpProxyAuthenticator",
        ""),
    MSG((NULL), 
        (&TorkConfig::httpsProxyAuthenticatorUserName),
        (&TorkConfig::httpsProxyAuthenticatorPassword),
        CONFIG_TYPE_DUO,
        "HttpsProxyAuthenticator",
        ""),

/*    MSG((NULL), 
        (&TorkConfig::keepalivePeriod),
        NULL,
        CONFIG_TYPE_UINT,
        "KeepalivePeriod",
        ""),*/
/*    MSG((NULL), 
        (&TorkConfig::longLivedPorts),
        NULL,
        CONFIG_TYPE_STRING,
        "LongLivedPorts",
        ""),
    MSG((NULL), 
        (&TorkConfig::mapAddress),
        NULL,
        CONFIG_TYPE_STRING,
        "MapAddress",
        ""),*/
/*    MSG((NULL), 
        (&TorkConfig::numHelperNodes),
        NULL,
        CONFIG_TYPE_UINT,
        "NumHelperNodes",
        ""),*/
/*    MSG((NULL), 
        (&TorkConfig::reachableAddresses),
        NULL,
        CONFIG_TYPE_LINELIST,
        "ReachableAddresses",
        ""),
    MSG((NULL), 
        (&TorkConfig::rendNodes),
        NULL,
        CONFIG_TYPE_LINELIST,
        "RendNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::sOCKSBindAddressHost),
        (&TorkConfig::sOCKSBindAddressPort),
        CONFIG_TYPE_DUO,
        "SOCKSBindAddress",
        ":"),
    MSG((NULL), 
        (&TorkConfig::sOCKSBindAddressMany),
        NULL,
        CONFIG_TYPE_LINELIST,
        "SOCKSBindAddress",
        "\nSOCKSBindAddress"),
    MSG((NULL), 
        (&TorkConfig::sOCKSPolicy),
        NULL,
        CONFIG_TYPE_LINELIST,
        "SOCKSPolicy",
        ""),*/
/*    MSG((NULL), 
        (&TorkConfig::statusFetchPeriod),
        NULL,
        CONFIG_TYPE_UINT,
        "StatusFetchPeriod",
        ""),*/
/*    MSG((NULL), 
        (&TorkConfig::statusFetchPeriod),
        NULL,
        CONFIG_TYPE_BOOL,
        "StrictExitNodes",
        ""),
    MSG((NULL), 
        (&TorkConfig::trackHostExits),
        NULL,
        CONFIG_TYPE_LINELIST,
        "TrackHostExits",
        ""),*/
    MSG((NULL), 
        (&TorkConfig::trackHostExitsExpire),
        NULL,
        CONFIG_TYPE_UINT,
        "TrackHostExitsExpire",
        ""),

/*  { NULL,  NULL, NULL, NULL, NULL, NULL }*/
};
#undef MSG