/*
 * active port forwarder - software for secure forwarding
 * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#include <config.h>

#include "afserver.h"

static struct option long_options[] = {
	{"help", 0, 0, 'h'},
	{"hostname", 1, 0, 'n'},
	{"listenport", 1, 0, 'l'},
	{"manageport", 1, 0, 'm'},
	{"timeout", 1, 0, 't'},
	{"maxidle", 1, 0, 321},
	{"verbose", 0, 0, 'v'},
	{"users", 1, 0, 'u'},
	{"clients", 1, 0, 'C'},
	{"realm", 1, 0, 'r'},
	{"raclients", 1, 0, 'R'},
	{"usrpcli", 1, 0, 'U'},
	{"climode", 1, 0, 'M'},
	{"cerfile", 1, 0, 'c'},
	{"keyfile", 1, 0, 'k'},
	{"cfgfile", 1, 0, 'f'},
	{"proto", 1, 0, 'p'},
	{"log", 1, 0, 'o'},
	{"audit", 0, 0, 'a'},
	{"nossl", 0, 0, 301},
	{"nozlib", 0, 0, 302},
	{"pass", 1, 0, 303},
#ifdef AF_INET6
	{"ipv4", 0, 0, '4'},
	{"ipv6", 0, 0, '6'},
#endif
	{"baseport", 0, 0, 'b'},
	{"dnslookups", 0, 0, 311},
	{"dateformat", 1, 0, 'D'},
#ifdef HAVE_LIBPTHREAD
	{"enableproxy", 0, 0, 'P'},
  /* FIXME: don't need it now
	{"use-https", 0, 0, 'S'},
  */
#endif
	{"version", 0, 0, 'V'},
	{0, 0, 0, 0}
};

ServerConfiguration* config;

int
main(int argc, char **argv)
{
	int	i, j=0, k, l, n, flags, sent = 0, temp;
	socklen_t	len;
	unsigned char				buff[9000];
	int			maxfdp1;
	fd_set		rset, allset, wset, tmpset;
	int numofcon, length;
	char* name    = NULL;
	char** listen  = NULL;
  int listencount = 0;
	char** manage  = NULL;
  int managecount = 0;
	char* amount  = NULL;
	char* clients = NULL;
	char* raclients = NULL;
	char* usrpcli = NULL;
  char* clim    = NULL;
	char* filenam = NULL;
	char* type    = NULL;
	char* timeout = NULL;
	char* maxidle = NULL;
  char* realmname = NULL;
	unsigned char pass[4] = {1, 2, 3, 4};
	char verbose = 0;
	char mode = 0;
#ifdef HAVE_LIBPTHREAD
  char tunneltype = 0;
#endif
	char ipfam = 0;
  char baseport = 0;
  char audit = 0;
  char dnslookups = 0;
	ServerRealm* pointer = NULL;
  TaskScheduler* scheduler;
  Task* task;
	struct sigaction act;
  time_t now;
  ServerRealm** scRealmsTable;
  UsrCli** srUsersClientsTable;
  ConnectUser** srUsersTable;
  ConnectClient** srClientsTable;
  ConnectClient** srRaClientsTable;

  char* certif = NULL;
  char* keys = NULL;
  char* dateformat = NULL;
  static char* stemp = NULL;

	SSL_METHOD* method;
	SSL_CTX* ctx;
  SSL* tmp_ssl;
	
	sigfillset(&(act.sa_mask));
	act.sa_flags = 0;
	
	act.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &act, NULL);
	act.sa_handler = server_sig_int;
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);
	
	TYPE_SET_SSL(mode);
	TYPE_SET_ZLIB(mode);
  TYPE_SET_SUPPORTED_MULTI(mode);
  
#ifdef HAVE_LIBPTHREAD
  remember_mainthread();
#endif

#ifdef AF_INET6
#define GETOPT_LONG_AF_INET6(x) "46"x
#else
#define GETOPT_LONG_AF_INET6(x) x
#endif
#ifdef HAVE_LIBPTHREAD
/* FIXME: 'S' option is not needed now
#define GETOPT_LONG_LIBPTHREAD(x) "PS"x
*/
#define GETOPT_LONG_LIBPTHREAD(x) "P"x
#else
#define GETOPT_LONG_LIBPTHREAD(x) x
#endif
  
  while ((n = getopt_long(argc, argv,
          GETOPT_LONG_LIBPTHREAD(GETOPT_LONG_AF_INET6("hn:l:m:vu:c:k:f:p:o:t:C:U:M:abD:R:r:V"))
          , long_options, 0)) != -1) {
    switch (n) {
      case 'h': {
                  server_long_usage(AF_VER("Active port forwarder (server)"));
                  break;
                }
      case 'n': {
                  name = optarg;
                  break;
                }
      case 'l': {
                  ++listencount;
                  listen = realloc(listen, sizeof(char*));
                  listen[listencount-1] = optarg;
                  break;
                }
      case 'm': {
                  ++managecount;
                  manage = realloc(manage, sizeof(char*));
                  manage[managecount-1] = optarg;
                  break;
                }
      case 't': {
                  timeout = optarg;
                  break;
                }
      case 321: {
                  maxidle = optarg;
                  break;
                }
      case 'v': {
                  ++verbose;
                  break;
                }
      case 'u': {
                  amount = optarg;
                  break;
                }
      case 'C': {
                  clients = optarg;
                  break;
                }
      case 'r': {
                  realmname = optarg;
                  break;
                }
      case 'R': {
                  raclients = optarg;
                  break;
                }
      case 'U': {
                  usrpcli = optarg;
                  break;
                }
      case 'M': {
                  clim = optarg;
                  break;
                }
      case 'c': {
                  certif = optarg;
                  break;
                }
      case 'k': {
                  keys = optarg;
                  break;
                }
      case 'p': {
                  type = optarg;
                  break;
                }
      case 'f': {
                  filenam = optarg;
                  break;
                }
      case 'o': {
                  addlogtarget(optarg);
                  break;
                }
      case 301: {
                  TYPE_UNSET_SSL(mode);
                  break;
                }
      case 302: {
                  TYPE_UNSET_ZLIB(mode);
                  break;
                }
      case 303: {
                  n = strlen(optarg);
                  memset(pass, 0, 4);
                  for (i = 0; i < n; ++i) {
                    pass[i%4] += optarg[i];
                  }
                  sent = 1;
                  break;
                }
#ifdef AF_INET6
      case '4': {
                  if (ipfam != 0) {
                    ipfam = -1;
                  }
                  else {
                    ipfam = 4;
                  }
                  break;
                }
      case '6': {
                  if (ipfam != 0) {
                    ipfam = -1;
                  }
                  else {
                    ipfam = 6;
                  }
                  break;
                }
#endif
      case 'b': {
                  baseport = 1;
                  break;
                }
      case 'a': {
                  audit = 1;
                  break;
                }
      case 311: {
                  dnslookups = 1;
                  break;
                }
      case 'D': {
                  dateformat = optarg;
                  break;
                }
#ifdef HAVE_LIBPTHREAD
      case 'P': {
                  if ((tunneltype < 0) || (tunneltype > 2)) {
                    tunneltype = -1;
                  }
                  else {
                    if (tunneltype != 2) {
                      tunneltype = 1;
                    }
                  }
                  break;
                }
                /* FIXME: don't need it now
      case 'S': {
                  if ((tunneltype < 0) || (tunneltype > 2)) {
                    tunneltype = -1;
                  }
                  else {
                    tunneltype = 2;
                  }
                  break;
                }
                */
#endif
      case 'V': {
                  printf("%s\n", (AF_VER("Active port forwarder (server)")));
                  exit(0);
                  break;
                }
      case '?': {
                  server_short_usage("");
                  break;
                }
    }
  }

	if (optind < argc) {
	    server_short_usage("Unrecognized non-option elements");
	}

	if (filenam != NULL) {
		config = parsefile(filenam, &n);
		if (n) {
			printf("parsing failed! line:%d\n", n);
			exit(1);
		}
		else {
      if (certif == NULL) {
        if (ServerConfiguration_get_certificateFile(config) == NULL) {
          ServerConfiguration_set_certificateFile(config, "cacert.pem");
        }
      }
      else {
        ServerConfiguration_set_certificateFile(config, certif);
      }
      if (keys == NULL) {
        if (ServerConfiguration_get_keysFile(config) == NULL) {
          ServerConfiguration_set_keysFile(config, "server.rsa");
        }
      }
      else {
        ServerConfiguration_set_keysFile(config, keys);
      }
      if (dateformat != NULL) {
        ServerConfiguration_set_dateFormat(config, dateformat);
      }
     
      initializelogging(verbose, ServerConfiguration_get_dateFormat(config));
      
      aflog(LOG_T_INIT, LOG_I_INFO,
          "cfg file OK! (readed realms: %d)", ServerConfiguration_get_realmsNumber(config));
      if (name != NULL)
        aflog(LOG_T_INIT, LOG_I_WARNING,
            "Warning: hostname=%s will be ignored", name);
      if (listen != NULL)
        aflog(LOG_T_INIT, LOG_I_WARNING,
            "Warning: listenport will be ignored");
      if (manage != NULL)
        aflog(LOG_T_INIT, LOG_I_WARNING,
            "Warning: manageport will be ignored");
      if (realmname != NULL)
        aflog(LOG_T_INIT, LOG_I_WARNING,
            "Warning: realmname=%s will be ignored", realmname);
      if (sent == 1)
        aflog(LOG_T_INIT, LOG_I_WARNING,
            "Warning: password from command line will be ignored");
		}
	}
  else {
    config = ServerConfiguration_new();
    if (config == NULL) {
      printf("Can't allocate memory for server configuration... exiting\n");
      exit(1);
    }
    ServerConfiguration_set_certificateFile(config, certif);
    ServerConfiguration_set_keysFile(config, keys);
    ServerConfiguration_set_dateFormat(config, dateformat);

    initializelogging(verbose, ServerConfiguration_get_dateFormat(config));
    
		if (listen == NULL) {
      listencount = 1;
      listen = calloc(1, sizeof(char*));
			listen[0] = "50127";
		}
		if (manage == NULL) {
      managecount = 1;
      manage = calloc(1, sizeof(char*));
			manage[0] = "50126";
		}
    if (managecount != listencount) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Number of listen and manage options are not the same... exiting");
      exit(1);
    }
    if (ServerConfiguration_get_certificateFile(config) == NULL) {
      ServerConfiguration_set_certificateFile(config, "cacert.pem");
    }
    if (ServerConfiguration_get_keysFile(config) == NULL) {
      ServerConfiguration_set_keysFile(config, "server.rsa");
    }
		if (type == NULL) {
			type = "tcp";
		}
    ServerConfiguration_set_realmsNumber(config, 1);
    scRealmsTable = calloc(1, sizeof(ServerRealm*));
    if (scRealmsTable == NULL) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Problem with allocating memory for ServerRealm* table... exiting");
      exit(1);
    }
    ServerConfiguration_set_realmsTable(config, scRealmsTable);
    pointer = ServerRealm_new();
    if (pointer == NULL) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Problem with allocating memory for ServerRealm structure... exiting");
      exit(1);
    }
    scRealmsTable[0] = pointer;
    ServerRealm_set_hostName(pointer, name);
    ServerRealm_set_userClientPairs(pointer, managecount);
    srUsersClientsTable = calloc(managecount, sizeof(UsrCli*));
    if (srUsersClientsTable == NULL) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Problem with allocating memory for UsrCli* table... exiting");
      exit(1);
    }
    ServerRealm_set_usersClientsTable(pointer, srUsersClientsTable);
    for (i = 0; i < managecount; ++i) {
      srUsersClientsTable[i] = UsrCli_new();
      if (srUsersClientsTable[i] == NULL) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Problem with allocating memory for UsrCli structure... exiting");
        exit(1);
      }
      UsrCli_set_listenPortName(srUsersClientsTable[i], listen[i]);
      UsrCli_set_managePortName(srUsersClientsTable[i], manage[i]);
    }
    ServerRealm_set_sUsersLimit(pointer, amount);
    ServerRealm_set_sClientsLimit(pointer, clients);
    ServerRealm_set_sRaClientsLimit(pointer, raclients);
    ServerRealm_set_sTimeout(pointer, timeout);
    ServerRealm_set_sMaxIdle(pointer, maxidle);
    ServerRealm_set_sUsersPerClient(pointer, usrpcli);
    ServerRealm_set_sClientMode(pointer, clim);
    ServerRealm_set_basePortOn(pointer, baseport);
    ServerRealm_set_auditOn(pointer, audit);
#ifdef HAVE_LIBPTHREAD
    ServerRealm_set_tunnelType(pointer, tunneltype);
#endif
    ServerRealm_set_dnsLookupsOn(pointer, dnslookups);
    ServerRealm_set_realmName(pointer, realmname);
    ServerRealm_set_password(pointer, pass);
		if (strcmp(type, "tcp") == 0) {
      temp = ServerRealm_get_realmType(pointer);
			TYPE_SET_TCP(temp);
      ServerRealm_set_realmType(pointer, temp);
		}
		else if (strcmp(type, "udp") == 0) {
      temp = ServerRealm_get_realmType(pointer);
			TYPE_SET_UDP(temp);
      ServerRealm_set_realmType(pointer, temp);
		}
		else {
      temp = ServerRealm_get_realmType(pointer);
			TYPE_SET_ZERO(temp);
      ServerRealm_set_realmType(pointer, temp);
		}
