/*****************************************************************************

  POPular -- A POP3 server and proxy for large mail systems

  $Id: pproxy_res.c,v 1.9 2003/11/24 19:23:30 sqrt Exp $

  http://www.remote.org/jochen/mail/popular/

******************************************************************************

  Copyright (C) 1999-2003  Jochen Topf <jochen@remote.org>

  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

*****************************************************************************/

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include "popular.h"
#include "pproxy.h"


/* space for saving all the virtual server descriptions */
static struct virt_serv vserv[MAX_VIRT_SERV];

/* space for saving all the backend descriptions */
static struct backend backend[MAX_BACKEND];


/*****************************************************************************

  void flush_backend(void)

  Mark all backend slots as free.

*****************************************************************************/
void
flush_backend(void)
{
  int n;
  for (n=0; n < MAX_BACKEND; n++) {
    backend[n].state = bstFree;
  } 
}


/*****************************************************************************

  char *list_backend(void)

  List all backend ids. Returns char pointer to static buffer.

*****************************************************************************/
char *
list_backend(void)
{
  static char buf[MAX_BACKEND * (MAXLEN_ID + 1)];
  int n;

  buf[0] = '\0';
  for (n=0; n < MAX_BACKEND; n++) {
    if (backend[n].state == bstFree) continue;
    (void) strlcat(buf, " ", sizeof(buf));
    (void) strlcat(buf, backend[n].id, sizeof(buf));
  }
  return buf;
}


/*****************************************************************************

  struct backend *get_backend(const char *id, int new)

  Find a backend by <id>. Returns pointer to struct backend or NULL. If the
  <new> parameter is true a free backend slot will be returned if there is
  one available.

*****************************************************************************/
struct backend *
get_backend(const char *id, int new)
{
  int n;
  struct backend *b=NULL;

  for (n=0; n < MAX_BACKEND; n++) {
    if (backend[n].state == bstFree) {
      if (!b) b = &(backend[n]);
      continue;
    }
    if (!strcmp(backend[n].id, id)) return &(backend[n]);
  }

  if (new) return b;
  return NULL;
}


/*****************************************************************************

  void flush_virt_serv(int state)

  Mark all virtual server slots as free or offline. All filedescriptors are
  closed.

*****************************************************************************/
void
flush_virt_serv(int state)
{
  int n;
  for (n=0; n < MAX_VIRT_SERV; n++) {
    if (vserv[n].state != vsstFree) {
      (void) close(vserv[n].fd);
      (void) close_listen_port(&(vserv[n].local_addr));
      vserv[n].state = state;
    }
  } 
}


/*****************************************************************************

  char *list_virt_serv(void)

  List all virtual server ids. Returns char pointer to static memory.

*****************************************************************************/
char *
list_virt_serv(void)
{
  static char buf[MAX_VIRT_SERV * (MAXLEN_ID + 1)];
  int n;

  buf[0] = '\0';
  for (n=0; n < MAX_VIRT_SERV; n++) {
    if (vserv[n].state == vsstFree) continue;
    (void) strlcat(buf, " ", sizeof(buf));
    (void) strlcat(buf, vserv[n].id, sizeof(buf));
  }
  return buf;
}


/*****************************************************************************

  void fdset_virt_serv(fd_set *fdset)

  Finds all file descriptors of active virtual servers and puts them into
  <fdset>.

****************************************************************************/
void
fdset_virt_serv(fd_set *fdset)
{
  int n;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if ((vserv[n].state == vsstDisabled) ||
	(vserv[n].state == vsstFake) ||
	(vserv[n].state == vsstOnline)) {
      FD_SET(vserv[n].fd, fdset);
    }
  }
}


/*****************************************************************************

  void fd_isset_virt_serv(fd_set *fdset, int maxnewsess)

  Finds all virtual server who's listening file descriptor is in <fdset>
  and calls new_session() for them. Opens no more that <maxnewsess>
  sessions.

****************************************************************************/
void
fd_isset_virt_serv(const fd_set *fdset, int maxnewsess)
{
  int n;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if ((vserv[n].state == vsstDisabled) ||
	(vserv[n].state == vsstFake) ||
	(vserv[n].state == vsstOnline)) {
      if (FD_ISSET(vserv[n].fd, fdset)) {
	new_session(&(vserv[n]));
	maxnewsess--;
	if (maxnewsess <= 0) return;
      }
    }
  }
}


/*****************************************************************************

  struct virt_serv *get_virt_serv(const char *id, int new)

  Find a virt_serv by <id>. Returns pointer to struct virt_serv or NULL. If
  the <new> parameter is true, an empty virt_serv slot will be returned if
  one is available.

*****************************************************************************/
struct virt_serv *
get_virt_serv(const char *id, int new)
{
  int n;
  struct virt_serv *v=NULL;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if (vserv[n].state == vsstFree) {
      if (!v) v = &(vserv[n]);
      continue;
    }
    if (!strcmp(vserv[n].id, id)) return &(vserv[n]);
  }

  if (new) return v;
  return NULL;
}


/*****************************************************************************

  struct virt_serv *find_virt_serv_by_ip(const struct sockaddr_in *sin)

  Find virtual server for given ip/port combination in <sin>. Returns
  pointer to struct virt_serv or NULL if no virtual server was found.

*****************************************************************************/
struct virt_serv *
find_virt_serv_by_ip(const struct sockaddr_in *sin)
{
  int n;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if ((vserv[n].state != vsstFree) &&
        (sin->sin_addr.s_addr == vserv[n].local_addr.sin_addr.s_addr) &&
	(sin->sin_port == vserv[n].local_addr.sin_port)) return &(vserv[n]);
  }

  return NULL;
}


/*****************************************************************************

  struct virt_serv *find_virt_serv_by_namespace(const char *ns)

  Find virtual server for namespace <ns>. Returns pointer to struct virt_serv
  or NULL if no virtual server was found.

*****************************************************************************/
struct virt_serv *
find_virt_serv_by_namespace(const char *ns)
{
  int n;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if ((vserv[n].state != vsstFree) && (! strcmp(vserv[n].namespace, ns)))
      return &(vserv[n]);
  }

  return NULL;
}


/*****************************************************************************

  struct virt_serv *find_virt_serv_by_capa(const struct capa *capa)

  Find first virtual server that uses the capability list <capa>. Returns
  pointer to struct virt_serv or NULL if no virtual server was found.

*****************************************************************************/
struct virt_serv *
find_virt_serv_by_capa(const struct capa *capa)
{
  int n;

  for (n=0; n < MAX_VIRT_SERV; n++) {
    if ((vserv[n].state != vsstFree) && (vserv[n].capa_ptr == capa))
      return &(vserv[n]);
  }

  return NULL;
}


/** THE END *****************************************************************/


syntax highlighted by Code2HTML, v. 0.9.1