#ifdef AF_INET6
		if (ipfam == -1) {
			aflog(LOG_T_INIT, LOG_I_CRIT,
          "Conflicting types of ip protocol family... exiting");
			exit(1);
		}
		else if (ipfam == 4) {
      temp = ServerRealm_get_realmType(pointer);
			TYPE_SET_IPV4(temp);
      ServerRealm_set_realmType(pointer, temp);
		}
		else if (ipfam == 6) {
      temp = ServerRealm_get_realmType(pointer);
			TYPE_SET_IPV6(temp);
      ServerRealm_set_realmType(pointer, temp);
		}
#endif
    temp = ServerRealm_get_realmType(pointer);
		temp |= mode;
    ServerRealm_set_realmType(pointer, temp);
	}
  
	maxfdp1 = 0;
	
	SSL_library_init();
	method = SSLv3_server_method();
	ctx = SSL_CTX_new(method);
	if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
		aflog(LOG_T_INIT, LOG_I_CRIT,
        "Setting ciphers list failed... exiting");
		exit(1);
	}
  if ((flags = create_apf_dir(0))) {
    aflog(LOG_T_INIT, LOG_I_WARNING,
        "Warning: Creating ~/.apf directory failed (%d)", flags);
    if ((flags = create_apf_dir(1))) {
      aflog(LOG_T_INIT, LOG_I_WARNING,
          "Warning: Creating ./apf directory failed (%d)", flags);
    }
  }
  keys = ServerConfiguration_get_keysFile(config);
  if ((flags = generate_rsa_key(&keys))) {
    aflog(LOG_T_INIT, LOG_I_WARNING,
        "Warning: Something bad happened when generating rsa keys... (%d)", flags);
  }
  ServerConfiguration_set_keysFile(config, keys);
	if (SSL_CTX_use_RSAPrivateKey_file(ctx, ServerConfiguration_get_keysFile(config), SSL_FILETYPE_PEM) != 1) {
    aflog(LOG_T_INIT, LOG_I_CRIT,
        "Setting rsa key failed (%s)... exiting", ServerConfiguration_get_keysFile(config));
    exit(1);
  }
  certif = ServerConfiguration_get_certificateFile(config);
  if ((flags = generate_certificate(&certif, ServerConfiguration_get_keysFile(config)))) {
    aflog(LOG_T_INIT, LOG_I_WARNING,
        "Warning: Something bad happened when generating certificate... (%d)", flags);
  }
  ServerConfiguration_set_certificateFile(config, certif);
	if (SSL_CTX_use_certificate_file(ctx,
        ServerConfiguration_get_certificateFile(config), SSL_FILETYPE_PEM) != 1) {
		aflog(LOG_T_INIT, LOG_I_CRIT,
        "Setting certificate failed (%s)... exiting", ServerConfiguration_get_certificateFile(config));
		exit(1);
	}
	if (ServerConfiguration_get_realmsNumber(config) == 0) {
		aflog(LOG_T_INIT, LOG_I_CRIT,
        "Working without sense is really without sense...");
		exit(1);
	}
	
	FD_ZERO(&allset);
	FD_ZERO(&wset);
	
	if (!verbose)
		daemon(0, 0);

  scheduler = TaskScheduler_new();
  if (scheduler == NULL) {
		aflog(LOG_T_INIT, LOG_I_CRIT,
        "Problems with creating task scheduler... exiting");
		exit(1);
  }
  
  scRealmsTable = ServerConfiguration_get_realmsTable(config);
	for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) {
    if (ServerRealm_get_userClientPairs(scRealmsTable[i]) == 0) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "You have to specify at least one listen port and one manage port in each realm");
      exit(1);
    }
    srUsersClientsTable = ServerRealm_get_usersClientsTable(scRealmsTable[i]);
    for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) {
  		if ((UsrCli_get_listenPortName(srUsersClientsTable[j]) == NULL) ||
  			(UsrCli_get_managePortName(srUsersClientsTable[j]) == NULL)) {
  			aflog(LOG_T_INIT, LOG_I_CRIT,
            "Missing some of the variables...\nRealm: %d\nlistenport[%d]: %s\nmanageport[%d]: %s",
  					i, j, UsrCli_get_listenPortName(srUsersClientsTable[j]),
  					j, UsrCli_get_managePortName(srUsersClientsTable[j]));
  			exit(1);
  		}
    }
    /* checking type of the realm */
    if (!TYPE_IS_SET(ServerRealm_get_realmType(scRealmsTable[i]))) {
      if (type != NULL) {
        if (strcmp(type, "tcp") == 0) {
          temp = ServerRealm_get_realmType(scRealmsTable[i]);
          TYPE_SET_TCP(temp);
          ServerRealm_set_realmType(scRealmsTable[i], temp);
        }
        else if (strcmp(type, "udp") == 0) {
          temp = ServerRealm_get_realmType(scRealmsTable[i]);
          TYPE_SET_UDP(temp);
          ServerRealm_set_realmType(scRealmsTable[i], temp);
        }
        else {
          temp = ServerRealm_get_realmType(scRealmsTable[i]);
          TYPE_SET_TCP(temp);
          ServerRealm_set_realmType(scRealmsTable[i], temp);
        }
      }
      else {
        temp = ServerRealm_get_realmType(scRealmsTable[i]);
        TYPE_SET_TCP(temp);
        ServerRealm_set_realmType(scRealmsTable[i], temp);
      }
    }
#ifdef AF_INET6
    /* using user's value for ipfam*/
    if (TYPE_IS_UNSPEC(ServerRealm_get_realmType(scRealmsTable[i]))) {
      if (ipfam == -1) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Conflicting types of ip protocol family... exiting");
        exit(1);
      }
      else if (ipfam == 4) {
        temp = ServerRealm_get_realmType(scRealmsTable[i]);
        TYPE_SET_IPV4(temp);
        ServerRealm_set_realmType(scRealmsTable[i], temp);
      }
      else if (ipfam == 6) {
        temp = ServerRealm_get_realmType(scRealmsTable[i]);
        TYPE_SET_IPV6(temp);
        ServerRealm_set_realmType(scRealmsTable[i], temp);
      }
    }
#endif
    /* using user's values for zlib and ssl mode*/
    if (!TYPE_IS_SSL(mode)) {
      temp = ServerRealm_get_realmType(scRealmsTable[i]);
      TYPE_UNSET_SSL(temp);
      ServerRealm_set_realmType(scRealmsTable[i], temp);
    }
    if (!TYPE_IS_ZLIB(mode)) {
      temp = ServerRealm_get_realmType(scRealmsTable[i]);
      TYPE_UNSET_ZLIB(temp);
      ServerRealm_set_realmType(scRealmsTable[i], temp);
    }
    /* using user's baseport value*/
    if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) {
      ServerRealm_set_basePortOn(scRealmsTable[i], baseport);
    }
    /* using user's audit value*/
    if (ServerRealm_get_auditOn(scRealmsTable[i]) == 0) {
      ServerRealm_set_auditOn(scRealmsTable[i], audit);
    }
#ifdef HAVE_LIBPTHREAD
    /* using user's tunneltype value*/
    if (ServerRealm_get_tunnelType(scRealmsTable[i]) == 0) {
      if (tunneltype == -1) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Conflicting types of tunnel type... exiting");
        exit(1);
      }
      ServerRealm_set_tunnelType(scRealmsTable[i], tunneltype);
    }
#endif
    /* using user's dnslookups value*/
    if (ServerRealm_get_dnsLookupsOn(scRealmsTable[i]) == 0) {
      ServerRealm_set_dnsLookupsOn(scRealmsTable[i], dnslookups);
    }
    /* checking users amount */
    stemp = ServerRealm_get_sUsersLimit(scRealmsTable[i]);
    set_value(&stemp, amount, "5");
    ServerRealm_set_sUsersLimit(scRealmsTable[i], stemp);
    ServerRealm_set_usersLimit(scRealmsTable[i],
        check_value(ServerRealm_get_sUsersLimit(scRealmsTable[i]), "Invalid users amount"));
    /* checking clients amount */
    stemp = ServerRealm_get_sClientsLimit(scRealmsTable[i]);
    set_value(&stemp, clients, "1");
    ServerRealm_set_sClientsLimit(scRealmsTable[i], stemp);
    ServerRealm_set_clientsLimit(scRealmsTable[i],
        check_value(ServerRealm_get_sClientsLimit(scRealmsTable[i]), "Invalid clients amount"));
    /* checking raclients amount */
    stemp = ServerRealm_get_sRaClientsLimit(scRealmsTable[i]);
    set_value(&stemp, raclients, "1");
    ServerRealm_set_sRaClientsLimit(scRealmsTable[i], stemp);
    ServerRealm_set_raClientsLimit(scRealmsTable[i],
        check_value(ServerRealm_get_sRaClientsLimit(scRealmsTable[i]), "Invalid raclients amount"));
    /* checking usrpcli value */
    stemp = ServerRealm_get_sUsersPerClient(scRealmsTable[i]);
    set_value(&stemp, usrpcli, ServerRealm_get_sUsersLimit(scRealmsTable[i]));
    ServerRealm_set_sUsersPerClient(scRealmsTable[i], stemp);
    ServerRealm_set_usersPerClient(scRealmsTable[i],
        check_value(ServerRealm_get_sUsersPerClient(scRealmsTable[i]), "Invalid usrpcli value"));
    /* checking timeout value */
    stemp = ServerRealm_get_sTimeout(scRealmsTable[i]);
    set_value(&stemp, timeout, "5");
    ServerRealm_set_sTimeout(scRealmsTable[i], stemp);
    ServerRealm_set_timeout(scRealmsTable[i],
        check_value(ServerRealm_get_sTimeout(scRealmsTable[i]), "Invalid timeout value"));
    /* checking maxidle value */
    stemp = ServerRealm_get_sMaxIdle(scRealmsTable[i]);
    set_value(&stemp, maxidle, "0");
    ServerRealm_set_sMaxIdle(scRealmsTable[i], stemp);
    temp = check_value_liberal(ServerRealm_get_sMaxIdle(scRealmsTable[i]), "Invalid maxidle value");
    if (temp < 0) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Invalid maxidle value: %d\n", temp);
      exit(1);
    }
    ServerRealm_set_maxIdle(scRealmsTable[i], temp);
    /* checking climode value */
    stemp = ServerRealm_get_sClientMode(scRealmsTable[i]);
    set_value(&stemp, clim, "1");
    ServerRealm_set_sClientMode(scRealmsTable[i], stemp);
    ServerRealm_set_clientMode(scRealmsTable[i],
        check_value(ServerRealm_get_sClientMode(scRealmsTable[i]), "Invalid climode value"));
    /* allocating memory*/
    srUsersTable = calloc(ServerRealm_get_usersLimit(scRealmsTable[i]), sizeof(ConnectUser*));
		if (srUsersTable == NULL) {
			aflog(LOG_T_INIT, LOG_I_CRIT,
          "Calloc error - try define smaller amount of users");
			exit(1);
		}
    ServerRealm_set_usersTable(scRealmsTable[i], srUsersTable);
    for (j = 0; j < ServerRealm_get_usersLimit(scRealmsTable[i]); ++j) {
      srUsersTable[j] = ConnectUser_new();
      if (srUsersTable[j] == NULL) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Calloc error - try define smaller amount of users");
        exit(1);
      }
    }
    srClientsTable = calloc(ServerRealm_get_clientsLimit(scRealmsTable[i]), sizeof(ConnectClient*));
		if (srClientsTable == NULL) {
			aflog(LOG_T_INIT, LOG_I_CRIT,
          "Calloc error - try define smaller amount of clients");
			exit(1);
		}
    ServerRealm_set_clientsTable(scRealmsTable[i], srClientsTable);
    for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) {
      srClientsTable[j] = ConnectClient_new();
      if (srClientsTable[j] == NULL) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Calloc error - try define smaller amount of clients");
        exit(1);
      }
    }
    srRaClientsTable = calloc(ServerRealm_get_raClientsLimit(scRealmsTable[i]), sizeof(ConnectClient*));
		if (srRaClientsTable == NULL) {
			aflog(LOG_T_INIT, LOG_I_CRIT,
          "Calloc error - try define smaller amount of raclients");
			exit(1);
		}
    ServerRealm_set_raClientsTable(scRealmsTable[i], srRaClientsTable);
    for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) {
      srRaClientsTable[j] = ConnectClient_new();
      if (srRaClientsTable[j] == NULL) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Calloc error - try define smaller amount of raclients");
        exit(1);
      }
    }
		ipfam = 0x01;
#ifdef AF_INET6
		if (TYPE_IS_IPV4(ServerRealm_get_realmType(scRealmsTable[i]))) {
			ipfam |= 0x02;
		}
		else if (TYPE_IS_IPV6(ServerRealm_get_realmType(scRealmsTable[i]))) {
			ipfam |= 0x04;
		}
#endif
    if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) {
      for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) {
        if (ip_listen(&temp, UsrCli_get_listenHostName(srUsersClientsTable[j]) ?
              UsrCli_get_listenHostName(srUsersClientsTable[j]) :
              ServerRealm_get_hostName(scRealmsTable[i]),
              UsrCli_get_listenPortName(srUsersClientsTable[j]),
              (&len), ipfam)) {
          aflog(LOG_T_INIT, LOG_I_CRIT,
#ifdef AF_INET6
              "tcp_listen_%s error for %s, %s",
              (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
#else
              "tcp_listen error for %s, %s",
#endif
              UsrCli_get_listenHostName(srUsersClientsTable[j]) ?
              UsrCli_get_listenHostName(srUsersClientsTable[j]) :
              ServerRealm_get_hostName(scRealmsTable[i]),
              UsrCli_get_listenPortName(srUsersClientsTable[j]));
          exit(1);
        }
        ServerRealm_set_addressLength(scRealmsTable[i], len);
        UsrCli_set_listenFd(srUsersClientsTable[j], temp);
        flags = fcntl(UsrCli_get_listenFd(srUsersClientsTable[j]), F_GETFL, 0);
        fcntl(UsrCli_get_listenFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK);
      }
    }
    
    for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) {
      switch (ServerRealm_get_tunnelType(scRealmsTable[i])) {
        case 0: {
                  temp = find_previousFd(srUsersClientsTable, j,
                      UsrCli_get_manageHostName(srUsersClientsTable[j]),
                      UsrCli_get_managePortName(srUsersClientsTable[j]));
                  if (temp == -1) {
                    if (ip_listen(&temp, UsrCli_get_manageHostName(srUsersClientsTable[j]) ?
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) :
                          ServerRealm_get_hostName(scRealmsTable[i]),
                          UsrCli_get_managePortName(srUsersClientsTable[j]),
                          (&len), ipfam)) {
                      aflog(LOG_T_INIT, LOG_I_CRIT,
#ifdef AF_INET6
                          "tcp_listen_%s error for %s, %s",
                          (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
#else
                          "tcp_listen error for %s, %s",
#endif
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) ?
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) :
                          ServerRealm_get_hostName(scRealmsTable[i]),
                          UsrCli_get_managePortName(srUsersClientsTable[j]));
                      exit(1);
                    }
                  }
                  ServerRealm_set_addressLength(scRealmsTable[i], len);
                  UsrCli_set_manageFd(srUsersClientsTable[j], temp);
                  flags = fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_GETFL, 0);
                  fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK);
                  UsrCli_set_number(srUsersClientsTable[j], eval_UsrCliPair(srUsersClientsTable, j,
                        UsrCli_get_manageHostName(srUsersClientsTable[j]),
                        UsrCli_get_managePortName(srUsersClientsTable[j])));
                  break;
                }
#ifdef HAVE_LIBPTHREAD
        case 1:
        case 2: {
                  temp = find_previousFd(srUsersClientsTable, j,
                      UsrCli_get_manageHostName(srUsersClientsTable[j]),
                      UsrCli_get_managePortName(srUsersClientsTable[j]));
                  if (temp == -1) {
                    if (initialize_http_proxy_server(&temp,
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) ?
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) :
                          ServerRealm_get_hostName(scRealmsTable[i]),
                          UsrCli_get_managePortName(srUsersClientsTable[j]),
                          (&len), ipfam,
                          ServerRealm_get_clientsLimit(scRealmsTable[i]) +
                          ServerRealm_get_raClientsLimit(scRealmsTable[i]),
                          (ServerRealm_get_tunnelType(scRealmsTable[i]) - 1),
                          ctx)) {
                      aflog(LOG_T_INIT, LOG_I_CRIT,
#ifdef AF_INET6
                          "http%s_proxy_listen_%s error for %s, %s",
                          (ServerRealm_get_tunnelType(scRealmsTable[i]) == 2) ? "s" : "",
                          (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
#else
                          "http%s_proxy_listen error for %s, %s",
                          (ServerRealm_get_tunnelType(scRealmsTable[i]) == 2) ? "s" : "",
#endif
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) ?
                          UsrCli_get_manageHostName(srUsersClientsTable[j]) :
                          ServerRealm_get_hostName(scRealmsTable[i]),
                          UsrCli_get_managePortName(srUsersClientsTable[j]));
                      exit(1);
                    }
                  }
                  ServerRealm_set_addressLength(scRealmsTable[i], len);
                  UsrCli_set_manageFd(srUsersClientsTable[j], temp);
                  flags = fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_GETFL, 0);
                  fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK);
                  UsrCli_set_number(srUsersClientsTable[j], eval_UsrCliPair(srUsersClientsTable, j,
                        UsrCli_get_manageHostName(srUsersClientsTable[j]),
                        UsrCli_get_managePortName(srUsersClientsTable[j])));
                  break;
                }
#endif
        default: {
                   aflog(LOG_T_INIT, LOG_I_CRIT,
                       "Unknown tunnel type");
                   exit(1);
                   break;
                 }
      }
    }

    ServerRealm_set_clientAddress(scRealmsTable[i], malloc(ServerRealm_get_addressLength(scRealmsTable[i])));
    if (ServerRealm_get_clientAddress(scRealmsTable[i]) == NULL) {
      aflog(LOG_T_INIT, LOG_I_CRIT,
          "Allocating memory for client addresses failed... exiting");
      exit(1);
    }
		
    for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) {
      SslFd_set_ssl(ConnectClient_get_sslFd(srClientsTable[j]), SSL_new(ctx));
  		if (SslFd_get_ssl(ConnectClient_get_sslFd(srClientsTable[j])) == NULL) {
  			aflog(LOG_T_INIT, LOG_I_CRIT,
            "Creation of ssl object failed... exiting");
  			exit(1);
  		}
    }
    
    for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) {
      SslFd_set_ssl(ConnectClient_get_sslFd(srRaClientsTable[j]), SSL_new(ctx));
  		if (SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[j])) == NULL) {
  			aflog(LOG_T_INIT, LOG_I_CRIT,
            "Creation of ssl object failed... exiting");
  			exit(1);
  		}
    }
	
    for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) {
  		FD_SET(UsrCli_get_manageFd(srUsersClientsTable[j]), &allset);
  		maxfdp1 = (maxfdp1 > (UsrCli_get_manageFd(srUsersClientsTable[j]) + 1)) ?
        maxfdp1 : (UsrCli_get_manageFd(srUsersClientsTable[j]) + 1);
    }
    if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) {
      for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) {
  		  FD_SET(UsrCli_get_listenFd(srUsersClientsTable[j]), &allset);
  		  maxfdp1 = (maxfdp1 > (UsrCli_get_listenFd(srUsersClientsTable[j]) + 1)) ?
          maxfdp1 : (UsrCli_get_listenFd(srUsersClientsTable[j]) + 1);
      }
    }
    ServerRealm_set_connectedUsers(scRealmsTable[i], 0);
    ServerRealm_set_connectedClients(scRealmsTable[i], 0);
    ServerRealm_set_connectedRaClients(scRealmsTable[i], 0);
    for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) {
      ConnectClient_set_timer(srClientsTable[j], timeval_create(ServerRealm_get_timeout(scRealmsTable[i]), 0));
      ConnectClient_set_limit(srClientsTable[j], ServerRealm_get_usersPerClient(scRealmsTable[i]));
      if (ConnectClient_create_users(srClientsTable[j])) {
        aflog(LOG_T_INIT, LOG_I_CRIT,
            "Calloc error - try define smaller amount of usrpcli (or users)");
        exit(1);
      }
    }
    for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) {
      ConnectClient_set_timer(srRaClientsTable[j],
          timeval_create(ServerRealm_get_timeout(scRealmsTable[i]), 0));
    }
  }

	aflog(LOG_T_MAIN, LOG_I_INFO,
      "SERVER STARTED realms: %d", ServerConfiguration_get_realmsNumber(config));
  time(&now);
  ServerConfiguration_set_startTime(config, now);
	
	for ( ; ; ) {
    rset = allset;
    tmpset = wset;
    aflog(LOG_T_MAIN, LOG_I_DDEBUG,
        "select, maxfdp1: %d", maxfdp1);
    if (TaskScheduler_hasMoreTasks(scheduler)) {
      TaskScheduler_startWatching(scheduler);
      select(maxfdp1, &rset, &tmpset, NULL, TaskScheduler_get_actualTimer(scheduler));
      TaskScheduler_stopWatching(scheduler);
    }
    else {
      select(maxfdp1, &rset, &tmpset, NULL, NULL);
    }
    aflog(LOG_T_MAIN, LOG_I_DDEBUG,
        "after select...");

    for (j = 0; j < ServerConfiguration_get_realmsNumber(config); ++j) {
      pointer = scRealmsTable[j];
      srUsersTable = ServerRealm_get_usersTable(pointer);
      srClientsTable = ServerRealm_get_clientsTable(pointer);
      srRaClientsTable = ServerRealm_get_raClientsTable(pointer);
      srUsersClientsTable = ServerRealm_get_usersClientsTable(pointer);
      for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) {
        if ((ConnectUser_get_state(srUsersTable[i]) == S_STATE_OPEN) ||
            (ConnectUser_get_state(srUsersTable[i]) == S_STATE_STOPPED) ||
            (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING)) {
          if (FD_ISSET(ConnectUser_get_connFd(srUsersTable[i]), &rset)) {
            k = eval_usernum(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])], i);
            aflog(LOG_T_USER, LOG_I_DDEBUG,
                "realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(config, j),
                get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                get_username(pointer,i));
            if (TYPE_IS_TCP(ServerRealm_get_realmType(pointer))) { /* forwarding tcp packets */
              n = read(ConnectUser_get_connFd(srUsersTable[i]), &buff[5], 8091);
              if (n == -1) {
                if (errno == EAGAIN) {
                  continue;
                }
                aflog(LOG_T_USER, LOG_I_ERR,
                    "realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i), errno);
                n = 0;
              }
              if (n) {
                aflog(LOG_T_USER, LOG_I_DEBUG,
                    "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i), n);
                UserStats_add_upload(ConnectUser_get_stats(srUsersTable[i]), n);
                if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) {
                  aflog(LOG_T_USER, LOG_I_WARNING,
                      "WARNING: got packet similiar to udp");
                }
                buff[0] = AF_S_MESSAGE; /* sending message */
                buff[1] = k >> 8;	/* high bits of user number */
                buff[2] = k;		/* low bits of user number */
                buff[3] = n >> 8;	/* high bits of message length */
                buff[4] = n;		/* low bits of message length */
                SslFd_send_message(ServerRealm_get_realmType(pointer),
                    ConnectClient_get_sslFd(
                      srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                    buff, n+5);
              }
              else {
                aflog(LOG_T_USER, LOG_I_INFO,
                    "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i));
                time(&now);
                aflog(LOG_T_USER, LOG_I_NOTICE,
                    "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s",
                    get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i),
                    ConnectUser_get_nameBuf(srUsersTable[i]),
                    ConnectUser_get_portBuf(srUsersTable[i]),
                    timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i])));
                if (ServerRealm_get_auditOn(pointer)) {
                  AuditList_insert_back(
                      ConnectClient_get_auditList(
                        srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                      AuditListNode_new_entry(
                        get_username(pointer, i),
                        ConnectUser_get_nameBuf(srUsersTable[i]),
                        ConnectUser_get_portBuf(srUsersTable[i]),
                        ConnectUser_get_connectTime(srUsersTable[i]),
                        now - ConnectUser_get_connectTime(srUsersTable[i]))
                      );
                }
                close(ConnectUser_get_connFd(srUsersTable[i]));
                FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset);
                FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset);
                if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) {
                  ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR);
                  ServerRealm_decrease_connectedUsers(pointer);
                  ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]);
                  ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1;
                }
                else {
                  ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING);
                }
                BufList_clear(ConnectUser_get_bufList(srUsersTable[i]));
                buff[0] = AF_S_CONCLOSED; /* closing connection */
                buff[1] = k >> 8;	/* high bits of user number */
                buff[2] = k;		/* low bits of user number */
                SslFd_send_message(ServerRealm_get_realmType(pointer),
                    ConnectClient_get_sslFd(
                      srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                    buff, 5);
              }
            }
            else { /* when forwarding udp packets */
              n = readn(ConnectUser_get_connFd(srUsersTable[i]), buff, 5 );
              if (n != 5) {
                n = 0;
              }
              if (n) {
                if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) {
                  length = buff[3];
                  length = length << 8;
                  length += buff[4]; /* this is length of message */
                  if ((n = readn(ConnectUser_get_connFd(srUsersTable[i]), &buff[5], length)) != 0) {
                    aflog(LOG_T_USER, LOG_I_DEBUG,
                        "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d",
                        get_realmname(config, j),
                        get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                        get_username(pointer, i), n);
                    buff[1] = k >> 8;	/* high bits of user number */
                    buff[2] = k;		/* low bits of user number */
                    SslFd_send_message(ServerRealm_get_realmType(pointer),
                        ConnectClient_get_sslFd(
                          srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                        buff, n+5);
                  }
                }
                else {
                  n = 0;
                }
              }

              if (n == 0) {
                aflog(LOG_T_USER, LOG_I_INFO,
                    "realm[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(config, j),
                    get_clientname(pointer,
                      ConnectUser_get_whatClient(srUsersTable[i])), get_username(pointer, i));
                time(&now);
                aflog(LOG_T_USER, LOG_I_NOTICE,
                    "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s",
                    get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i),
                    ConnectUser_get_nameBuf(srUsersTable[i]),
                    ConnectUser_get_portBuf(srUsersTable[i]),
                    timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i])));
                close(ConnectUser_get_connFd(srUsersTable[i]));
                FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset);
                FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset);
                ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING);
                BufList_clear(ConnectUser_get_bufList(srUsersTable[i]));
                buff[0] = AF_S_CONCLOSED; /* closing connection */
                buff[1] = k >> 8;	/* high bits of user number */
                buff[2] = k;		/* low bits of user number */
                SslFd_send_message(ServerRealm_get_realmType(pointer),
                    ConnectClient_get_sslFd(
                      srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                    buff, 5);
              }

            }
          }
        }
      }
      /* ------------------------------------ */
      for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) {
        if ((ConnectUser_get_state(srUsersTable[i]) == S_STATE_STOPPED) ||
            (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING))
          if (FD_ISSET(ConnectUser_get_connFd(srUsersTable[i]), &tmpset)) {
            k = eval_usernum(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])], i);
            aflog(LOG_T_USER, LOG_I_DDEBUG,
                "realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(config, j),
                get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                get_username(pointer, i));
            n = BufListNode_readMessageLength(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i])));
            sent = write(ConnectUser_get_connFd(srUsersTable[i]),
                BufListNode_readMessage(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i]))), n);
            if ((sent > 0) && (sent != n)) {
              BufListNode_set_actPtr(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i])),
                  BufListNode_get_actPtr(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i]))) + sent);
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(config, j),
                  get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                  get_username(pointer, i), sent, n);
            }
            else if ((sent == -1) && (errno == EAGAIN)) {
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(config, j),
                  get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                  get_username(pointer, i));
            }
            else if (sent == -1) {
              aflog(LOG_T_USER, LOG_I_INFO,
                  "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(config, j),
                  get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                  get_username(pointer, i));
              time(&now);
              aflog(LOG_T_USER, LOG_I_NOTICE,
                  "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s",
                  get_realmname(config, j),
                  get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                  get_username(pointer, i),
                  ConnectUser_get_nameBuf(srUsersTable[i]),
                  ConnectUser_get_portBuf(srUsersTable[i]),
                  timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i])));
              close(ConnectUser_get_connFd(srUsersTable[i]));
              FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset);
              FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset);
              if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) {
                ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR);
                ServerRealm_decrease_connectedUsers(pointer);
                ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]);
                ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1;
              }
              else {
                ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING);
              }
              BufList_clear(ConnectUser_get_bufList(srUsersTable[i]));
              buff[0] = AF_S_CONCLOSED; /* closing connection */
              buff[1] = k >> 8;	/* high bits of user number */
              buff[2] = k;		/* low bits of user number */
              SslFd_send_message(ServerRealm_get_realmType(pointer),
                  ConnectClient_get_sslFd(
                    srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                  buff, 5);
            }
            else {
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(config, j),
                  get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                  get_username(pointer, i), sent, n);
              BufList_delete_first(ConnectUser_get_bufList(srUsersTable[i]));
              if (BufList_get_first(ConnectUser_get_bufList(srUsersTable[i])) == NULL) {
                FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset);
                buff[0] = AF_S_CAN_SEND; /* stopping transfer */
                buff[1] = k >> 8;	/* high bits of user number */
                buff[2] = k;		/* low bits of user number */
                aflog(LOG_T_USER, LOG_I_DDEBUG,
                    "realm[%s]: Client[%s]: TO user[%d]: BUFFERING MESSAGE ENDED",
                    get_realmname(config, j),
                    get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                    get_username(pointer, i));
                SslFd_send_message(ServerRealm_get_realmType(pointer),
                    ConnectClient_get_sslFd(
                      srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                    buff, 5);
                if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) {
                  aflog(LOG_T_USER, LOG_I_INFO,
                      "realm[%s]: Client[%s]: user[%d]: delayed CLOSED", get_realmname(config, j),
                      get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                      get_username(pointer, i));
                  time(&now);
                  aflog(LOG_T_USER, LOG_I_NOTICE,
                      "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s",
                      get_realmname(config, j),
                      get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])),
                      get_username(pointer, i),
                      ConnectUser_get_nameBuf(srUsersTable[i]),
                      ConnectUser_get_portBuf(srUsersTable[i]),
                      timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i])));
                  close(ConnectUser_get_connFd(srUsersTable[i]));
                  FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset);
                  FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset);
                  ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR);
                  ServerRealm_decrease_connectedUsers(pointer);
                  ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]);
                  ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1;
                  BufList_clear(ConnectUser_get_bufList(srUsersTable[i]));
                  buff[0] = AF_S_CONCLOSED; /* closing connection */
                  buff[1] = k >> 8;	/* high bits of user number */
                  buff[2] = k;		/* low bits of user number */
                  SslFd_send_message(ServerRealm_get_realmType(pointer),
                      ConnectClient_get_sslFd(
                        srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]),
                      buff, 5);
                }
                else {
                  ConnectUser_set_state(srUsersTable[i], S_STATE_OPEN);
                }
              }
            }
          }
      }
      /* ------------------------------------ */
      if (ServerRealm_get_basePortOn(pointer) == 0) {
        for (l = 0; l < ServerRealm_get_userClientPairs(pointer); ++l) {
          if (FD_ISSET(UsrCli_get_listenFd(srUsersClientsTable[l]), &rset)) {
            len = ServerRealm_get_addressLength(pointer);
            sent = accept(UsrCli_get_listenFd(srUsersClientsTable[l]), ServerRealm_get_clientAddress(pointer), &len);
            if (sent == -1) {
              if (errno == EAGAIN) {
                aflog(LOG_T_USER, LOG_I_DDEBUG,
                    "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(config, j));
              }
              else {
                aflog(LOG_T_USER, LOG_I_DDEBUG,
                    "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(config, j), errno);
              }
              continue;
            }
            flags = fcntl(sent, F_GETFL, 0);
            fcntl(sent, F_SETFL, flags | O_NONBLOCK);
            aflog(LOG_T_USER, LOG_I_DDEBUG,
                "realm[%s]: listenfd: FD_ISSET", get_realmname(config, j));
            k = find_client(pointer, ServerRealm_get_clientMode(pointer), l);
            
            if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) {
              if (ServerRealm_get_connectedUsers(pointer) == ServerRealm_get_usersLimit(pointer)) {
                close(sent);
                aflog(LOG_T_USER, LOG_I_WARNING,
                    "realm[%s]: user limit EXCEEDED", get_realmname(config, j));
              }
              else if (ConnectClient_get_connected(srClientsTable[k]) ==
                  ConnectClient_get_limit(srClientsTable[k])) {
                close(sent);
                aflog(LOG_T_USER, LOG_I_WARNING,
                    "realm[%s]: Client[%s]: usrpcli limit EXCEEDED",
                    get_realmname(config, j), get_clientname(pointer, k));
              }
              else {
                for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) {
                  if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_CLEAR) {
                    ConnectUser_set_userId(srUsersTable[i], ServerRealm_get_usersCounter(pointer));
                    ServerRealm_increase_usersCounter(pointer);
                    aflog(LOG_T_USER, LOG_I_INFO,
                        "realm[%s]: Client[%s]: new user: CONNECTING from IP: %s",
                        get_realmname(config, j), get_clientname(pointer, k),
                        sock_ntop(ServerRealm_get_clientAddress(pointer), len, ConnectUser_get_nameBuf(srUsersTable[i]),
                          ConnectUser_get_portBuf(srUsersTable[i]), ServerRealm_get_dnsLookupsOn(pointer)));
                    ConnectUser_set_connFd(srUsersTable[i], sent);
                    ConnectUser_set_state(srUsersTable[i], S_STATE_OPENING);
                    ConnectUser_set_whatClient(srUsersTable[i], k);
                    time(&now);
                    ConnectUser_set_connectTime(srUsersTable[i], now);
                    UserStats_clear(ConnectUser_get_stats(srUsersTable[i]));
                    UserStats_set_lastActivity(ConnectUser_get_stats(srUsersTable[i]), now);
                    ServerRealm_increase_connectedUsers(pointer);
                    ConnectClient_increase_connected(srClientsTable[k]);
                    memcpy(&buff[5], ConnectUser_get_nameBuf(srUsersTable[i]), 128);
                    memcpy(&buff[133], ConnectUser_get_portBuf(srUsersTable[i]), 7);
                    n = 135;
                    if (ConnectClient_get_multi(srClientsTable[k]) == CONNECTCLIENT_MULTI_ENABLED) {
                      n = 136;
                      buff[140] = UsrCli_get_number(srUsersClientsTable[l]);
                    }
                    i = find_usernum(srClientsTable[k], i);
                    buff[0] = AF_S_CONOPEN; /* opening connection */
                    buff[1] = i >> 8;	/* high bits of user number */
                    buff[2] = i;		/* low bits of user number */
                    buff[3] = n >> 8;	/* high bits of message length */
                    buff[4] = n;		/* low bits of message length */
                    SslFd_send_message(ServerRealm_get_realmType(pointer),
                        ConnectClient_get_sslFd(
                          srClientsTable[k]),
                        buff, n+5);
                    break;
                  }
                }
              }
            }
            else {
              close(sent);
              aflog(LOG_T_USER, LOG_I_ERR,
                  "realm[%s]: Client(%d) is NOT CONNECTED",
                  get_realmname(config, j), k);
            }
          }
        }
      }
      /* ------------------------------------ */
      if (ServerRealm_get_basePortOn(pointer) == 1) {
        for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) {
          if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) {
            if (FD_ISSET(ConnectClient_get_listenFd(srClientsTable[k]), &rset)) {

              len = ServerRealm_get_addressLength(pointer);
              sent = accept(ConnectClient_get_listenFd(srClientsTable[k]), ServerRealm_get_clientAddress(pointer), &len);
              if (sent == -1) {
                if (errno == EAGAIN) {
                  aflog(LOG_T_USER, LOG_I_DDEBUG,
                      "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(config, j));
                }
                else {
                  aflog(LOG_T_USER, LOG_I_DDEBUG,
                      "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(config, j), errno);
                }
                continue;
              }
              flags = fcntl(sent, F_GETFL, 0);
              fcntl(sent, F_SETFL, flags | O_NONBLOCK);
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s]: listenfd: FD_ISSET",
                  get_realmname(config, j), get_clientname(pointer, k));
              if (ServerRealm_get_connectedUsers(pointer) == ServerRealm_get_usersLimit(pointer)) {
                close(sent);
                aflog(LOG_T_USER, LOG_I_WARNING,
                    "realm[%s]: user limit EXCEEDED", get_realmname(config, j));
              }
              else if(ConnectClient_get_connected(srClientsTable[k]) ==
                  ConnectClient_get_limit(srClientsTable[k])) {
                close(sent);
                aflog(LOG_T_USER, LOG_I_WARNING,
                    "realm[%s]: Client[%s]: usrpcli limit EXCEEDED",
                    get_realmname(config, j), get_clientname(pointer, k));
              }
              else {
                for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) {
                  if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_CLEAR) {
                    ConnectUser_set_userId(srUsersTable[i], ServerRealm_get_usersCounter(pointer));
                    ServerRealm_increase_usersCounter(pointer);
                    aflog(LOG_T_USER, LOG_I_INFO,
                        "realm[%s]: Client[%s]: new user: CONNECTING from IP: %s",
                        get_realmname(config, j), get_clientname(pointer, k),
                        sock_ntop(ServerRealm_get_clientAddress(pointer), len,
                          ConnectUser_get_nameBuf(srUsersTable[i]),
                          ConnectUser_get_portBuf(srUsersTable[i]), ServerRealm_get_dnsLookupsOn(pointer)));
                    ConnectUser_set_connFd(srUsersTable[i], sent);
                    ConnectUser_set_state(srUsersTable[i], S_STATE_OPENING);
                    ConnectUser_set_whatClient(srUsersTable[i], k);
                    time(&now);
                    ConnectUser_set_connectTime(srUsersTable[i], now);
                    UserStats_clear(ConnectUser_get_stats(srUsersTable[i]));
                    UserStats_set_lastActivity(ConnectUser_get_stats(srUsersTable[i]), now);
                    ServerRealm_increase_connectedUsers(pointer);
                    ConnectClient_increase_connected(srClientsTable[k]);
                    memcpy(&buff[5], ConnectUser_get_nameBuf(srUsersTable[i]), 128);
                    memcpy(&buff[133], ConnectUser_get_portBuf(srUsersTable[i]), 7);
                    n = 135;
                    i = find_usernum(srClientsTable[k], i);
                    buff[0] = AF_S_CONOPEN; /* opening connection */
                    buff[1] = i >> 8;	/* high bits of user number */
                    buff[2] = i;		/* low bits of user number */
                    buff[3] = n >> 8;	/* high bits of message length */
                    buff[4] = n;		/* low bits of message length */
                    SslFd_send_message(ServerRealm_get_realmType(pointer),
                        ConnectClient_get_sslFd(
                          srClientsTable[k]),
                        buff, n+5);
                    break;
                  }
                }
              }
            }
          }
        }
      }
      /* ------------------------------------ */
      for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k)
        if ((ConnectClient_get_state(srClientsTable[k]) > CONNECTCLIENT_STATE_FREE) &&
            (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &rset))) {
          if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_CONNECTING) {
            make_ssl_initialize(ConnectClient_get_sslFd(srClientsTable[k]));
            aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
                "realm[%s]: new Client[%s]: SSL_accept",
                get_realmname(config, j), get_clientname(pointer, k));
            switch (make_ssl_accept(ConnectClient_get_sslFd(srClientsTable[k]))) {
              case 2: {
                        close(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])));
                        FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &allset);
                        SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srClientsTable[k])));
                        ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_FREE);
                        if ((task = ConnectClient_get_task(srClientsTable[k]))) {
                          TaskScheduler_removeTask(scheduler, task);
                          ConnectClient_set_task(srClientsTable[k], NULL);
                        }
                        ServerRealm_decrease_connectedClients(pointer);
                        aflog(LOG_T_CLIENT, LOG_I_ERR,
                            "realm[%s]: new Client[%s]: DENIED by SSL_accept",
                            get_realmname(config, j), get_clientname(pointer, k));
                      }
              case 1: {
                        continue;
                      }
              default: {
                         aflog(LOG_T_CLIENT, LOG_I_DEBUG,
                             "realm[%s]: new Client[%s]: ACCEPTED by SSL_accept",
                             get_realmname(config, j), get_clientname(pointer, k));
                         ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_AUTHORIZING);
                         continue;
                       }
            }
          }
          aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
              "realm[%s]: Client[%s]: commfd: FD_ISSET",
              get_realmname(config, j), get_clientname(pointer, k));
          if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) {
            n = SslFd_get_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                ConnectClient_get_sslFd(srClientsTable[k]),
                buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k])));
          }
          else {
            n = SslFd_get_message(ServerRealm_get_realmType(pointer),
                ConnectClient_get_sslFd(srClientsTable[k]),
                buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k])));
          }
          if (n == -1) {
            if (errno == EAGAIN) {
              aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s]: commfd: EAGAIN",
                  get_realmname(config, j), get_clientname(pointer, k));
              continue;
            }
            else {
              aflog(LOG_T_CLIENT, LOG_I_ERR,
                  "realm[%s]: Client[%s]: commfd: ERROR: %d",
                  get_realmname(config, j), get_clientname(pointer, k), errno);
              n = 0;
            }
          }
          else if (n != 5) {
            if (n != 0) {
              aflog(LOG_T_CLIENT, LOG_I_DEBUG,
                  "realm[%s]: Client[%s]: header length = %d --> buffering",
                  get_realmname(config, j), get_clientname(pointer, k), n);
              HeaderBuffer_store(ConnectClient_get_header(srClientsTable[k]), buff, n);
              if (HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k])) == 0) {
                HeaderBuffer_restore(ConnectClient_get_header(srClientsTable[k]), buff);
                n = 5;
              }
              else {
                continue;
              }
            }
          }
          if (n==0) { 
            aflog(LOG_T_CLIENT, LOG_I_INFO,
                "realm[%s]: Client[%s]: commfd: CLOSED",
                get_realmname(config, j), get_clientname(pointer, k));
            time(&now);
            aflog(LOG_T_CLIENT, LOG_I_NOTICE,
                "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s",
                get_realmname(config, j),
                get_clientname(pointer, k),
                ConnectClient_get_nameBuf(srClientsTable[k]),
                ConnectClient_get_portBuf(srClientsTable[k]),
                timeperiod(now - ConnectClient_get_connectTime(srClientsTable[k])));
            if (ServerRealm_get_auditOn(pointer)) {
              while (AuditList_get_first(ConnectClient_get_auditList(srClientsTable[k]))) {
                aflog(LOG_T_CLIENT, LOG_I_NOTICE,
                    "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s",
                    AuditListNode_get_userId(
                      AuditList_get_first(
                        ConnectClient_get_auditList(srClientsTable[k]))),
                    AuditListNode_get_nameBuf(
                      AuditList_get_first(
                        ConnectClient_get_auditList(srClientsTable[k]))),
                    AuditListNode_get_portBuf(
                      AuditList_get_first(
                        ConnectClient_get_auditList(srClientsTable[k]))),
                    localdate(AuditListNode_get_connectTimep(
                        AuditList_get_first(
                          ConnectClient_get_auditList(srClientsTable[k])))),
                    timeperiod(AuditListNode_get_duration(
                        AuditList_get_first(
                          ConnectClient_get_auditList(srClientsTable[k])))));
                AuditList_delete_first(ConnectClient_get_auditList(srClientsTable[k]));
              }
            }
            remove_client(pointer, k, &allset, &wset, scheduler);
            continue;
          }

          numofcon = buff[1];
          numofcon = numofcon << 8;
          numofcon += buff[2]; /* this is id of user */
          length = buff[3];
          length = length << 8;
          length += buff[4]; /* this is length of message */ 

          if ((k == ServerRealm_get_clientsLimit(pointer)) && (buff[0] != AF_S_LOGIN) &&
              (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) {
            buff[0] = AF_S_WRONG;
          }
          if (ConnectClient_get_state(srClientsTable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) {
            aflog(LOG_T_CLIENT, LOG_I_WARNING,
                "realm[%s]: Client[%s]: Impossible behaviour --> ignoring",
                get_realmname(config, j), get_clientname(pointer, k));
            continue;
          }
          if ((ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) &&
              (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
            buff[0] = AF_S_WRONG;
          }
          
          time(&now);
          ConnectClient_set_lastActivity(srClientsTable[k], now);
          if (ServerRealm_get_maxIdle(pointer)) {
            ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_maxIdle(pointer), 0));
            TaskScheduler_update(scheduler);
          }

          switch (buff[0]) {
            case AF_S_CONCLOSED : {
                                    n = numofcon;
                                    numofcon = eval_numofcon(pointer, k, numofcon);
                                    if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) &&
                                        (ConnectClient_get_state(srClientsTable[k]) ==
                                         CONNECTCLIENT_STATE_ACCEPTED)) {
                                      if (ConnectUser_get_state(srUsersTable[numofcon]) ==
                                          S_STATE_STOPPED) {
                                        ConnectUser_set_state(srUsersTable[numofcon], S_STATE_KICKING);
                                        aflog(LOG_T_USER, LOG_I_INFO,
                                            "realm[%s]: user[%d]: KICKING...",
                                            get_realmname(config, j), get_username(pointer, numofcon));
                                      }
                                      else {
                                        ServerRealm_decrease_connectedUsers(pointer);
                                        ConnectClient_decrease_connected(srClientsTable[k]);
                                        ConnectClient_get_users(srClientsTable[k])[n] = -1;
                                        if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_CLOSING) {
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR);
                                          aflog(LOG_T_USER, LOG_I_DEBUG,
                                              "realm[%s]: user[%d]: CLOSE CONFIRMED",
                                              get_realmname(config, j), get_username(pointer, numofcon));
                                        }
                                        else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) {
                                          aflog(LOG_T_USER, LOG_I_INFO,
                                              "realm[%s]: user[%d]: KICKED",
                                              get_realmname(config, j), get_username(pointer, numofcon));
                                          time(&now);
                                          aflog(LOG_T_USER, LOG_I_NOTICE,
                                              "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s",
                                              get_realmname(config, j),
                                              get_username(pointer, numofcon),
                                              ConnectUser_get_nameBuf(srUsersTable[numofcon]),
                                              ConnectUser_get_portBuf(srUsersTable[numofcon]),
                                              timeperiod(now -
                                                ConnectUser_get_connectTime(srUsersTable[numofcon])));
                                          close(ConnectUser_get_connFd(srUsersTable[numofcon]));
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset);
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR);
                                          BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon]));
                                          buff[0] = AF_S_CONCLOSED; /* closing connection */
                                          buff[1] = n >> 8;	/* high bits of user number */
                                          buff[2] = n;		/* low bits of user number */
                                          SslFd_send_message(ServerRealm_get_realmType(pointer),
                                              ConnectClient_get_sslFd(
                                                srClientsTable[k]),
                                              buff, 5);
                                        }
                                      }
                                    }
                                    else {
                                      remove_client(pointer, k, &allset, &wset, scheduler);
                                    }
                                    break;
                                  }
            case AF_S_CONOPEN : {
                                  n = numofcon;
                                  numofcon = eval_numofcon(pointer, k, numofcon);
                                  if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) &&
                                      (ConnectClient_get_state(srClientsTable[k]) ==
                                       CONNECTCLIENT_STATE_ACCEPTED)) {
                                    if (ConnectUser_get_state(srUsersTable[numofcon]) ==
                                          S_STATE_OPENING) {
                                      aflog(LOG_T_USER, LOG_I_INFO,
                                          "realm[%s]: user[%d]: NEW",
                                          get_realmname(config, j), get_username(pointer, numofcon));
                                      FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                      maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(srUsersTable[numofcon]) + 1)) ?
                                        maxfdp1 : (ConnectUser_get_connFd(srUsersTable[numofcon]) + 1);
                                      ConnectUser_set_state(srUsersTable[numofcon], S_STATE_OPEN);
                                    }
                                    if (ConnectUser_get_state(srUsersTable[numofcon]) ==
                                         S_STATE_OPENING_CLOSED) {
                                      aflog(LOG_T_USER, LOG_I_INFO,
                                          "realm[%s]: user[%d]: delayed CLOSING",
                                          get_realmname(config, j), get_username(pointer, numofcon));
                                      ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING);
                                      buff[0] = AF_S_CONCLOSED; /* closing connection */
                                      buff[1] = n >> 8;	/* high bits of user number */
                                      buff[2] = n;		/* low bits of user number */
                                      SslFd_send_message(ServerRealm_get_realmType(pointer),
                                          ConnectClient_get_sslFd(
                                            srClientsTable[k]),
                                          buff, 5);
                                    }
                                  }
                                  else {
                                    remove_client(pointer, k, &allset, &wset, scheduler);
                                  }
                                  break;
                                }
            case AF_S_CANT_OPEN : {
                                    n = numofcon;
                                    numofcon = eval_numofcon(pointer, k, numofcon);
                                    if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) &&
                                        (ConnectClient_get_state(srClientsTable[k]) ==
                                         CONNECTCLIENT_STATE_ACCEPTED)) {
                                      if ((ConnectUser_get_state(srUsersTable[numofcon]) ==
                                          S_STATE_OPENING) ||
                                        (ConnectUser_get_state(srUsersTable[numofcon]) ==
                                         S_STATE_OPENING_CLOSED)) {
                                        aflog(LOG_T_USER, LOG_I_INFO,
                                            "realm[%s]: user[%d]: DROPPED",
                                            get_realmname(config, j), get_username(pointer, numofcon));
                                        ServerRealm_decrease_connectedUsers(pointer);
                                        ConnectClient_decrease_connected(srClientsTable[k]);
                                        ConnectClient_get_users(srClientsTable[k])[n] = -1;
                                        if (ConnectUser_get_state(srUsersTable[numofcon]) ==
                                            S_STATE_OPENING) {
                                          close(ConnectUser_get_connFd(srUsersTable[numofcon]));
                                        }
                                        ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR);
                                      }
                                    }
                                    else {
                                      remove_client(pointer, k, &allset, &wset, scheduler);
                                    }
                                    break;
                                  }						    
            case AF_S_MESSAGE : {
                                  if (ConnectClient_get_state(srClientsTable[k]) !=
                                      CONNECTCLIENT_STATE_ACCEPTED) {
                                    remove_client(pointer, k, &allset, &wset, scheduler);
                                    break;
                                  }
                                  if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */
                                    n = SslFd_get_message(ServerRealm_get_realmType(pointer),
                                        ConnectClient_get_sslFd(
                                          srClientsTable[k]),
                                        &buff[5], length);
                                  }
                                  else {
                                    n = SslFd_get_message(ServerRealm_get_realmType(pointer),
                                        ConnectClient_get_sslFd(
                                          srClientsTable[k]),
                                        buff, length);
                                  }
                                  temp = numofcon;
                                  numofcon = eval_numofcon(pointer, k, numofcon);
                                  if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer)))) {
                                    if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) {
                                      aflog(LOG_T_USER, LOG_I_DEBUG,
                                          "realm[%s]: TO user[%d]: MESSAGE length=%d",
                                          get_realmname(config, j), get_username(pointer, numofcon), n);
                                      UserStats_add_download(ConnectUser_get_stats(srUsersTable[numofcon]), n);
                                      if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */
                                        buff[1] = AF_S_LOGIN;
                                        buff[2] = AF_S_MESSAGE;
                                        buff[3] = n >> 8; /* high bits of message length */
                                        buff[4] = n;      /* low bits of message length */
                                        sent = write(ConnectUser_get_connFd(srUsersTable[numofcon]), buff, n+5);
                                        if (sent == -1) {
                                          aflog(LOG_T_USER, LOG_I_INFO,
                                              "realm[%s]: user[%d]: CLOSED (write-udp)",
                                              get_realmname(config, j), get_username(pointer, numofcon));
                                          time(&now);
                                          aflog(LOG_T_USER, LOG_I_NOTICE,
                                              "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s",
                                              get_realmname(config, j),
                                              get_username(pointer, numofcon),
                                              ConnectUser_get_nameBuf(srUsersTable[numofcon]),
                                              ConnectUser_get_portBuf(srUsersTable[numofcon]),
                                              timeperiod(now - ConnectUser_get_connectTime(srUsersTable[numofcon])));
                                          close(ConnectUser_get_connFd(srUsersTable[numofcon]));
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset);
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING);
                                          BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon]));
                                          buff[0] = AF_S_CONCLOSED; /* closing connection */
                                          buff[1] = temp >> 8;	/* high bits of user number */
                                          buff[2] = temp;		/* low bits of user number */
                                          SslFd_send_message(ServerRealm_get_realmType(pointer),
                                              ConnectClient_get_sslFd(
                                                srClientsTable[k]),
                                              buff, 5);
                                        }
                                      }
                                      else { /* tcp */
                                        sent = write(ConnectUser_get_connFd(srUsersTable[numofcon]), buff, n);
                                        if ((sent > 0) && (sent != n)) {
                                          BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]),
                                              BufListNode_new_message(sent, n, buff));
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_STOPPED);
                                          FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset);
                                          buff[0] = AF_S_DONT_SEND; /* stopping transfer */
                                          buff[1] = temp >> 8;	/* high bits of user number */
                                          buff[2] = temp;		/* low bits of user number */
                                          aflog(LOG_T_USER, LOG_I_DDEBUG,
                                              "realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)",
                                              get_realmname(config, j), get_username(pointer, numofcon), sent, n);
                                          SslFd_send_message(ServerRealm_get_realmType(pointer),
                                              ConnectClient_get_sslFd(
                                                srClientsTable[k]),
                                              buff, 5);
                                        }
                                        else if ((sent == -1) && (errno == EAGAIN)) {
                                          BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]),
                                              BufListNode_new_message(0, n, buff));
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_STOPPED);
                                          FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset);
                                          buff[0] = AF_S_DONT_SEND; /* stopping transfer */
                                          buff[1] = temp >> 8;	/* high bits of user number */
                                          buff[2] = temp;		/* low bits of user number */
                                          aflog(LOG_T_USER, LOG_I_DDEBUG,
                                              "realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)",
                                              get_realmname(config, j), get_username(pointer, numofcon), sent, n);
                                          SslFd_send_message(ServerRealm_get_realmType(pointer),
                                              ConnectClient_get_sslFd(
                                                srClientsTable[k]),
                                              buff, 5);
                                        }
                                        else if (sent == -1) {
                                          aflog(LOG_T_USER, LOG_I_INFO,
                                              "realm[%s]: user[%d]: CLOSED (write-tcp)",
                                              get_realmname(config, j), get_username(pointer, numofcon));
                                          time(&now);
                                          aflog(LOG_T_USER, LOG_I_NOTICE,
                                              "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s",
                                              get_realmname(config, j),
                                              get_username(pointer, numofcon),
                                              ConnectUser_get_nameBuf(srUsersTable[numofcon]),
                                              ConnectUser_get_portBuf(srUsersTable[numofcon]),
                                              timeperiod(now - ConnectUser_get_connectTime(srUsersTable[numofcon])));
                                          close(ConnectUser_get_connFd(srUsersTable[numofcon]));
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                          FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset);
                                          ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING);
                                          BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon]));
                                          buff[0] = AF_S_CONCLOSED; /* closing connection */
                                          buff[1] = temp >> 8;	/* high bits of user number */
                                          buff[2] = temp;		/* low bits of user number */
                                          SslFd_send_message(ServerRealm_get_realmType(pointer),
                                              ConnectClient_get_sslFd(
                                                srClientsTable[k]),
                                              buff, 5);
                                        }
                                      }
                                    }
                                    else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED) {
                                      aflog(LOG_T_USER, LOG_I_DDEBUG,
                                          "realm[%s]: TO user[%d]: BUFFERING MESSAGE (%d)",
                                          get_realmname(config, j), get_username(pointer, numofcon), n);
                                      if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */
                                        buff[1] = AF_S_LOGIN;
                                        buff[2] = AF_S_MESSAGE;
                                        buff[3] = n >> 8; /* high bits of message length */
                                        buff[4] = n;      /* low bits of message length */
                                        BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]),
                                            BufListNode_new_message(0, n+5, buff));
                                      }
                                      else {
                                        BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]),
                                            BufListNode_new_message(0, n, buff));
                                      }
                                    }
                                    else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_CLOSING) {
                                      aflog(LOG_T_USER, LOG_I_WARNING,
                                          "realm[%s]: TO user[%d]: IGNORED message length=%d",
                                          get_realmname(config, j), get_username(pointer, numofcon), n);
                                    }
                                    else {
                                      aflog(LOG_T_USER, LOG_I_WARNING,
                                          "realm[%s]: TO user[%d]: user in wrong state - IGNORED",
                                          get_realmname(config, j), get_username(pointer, numofcon));
                                    }
                                  }
                                  else {
                                      aflog(LOG_T_USER, LOG_I_WARNING,
                                          "realm[%s]: message to non-existing user - IGNORED",
                                          get_realmname(config, j));
                                  }
                                  break;
                                }
            case AF_S_LOGIN : {
                                if ((ConnectClient_get_state(srClientsTable[k]) ==
                                      CONNECTCLIENT_STATE_AUTHORIZING) &&
                                    (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) &&
                                    (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) {
                                  ConnectClient_set_multi(srClientsTable[k], CONNECTCLIENT_MULTI_DISABLED);
                                  if (k != ServerRealm_get_clientsLimit(pointer)) {
                                    ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_ACCEPTED);
                                    aflog(LOG_T_CLIENT, LOG_I_INFO,
                                        "realm[%s]: Client[%s]: pass ok - ACCESS GRANTED",
                                        get_realmname(config, j), get_clientname(pointer, k));
                                    buff[0] = AF_S_LOGIN; /* sending message */
                                    buff[1] = ConnectClient_get_limit(
                                        srClientsTable[k]) >> 8;/* high bits of user number */
                                    buff[2] = ConnectClient_get_limit(
                                        srClientsTable[k]);     /* low bits of user number */
                                    buff[3] = ServerRealm_get_realmType(pointer);	/* type of connection */
                                    SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                                        ConnectClient_get_sslFd(
                                          srClientsTable[k]),
                                        buff, 5);
                                    if ((task = ConnectClient_get_task(srClientsTable[k]))) {
                                      TaskScheduler_removeTask(scheduler, task);
                                      ConnectClient_set_task(srClientsTable[k], NULL);
                                    }
                                    if (ServerRealm_get_maxIdle(pointer)) {
                                      ConnectClient_set_timer(srClientsTable[k],
                                          timeval_create(ServerRealm_get_maxIdle(pointer), 0));
                                      task = Task_new(ConnectClient_get_timerp(srClientsTable[k]),
                                          RCTfunction,
                                          RCTdata_new(config, j, k, 0, RCT_REASON_MAXIDLE, &allset, &wset),
                                          RCTdata_free);
                                      ConnectClient_set_task(srClientsTable[k], task);
                                      TaskScheduler_addTask(scheduler, task);
                                    }
                                    if (ServerRealm_get_basePortOn(pointer) == 1) {
                                      long tmp_val;
                                      char tmp_tab[6];
                                      if (check_long(
                                            UsrCli_get_listenPortName(
                                              srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[k])]),
                                            &tmp_val)) {
                                        aflog(LOG_T_CLIENT, LOG_I_ERR,
                                            "realm[%s]: INVALID listenport - removing Client[%s]",
                                            get_realmname(config, j), get_clientname(pointer, k));
                                        remove_client(pointer, k, &allset, &wset, scheduler);
                                        break;
                                      }
                                      tmp_val = tmp_val%65536;
                                      memset(tmp_tab, 0, 6);
                                      sprintf(tmp_tab, "%d", (int)tmp_val);
                                      ipfam = 0x01;
#ifdef AF_INET6
                                      if (TYPE_IS_IPV4(ServerRealm_get_realmType(pointer))) {
                                        ipfam |= 0x02;
                                      }
                                      else if (TYPE_IS_IPV6(ServerRealm_get_realmType(pointer))) {
                                        ipfam |= 0x04;
                                      }
#endif
                                      while (ip_listen(ConnectClient_get_listenFdp(srClientsTable[k]),
                                            UsrCli_get_listenHostName(srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[k])]) ?
                                            UsrCli_get_listenHostName(srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[k])]) :
                                            ServerRealm_get_hostName(pointer),
                                            tmp_tab, (&len), ipfam)) {
                                        tmp_val = (tmp_val+1)%65536;
                                        memset(tmp_tab, 0, 6);
                                        sprintf(tmp_tab, "%d", (int)tmp_val);
                                      }
                                      ServerRealm_set_addressLength(pointer, len);
                                      FD_SET(ConnectClient_get_listenFd(srClientsTable[k]), &allset);
                                      maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(srClientsTable[k])+1)) ?
                                        maxfdp1 : (ConnectClient_get_listenFd(srClientsTable[k]) + 1);
                                      aflog(LOG_T_CLIENT, LOG_I_INFO,
                                          "realm[%s]: Client[%s]: listenport=%s",
                                          get_realmname(config, j), get_clientname(pointer, k), tmp_tab);
                                    }
                                  }
                                  else {
                                    aflog(LOG_T_CLIENT, LOG_I_WARNING,
                                        "realm[%s]: client limit EXCEEDED", get_realmname(config, j));
                                    buff[0] = AF_S_CANT_OPEN; /* sending message */
                                    SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL,
                                        ConnectClient_get_sslFd(
                                          srClientsTable[k]),
                                        buff, 5);
                                    remove_client(pointer, k, &allset, &wset, scheduler);
                                  }
                                }
                                else if ((ConnectClient_get_state(srClientsTable[k]) ==
                                      CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) {
                                  n = SslFd_get_message(ServerRealm_get_realmType(pointer),
                                      ConnectClient_get_sslFd(
                                        srClientsTable[k]),
                                      buff, length);
                                  buff[n] = 0;
                                  aflog(LOG_T_CLIENT, LOG_I_INFO,
                                      "realm[%s]: Client[%s]: ID received: %s",
                                      get_realmname(config, j), get_clientname(pointer, k), buff);
                                  ConnectClient_set_sClientId(srClientsTable[k], (char*) buff);
                                }
                                else {
                                  aflog(LOG_T_CLIENT, LOG_I_ERR,
                                      "realm[%s]: Client[%s]: Wrong password - CLOSING",
                                      get_realmname(config, j), get_clientname(pointer, k));
                                  buff[0] = AF_S_WRONG; /* sending message */
                                  SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL,
                                      ConnectClient_get_sslFd(
                                        srClientsTable[k]),
                                      buff, 5);
                                  remove_client(pointer, k, &allset, &wset, scheduler);
                                }
                                break;
                              }
            case AF_S_DONT_SEND: {
                                   if ((ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) ||
                                       (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED)) {
                                     aflog(LOG_T_CLIENT, LOG_I_DEBUG,
                                         "realm[%s]: user[%d]: STOP READING",
                                         get_realmname(config, j), get_username(pointer, numofcon));
                                     FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                   }
                                   else {
                                     aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
                                         "realm[%s]: user[%d]: STOP READING - ignored",
                                         get_realmname(config, j), get_username(pointer, numofcon));
                                   }
                                   break;
                                 }
            case AF_S_CAN_SEND: {
                                  if ((ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) ||
                                      (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED)) {
                                    aflog(LOG_T_CLIENT, LOG_I_DEBUG,
                                        "realm[%s]: user[%d]: START READING",
                                        get_realmname(config, j), get_username(pointer, numofcon));
                                    FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset);
                                  }
                                  else {
                                    aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
                                        "realm[%s]: user[%d]: START READING - ignored",
                                        get_realmname(config, j), get_username(pointer, numofcon));
                                  }
                                  break;
                                }
            case AF_S_WRONG: {
                               aflog(LOG_T_CLIENT, LOG_I_ERR,
                                   "realm[%s]: Client[%s]: Wrong message - CLOSING",
                                   get_realmname(config, j), get_clientname(pointer, k));
                               remove_client(pointer, k, &allset, &wset, scheduler);
                               break;
                             }
            case AF_S_ADMIN_LOGIN: {
                                     if ((ConnectClient_get_state(srClientsTable[k]) ==
                                           CONNECTCLIENT_STATE_AUTHORIZING) &&
                                         (numofcon == (ServerRealm_get_password(pointer)[0]*256 + ServerRealm_get_password(pointer)[1])) &&
                                         (length == (ServerRealm_get_password(pointer)[2]*256 + ServerRealm_get_password(pointer)[3]))) {
                                       aflog(LOG_T_MANAGE, LOG_I_INFO,
                                           "realm[%s]: Client[%s]: NEW remote admin -- pass OK",
                                           get_realmname(config, j), get_clientname(pointer, k));
                                       for (l = 0; l < ServerRealm_get_raClientsLimit(pointer); ++l) {
                                         if (ConnectClient_get_state(srRaClientsTable[l]) ==
                                             CONNECTCLIENT_STATE_FREE) {
                                           SslFd_set_fd(
                                               ConnectClient_get_sslFd(srRaClientsTable[l]),
                                               SslFd_get_fd(
                                                 ConnectClient_get_sslFd(srClientsTable[k])));
                                           ConnectClient_set_connectTime(
                                               srRaClientsTable[l],
                                               ConnectClient_get_connectTime(srClientsTable[k]));
                                           ConnectClient_set_lastActivity(
                                               srRaClientsTable[l],
                                               ConnectClient_get_lastActivity(srClientsTable[k]));
#ifdef HAVE_LIBPTHREAD
                                           ConnectClient_set_tunnelType(
                                               srRaClientsTable[l],
                                               ConnectClient_get_tunnelType(srClientsTable[k]));
#endif
                                           ConnectClient_set_clientId(
                                               srRaClientsTable[l],
                                               ConnectClient_get_clientId(srClientsTable[k]));
                                           ConnectClient_set_nameBuf(
                                               srRaClientsTable[l],
                                               ConnectClient_get_nameBuf(srClientsTable[k]));
                                           ConnectClient_set_portBuf(
                                               srRaClientsTable[l],
                                               ConnectClient_get_portBuf(srClientsTable[k]));
                                           tmp_ssl = SslFd_get_ssl(
                                               ConnectClient_get_sslFd(srRaClientsTable[l]));
                                           SslFd_set_ssl_nf(
                                               ConnectClient_get_sslFd(srRaClientsTable[l]),
                                               SslFd_get_ssl(
                                                 ConnectClient_get_sslFd(srClientsTable[k])));
                                           SslFd_set_ssl_nf(
                                               ConnectClient_get_sslFd(srClientsTable[k]),
                                               tmp_ssl);
                                           ConnectClient_set_state(
                                               srClientsTable[k],
                                               CONNECTCLIENT_STATE_FREE);
                                           break;
                                         }
                                       }
                                       if (l != ServerRealm_get_raClientsLimit(pointer)) {
                                         ConnectClient_set_state(
                                             srRaClientsTable[l],
                                             CONNECTCLIENT_STATE_ACCEPTED);
                                         ServerRealm_increase_connectedRaClients(pointer);
                                         if ((task = ConnectClient_get_task(srClientsTable[k]))) {
                                           TaskScheduler_removeTask(scheduler, task);
                                           ConnectClient_set_task(srClientsTable[k], NULL);
                                         }
                                         sprintf((char*) &buff[5], AF_VER("AFSERVER"));
                                         n = strlen((char*) &buff[5]);
                                         buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
                                         buff[1] = ServerRealm_get_realmType(pointer);	/* type of connection */
                                         buff[2] = AF_RA_UNDEFINED;
                                         buff[3] = n >> 8; /* high bits of message length */
                                         buff[4] = n;      /* low bits of message length */
                                         SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL,
                                             ConnectClient_get_sslFd(
                                               srRaClientsTable[l]),
                                             buff, n+5);
                                       }
                                       else {
                                         aflog(LOG_T_MANAGE, LOG_I_WARNING,
                                             "realm[%s]: Client[%s]: remote admin -- limit EXCEEDED",
                                             get_realmname(config, j), get_clientname(pointer, k));
                                         buff[0] = AF_S_CANT_OPEN; /* sending message */
                                         SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                                             ConnectClient_get_sslFd(
                                               srClientsTable[k]),
                                             buff, 5);
                                         remove_client(pointer, k, &allset, &wset, scheduler);
                                       }
                                     }
                                     break;
                                   }
            case AF_S_KEEP_ALIVE: {
                                    aflog(LOG_T_CLIENT, LOG_I_DEBUG,
                                        "realm[%s]: Client[%s]: Keep alive packet",
                                        get_realmname(config, j), get_clientname(pointer, k));
                                    break;
                                  }
            case AF_S_ENABLE_MULTI: {
                                      aflog(LOG_T_CLIENT, LOG_I_INFO,
                                          "realm[%s]: Client[%s]: MULTI enabled: %d",
                                          get_realmname(config, j), get_clientname(pointer, k), buff[1]);
                                      ConnectClient_set_multi(srClientsTable[k], CONNECTCLIENT_MULTI_ENABLED);
                                      break;
                                    }
            default : {
                        aflog(LOG_T_CLIENT, LOG_I_ERR,
                            "realm[%s]: Client[%s]: Unrecognized message - CLOSING",
                            get_realmname(config, j), get_clientname(pointer, k));
                        remove_client(pointer, k, &allset, &wset, scheduler);
                      }
          }
        }
      /* ------------------------------------ */
      for (k = 0; k < ServerRealm_get_raClientsLimit(pointer); ++k)
        if ((ConnectClient_get_state(srRaClientsTable[k]) > CONNECTCLIENT_STATE_FREE) &&
            (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &rset))) {
          if (ConnectClient_get_state(srRaClientsTable[k]) == CONNECTCLIENT_STATE_CONNECTING) {
            make_ssl_initialize(ConnectClient_get_sslFd(srRaClientsTable[k]));
            aflog(LOG_T_MANAGE, LOG_I_DDEBUG,
                "realm[%s]: new Client[%s] (ra): SSL_accept",
                get_realmname(config, j), get_raclientname(pointer, k));
            switch (make_ssl_accept(ConnectClient_get_sslFd(srRaClientsTable[k]))) {
              case 2: {
                        close (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])));
                        FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &allset);
                        SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[k])));
                        ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_FREE);
                        if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
                          TaskScheduler_removeTask(scheduler, task);
                          ConnectClient_set_task(srRaClientsTable[k], NULL);
                        }
                        ServerRealm_decrease_connectedClients(pointer);
                        aflog(LOG_T_MANAGE, LOG_I_ERR,
                            "realm[%s]: new Client[%s] (ra): DENIED by SSL_accept",
                            get_realmname(config, j), get_raclientname(pointer, k));
                      }
              case 1: {
                        continue;
                      }
              default: {
                         aflog(LOG_T_MANAGE, LOG_I_DEBUG,
                             "realm[%s]: new Client[%s] (ra): ACCEPTED by SSL_accept",
                             get_realmname(config, j), get_raclientname(pointer, k));
                         ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_AUTHORIZING);
                         continue;
                       }
            }
          }
          aflog(LOG_T_MANAGE, LOG_I_DDEBUG,
              "realm[%s]: Client[%s] (ra): commfd: FD_ISSET",
              get_realmname(config, j), get_raclientname(pointer, k));
          n = SslFd_get_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
              ConnectClient_get_sslFd(
                srRaClientsTable[k]),
              buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srRaClientsTable[k])));
          if (n == -1) {
            if (errno == EAGAIN) {
              aflog(LOG_T_MANAGE, LOG_I_DDEBUG,
                  "realm[%s]: Client[%s] (ra): commfd: EAGAIN",
                  get_realmname(config, j), get_raclientname(pointer, k));
              continue;
            }
            else {
              aflog(LOG_T_MANAGE, LOG_I_ERR,
                  "realm[%s]: Client[%s] (ra): commfd: ERROR: %d",
                  get_realmname(config, j), get_raclientname(pointer, k), errno);
              n = 0;
            }
          }
          else if (n != 5) {
            if (n != 0) {
              aflog(LOG_T_MANAGE, LOG_I_WARNING,
                  "realm[%s]: Client[%s] (ra): header length = %d --> buffering",
                  get_realmname(config, j), get_raclientname(pointer, k), n);
              HeaderBuffer_store(ConnectClient_get_header(srRaClientsTable[k]), buff, n);
              if (HeaderBuffer_to_read(ConnectClient_get_header(srRaClientsTable[k])) == 0) {
                HeaderBuffer_restore(ConnectClient_get_header(srRaClientsTable[k]), buff);
                n = 5;
              }
              else {
                continue;
              }
            }
          }
          if (n==0) { 
            remove_raclient(pointer, k, &allset, &wset, scheduler);
            aflog(LOG_T_MANAGE, LOG_I_INFO,
                "realm[%s]: Client[%s] (ra): commfd: CLOSED",
                get_realmname(config, j), get_raclientname(pointer, k));
            continue;
          }

          numofcon = buff[1];
          numofcon = numofcon << 8;
          numofcon += buff[2]; /* this is id of user */
          length = buff[3];
          length = length << 8;
          length += buff[4]; /* this is length of message */ 

          if (ConnectClient_get_state(srRaClientsTable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) {
            aflog(LOG_T_MANAGE, LOG_I_WARNING,
                "realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring",
                get_realmname(config, j), get_raclientname(pointer, k));
            continue;
          }
          if ((ConnectClient_get_state(srRaClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) &&
              (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
            buff[0] = AF_S_WRONG;
          }
          
          time(&now);
          ConnectClient_set_lastActivity(srRaClientsTable[k], now);

          switch (buff[0]) {
            case AF_S_LOGIN : {
                                if ((ConnectClient_get_state(srRaClientsTable[k]) == 
                                      CONNECTCLIENT_STATE_AUTHORIZING) &&
                                    (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) &&
                                    (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) {
                                  ConnectClient_set_multi(srRaClientsTable[k], CONNECTCLIENT_MULTI_DISABLED);
                                  for (l = 0; l < ServerRealm_get_clientsLimit(pointer); ++l) {
                                    if (ConnectClient_get_state(srClientsTable[l]) ==
                                        CONNECTCLIENT_STATE_FREE) {
                                      aflog(LOG_T_MANAGE | LOG_T_CLIENT, LOG_I_INFO,
                                          "realm[%s]: Client[%s] (ra) --> Client[%s]",
                                          get_realmname(config, j),
                                          get_raclientname(pointer, k), get_clientname(pointer, l));
                                      SslFd_set_fd(
                                          ConnectClient_get_sslFd(srClientsTable[l]),
                                          SslFd_get_fd(
                                            ConnectClient_get_sslFd(srRaClientsTable[k])));
                                      ConnectClient_set_connectTime(
                                          srClientsTable[l],
                                          ConnectClient_get_connectTime(srRaClientsTable[k]));
                                      ConnectClient_set_lastActivity(
                                          srClientsTable[l],
                                          ConnectClient_get_lastActivity(srRaClientsTable[k]));
#ifdef HAVE_LIBPTHREAD
                                      ConnectClient_set_tunnelType(
                                          srClientsTable[l],
                                          ConnectClient_get_tunnelType(srRaClientsTable[k]));
#endif
                                      ConnectClient_set_clientId(
                                          srClientsTable[l],
                                          ConnectClient_get_clientId(srRaClientsTable[k]));
                                      ConnectClient_set_nameBuf(
                                          srClientsTable[l],
                                          ConnectClient_get_nameBuf(srRaClientsTable[k]));
                                      ConnectClient_set_portBuf(
                                          srClientsTable[l],
                                          ConnectClient_get_portBuf(srRaClientsTable[k]));
                                      tmp_ssl = SslFd_get_ssl(
                                          ConnectClient_get_sslFd(srClientsTable[l]));
                                      SslFd_set_ssl_nf(
                                          ConnectClient_get_sslFd(srClientsTable[l]),
                                          SslFd_get_ssl(
                                            ConnectClient_get_sslFd(srRaClientsTable[k])));
                                      SslFd_set_ssl_nf(
                                          ConnectClient_get_sslFd(srRaClientsTable[k]),
                                          tmp_ssl);
                                      ConnectClient_set_usrCliPair(
                                          srClientsTable[l],
                                          ConnectClient_get_usrCliPair(srRaClientsTable[k]));
                                      ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_FREE);
                                      break;
                                    }
                                  }
                                  if (l != ServerRealm_get_clientsLimit(pointer)) {
                                    ConnectClient_set_state(srClientsTable[l], CONNECTCLIENT_STATE_ACCEPTED);
                                    aflog(LOG_T_CLIENT, LOG_I_INFO,
                                        "realm[%s]: Client[%s]: pass ok - ACCESS GRANTED",
                                        get_realmname(config, j), get_clientname(pointer, l));
                                    buff[0] = AF_S_LOGIN; /* sending message */
                                    buff[1] = ConnectClient_get_limit(
                                        srClientsTable[l]) >> 8;/* high bits of user number */
                                    buff[2] = ConnectClient_get_limit(
                                        srClientsTable[l]);     /* low bits of user number */
                                    buff[3] = ServerRealm_get_realmType(pointer);	/* type of connection */
                                    SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                                        ConnectClient_get_sslFd(
                                          srClientsTable[l]),
                                        buff, 5);
                                    if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
                                      TaskScheduler_removeTask(scheduler, task);
                                      ConnectClient_set_task(srRaClientsTable[k], NULL);
                                    }
                                    if (ServerRealm_get_maxIdle(pointer)) {
                                      ConnectClient_set_timer(srClientsTable[l],
                                          timeval_create(ServerRealm_get_maxIdle(pointer), 0));
                                      task = Task_new(ConnectClient_get_timerp(srClientsTable[l]),
                                          RCTfunction,
                                          RCTdata_new(config, j, l, 0, RCT_REASON_MAXIDLE, &allset, &wset),
                                          RCTdata_free);
                                      ConnectClient_set_task(srClientsTable[l], task);
                                      TaskScheduler_addTask(scheduler, task);
                                    }
                                    if (ServerRealm_get_basePortOn(pointer) == 1) {
                                      long tmp_val;
                                      char tmp_tab[6];
                                      if (check_long(
                                            UsrCli_get_listenPortName(
                                              srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[l])]),
                                            &tmp_val)) {
                                        aflog(LOG_T_CLIENT, LOG_I_ERR,
                                            "realm[%s]: INVALID listenport - removing Client[%s]",
                                            get_realmname(config, j), get_clientname(pointer, l));
                                        remove_client(pointer, l, &allset, &wset, scheduler);
                                        break;
                                      }
                                      tmp_val = tmp_val%65536;
                                      memset(tmp_tab, 0, 6);
                                      sprintf(tmp_tab, "%d", (int)tmp_val);
                                      ipfam = 0x01;
#ifdef AF_INET6
                                      if (TYPE_IS_IPV4(ServerRealm_get_realmType(pointer))) {
                                        ipfam |= 0x02;
                                      }
                                      else if (TYPE_IS_IPV6(ServerRealm_get_realmType(pointer))) {
                                        ipfam |= 0x04;
                                      }
#endif
                                      while (ip_listen(ConnectClient_get_listenFdp(srClientsTable[l]),
                                            UsrCli_get_listenHostName(srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[l])]) ?
                                            UsrCli_get_listenHostName(srUsersClientsTable[
                                              ConnectClient_get_usrCliPair(srClientsTable[l])]) :
                                            ServerRealm_get_hostName(pointer),
                                            tmp_tab, (&len), ipfam)) {
                                        tmp_val = (tmp_val+1)%65536;
                                        memset(tmp_tab, 0, 6);
                                        sprintf(tmp_tab, "%d", (int)tmp_val);
                                      }
                                      ServerRealm_set_addressLength(pointer, len);
                                      FD_SET(ConnectClient_get_listenFd(srClientsTable[l]), &allset);
                                      maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(srClientsTable[l])+1)) ?
                                        maxfdp1 : (ConnectClient_get_listenFd(srClientsTable[l])+1);
                                      aflog(LOG_T_CLIENT, LOG_I_INFO,
                                          "realm[%s]: Client[%s]: listenport=%s",
                                          get_realmname(config, j), get_clientname(pointer, l), tmp_tab);
                                    }
                                  }
                                  else {
                                    aflog(LOG_T_CLIENT, LOG_I_WARNING,
                                        "realm[%s]: client limit EXCEEDED", get_realmname(config, j));
                                    buff[0] = AF_S_CANT_OPEN; /* sending message */
                                    SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                                        ConnectClient_get_sslFd(
                                          srRaClientsTable[k]),
                                        buff, 5);
                                    remove_raclient(pointer, k, &allset, &wset, scheduler);
                                  }
                                }
                                else if ((ConnectClient_get_state(srRaClientsTable[k]) ==
                                      CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) {
                                  n = SslFd_get_message(ServerRealm_get_realmType(pointer),
                                      ConnectClient_get_sslFd(
                                        srRaClientsTable[k]),
                                      buff, length);
                                  buff[n] = 0;
                                  aflog(LOG_T_MANAGE, LOG_I_INFO,
                                      "realm[%s]: Client[%s] (ra): ID received: %s",
                                      get_realmname(config, j), get_raclientname(pointer, k), buff);
                                  ConnectClient_set_sClientId(srRaClientsTable[k], (char*) buff);
                                }
                                else {
                                  aflog(LOG_T_MANAGE, LOG_I_ERR,
                                      "realm[%s]: Client[%s] (ra): Wrong password - CLOSING",
                                      get_realmname(config, j), get_raclientname(pointer, k));
                                  remove_raclient(pointer, k, &allset, &wset, scheduler);
                                }
                                break;
                              }
            case AF_S_WRONG: {
                               aflog(LOG_T_MANAGE, LOG_I_ERR,
                                   "realm[%s]: Client[%s] (ra): Wrong message - CLOSING",
                                   get_realmname(config, j), get_raclientname(pointer, k));
                               remove_raclient(pointer, k, &allset, &wset, scheduler);
                               break;
                             }
            case AF_S_ADMIN_LOGIN: {
                                     if ((ConnectClient_get_state(srRaClientsTable[k]) ==
                                           CONNECTCLIENT_STATE_AUTHORIZING) &&
                                         (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) &&
                                         (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) {
                                       aflog(LOG_T_MANAGE, LOG_I_INFO,
                                           "realm[%s]: Client[%s] (ra): NEW remote admin -- pass OK",
                                           get_realmname(config, j), get_raclientname(pointer, k));
                                       ConnectClient_set_state(
                                           srRaClientsTable[k],
                                           CONNECTCLIENT_STATE_ACCEPTED);
                                       ServerRealm_increase_connectedRaClients(pointer);
                                       if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
                                         TaskScheduler_removeTask(scheduler, task);
                                         ConnectClient_set_task(srRaClientsTable[k], NULL);
                                       }
                                       sprintf((char*) &buff[5], AF_VER("AFSERVER"));
                                       n = strlen((char*) &buff[5]);
                                       buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
                                       buff[1] = ServerRealm_get_realmType(pointer);	/* type of connection */
                                       buff[2] = AF_RA_UNDEFINED;
                                       buff[3] = n >> 8; /* high bits of message length */
                                       buff[4] = n;      /* low bits of message length */
                                       SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB,
                                           ConnectClient_get_sslFd(
                                             srRaClientsTable[k]),
                                           buff, n+5);
                                     }
                                     break;
                                   }
            case AF_S_ADMIN_CMD: {
                                   if (ConnectClient_get_state(srRaClientsTable[k]) ==
                                       CONNECTCLIENT_STATE_ACCEPTED) {
                                     if ((n = serve_admin(config, j, k, buff))) {
                                       if (n == 1) {
                                         aflog(LOG_T_MANAGE, LOG_I_NOTICE,
                                             "realm[%s]: Client[%s] (ra): remote admin -- closing",
                                             get_realmname(config, j), get_raclientname(pointer, k));
                                         remove_raclient(pointer, k, &allset, &wset, scheduler);
                                       }
                                       else {
                                         for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) {
                                           srClientsTable = ServerRealm_get_clientsTable(scRealmsTable[i]);
                                           l = get_clientnumber(scRealmsTable[i], n-2);
                                           if (l != -1) {
                                             aflog(LOG_T_MANAGE, LOG_I_NOTICE,
                                                 "realm[%s]: Client[%s] (ra): remote admin: KICKING realm[%s]: Client[%s]",
                                                 get_realmname(config, j), get_raclientname(pointer, k),
                                                 get_realmname(config, i),
                                                 get_clientname(scRealmsTable[i], l));
                                             buff[0] = AF_S_CLOSING; /* closing */
                                             SslFd_send_message(ServerRealm_get_realmType(scRealmsTable[i]),
                                                 ConnectClient_get_sslFd(
                                                   srClientsTable[l]),
                                                 buff, 5);
                                             time(&now);
                                             aflog(LOG_T_CLIENT, LOG_I_NOTICE,
                                                 "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s",
                                                 get_realmname(config, j),
                                                 get_clientname(scRealmsTable[i], l),
                                                 ConnectClient_get_nameBuf(srClientsTable[l]),
                                                 ConnectClient_get_portBuf(srClientsTable[l]),
                                                 timeperiod(now - ConnectClient_get_connectTime(
                                                     srClientsTable[l])));
                                             if (ServerRealm_get_auditOn(scRealmsTable[i])) {
                                               while (AuditList_get_first(
                                                     ConnectClient_get_auditList(
                                                       srClientsTable[l]))) {
                                                 aflog(LOG_T_CLIENT, LOG_I_NOTICE,
                                                     "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s",
                                                     AuditListNode_get_userId(
                                                       AuditList_get_first(
                                                         ConnectClient_get_auditList(
                                                           srClientsTable[l]))),
                                                     AuditListNode_get_nameBuf(
                                                       AuditList_get_first(
                                                         ConnectClient_get_auditList(
                                                           srClientsTable[l]))),
                                                     AuditListNode_get_portBuf(
                                                       AuditList_get_first(
                                                         ConnectClient_get_auditList(
                                                           srClientsTable[l]))),
                                                     localdate(
                                                       AuditListNode_get_connectTimep(
                                                         AuditList_get_first(
                                                           ConnectClient_get_auditList(
                                                             srClientsTable[l])))),
                                                     timeperiod(
                                                       AuditListNode_get_duration(
                                                         AuditList_get_first(
                                                           ConnectClient_get_auditList(
                                                             srClientsTable[l])))));
                                                     AuditList_delete_first(
                                                         ConnectClient_get_auditList(
                                                           srClientsTable[l]));
                                               }
                                             }
                                             remove_client(scRealmsTable[i], l,
                                                 &allset, &wset, scheduler);
                                             break;
                                           }
                                         }
                                       }
                                     }
                                   }
                                   else {
                                     aflog(LOG_T_MANAGE, LOG_I_ERR,
                                         "realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION",
                                         get_realmname(config, j), get_raclientname(pointer, k));
                                     remove_raclient(pointer, k, &allset, &wset, scheduler);
                                   }
                                   break;
                                 }
            case AF_S_KEEP_ALIVE: {
                                    aflog(LOG_T_MANAGE, LOG_I_DEBUG,
                                        "realm[%s]: Client[%s] (ra): Keep alive packet",
                                        get_realmname(config, j), get_raclientname(pointer, k));
                                    break;
                                  }
            default : {
                        aflog(LOG_T_MANAGE, LOG_I_ERR,
                            "realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING",
                            get_realmname(config, j), get_raclientname(pointer, k));
                        remove_raclient(pointer, k, &allset, &wset, scheduler);
                      }
          }
        }
      /* ------------------------------------ */    
      for (l = 0; l < ServerRealm_get_userClientPairs(pointer); ++l) {
        if (FD_ISSET(UsrCli_get_manageFd(srUsersClientsTable[l]), &rset)) {
          
          aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
              "realm[%s]: managefd: FD_ISSET", get_realmname(config, j));
          len = ServerRealm_get_addressLength(pointer);
#ifdef HAVE_LIBPTHREAD
          sent = get_new_socket(UsrCli_get_manageFd(srUsersClientsTable[l]),
              ServerRealm_get_tunnelType(pointer),ServerRealm_get_clientAddress(pointer), &len, &tunneltype); 
#else
          sent = accept(UsrCli_get_manageFd(srUsersClientsTable[l]), ServerRealm_get_clientAddress(pointer), &len);
#endif
          if (sent == -1) {
            if (errno == EAGAIN) {
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: managefd: FD_ISSET --> EAGAIN", get_realmname(config, j));
            }
            else {
              aflog(LOG_T_USER, LOG_I_DDEBUG,
                  "realm[%s]: managefd: FD_ISSET --> errno=%d", get_realmname(config, j), errno);
            }
            break;
          }
          flags = fcntl(sent, F_GETFL, 0);
          fcntl(sent, F_SETFL, flags | O_NONBLOCK);
          for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) {
            if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_FREE) {
              ConnectClient_set_clientId(srClientsTable[k], ServerRealm_get_clientsCounter(pointer));
              ServerRealm_increase_clientsCounter(pointer);
              aflog(LOG_T_CLIENT, LOG_I_INFO,
                  "realm[%s]: new Client[%s]: CONNECTING",
                  get_realmname(config, j), get_clientname(pointer, k));
              SslFd_set_fd(ConnectClient_get_sslFd(srClientsTable[k]), sent);
              ConnectClient_set_usrCliPair(srClientsTable[k], l);
              time(&now);
              ConnectClient_set_connectTime(srClientsTable[k], now);
              ConnectClient_set_lastActivity(srClientsTable[k], now);
#ifdef HAVE_LIBPTHREAD
              ConnectClient_set_tunnelType(srClientsTable[k], tunneltype);
#endif
              aflog(LOG_T_CLIENT, LOG_I_INFO,
                  "realm[%s]: new Client[%s] IP:%s", get_realmname(config, j), get_clientname(pointer, k),
                  sock_ntop(ServerRealm_get_clientAddress(pointer), len, ConnectClient_get_nameBuf(srClientsTable[k]),
                    ConnectClient_get_portBuf(srClientsTable[k]), ServerRealm_get_dnsLookupsOn(pointer)));
              FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &allset);
              maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])) + 1)) ?
                maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])) + 1);
              ServerRealm_increase_connectedClients(pointer);
              ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_timeout(pointer), 0));
              task = Task_new(ConnectClient_get_timerp(srClientsTable[k]),
                  RCTfunction,
                  RCTdata_new(config, j, k, 0, RCT_REASON_TIMEOUT, &allset, &wset),
                  RCTdata_free);
              ConnectClient_set_task(srClientsTable[k], task);
              TaskScheduler_addTask(scheduler, task);
              ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_CONNECTING);
              break;
            }
          }
          if (k == ServerRealm_get_clientsLimit(pointer)) {
            for (k = 0; k < ServerRealm_get_raClientsLimit(pointer); ++k) {
              if (ConnectClient_get_state(srRaClientsTable[k]) ==
                  CONNECTCLIENT_STATE_FREE) {
                ConnectClient_set_clientId(srRaClientsTable[k], ServerRealm_get_clientsCounter(pointer));
                ServerRealm_increase_clientsCounter(pointer);
                aflog(LOG_T_MANAGE, LOG_I_INFO,
                    "realm[%s]: new Client[%s] (ra): CONNECTING",
                    get_realmname(config, j), get_raclientname(pointer, k));
                SslFd_set_fd(ConnectClient_get_sslFd(srRaClientsTable[k]), sent);
                ConnectClient_set_usrCliPair(srRaClientsTable[k], l);
                time(&now);
                ConnectClient_set_connectTime(srRaClientsTable[k], now);
                ConnectClient_set_lastActivity(srRaClientsTable[k], now);
#ifdef HAVE_LIBPTHREAD
                ConnectClient_set_tunnelType(srRaClientsTable[k], tunneltype);
#endif
                aflog(LOG_T_MANAGE, LOG_I_INFO,
                    "realm[%s]: new Client[%s] (ra) IP:%s",
                    get_realmname(config, j), get_raclientname(pointer, k),
                    sock_ntop(ServerRealm_get_clientAddress(pointer), len,
                      ConnectClient_get_nameBuf(srRaClientsTable[k]),
                      ConnectClient_get_portBuf(srRaClientsTable[k]),
                      ServerRealm_get_dnsLookupsOn(pointer)));
                FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &allset);
                maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])) + 1)) ?
                  maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])) + 1);
                ServerRealm_increase_connectedClients(pointer);
                ConnectClient_set_timer(srRaClientsTable[k],
                    timeval_create(ServerRealm_get_timeout(pointer), 0));
                task = Task_new(ConnectClient_get_timerp(srRaClientsTable[k]),
                    RCTfunction,
                    RCTdata_new(config, j, k, 1, RCT_REASON_TIMEOUT, &allset, &wset),
                    RCTdata_free);
                ConnectClient_set_task(srRaClientsTable[k], task);
                TaskScheduler_addTask(scheduler, task);
                ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_CONNECTING);
                break;
              }
            }
            if (k == ServerRealm_get_raClientsLimit(pointer)) {
              aflog(LOG_T_CLIENT | LOG_T_MANAGE, LOG_I_WARNING,
                  "realm[%s]: client limit EXCEEDED", get_realmname(config, j));
              close(sent);
            }
          }
          break;
        }
      }
    } /* realms loop */
  }
}
