/*
 * hub.c:
 *
 * Copyright (c) 2000 James McKenzie <james@fishsoup.dhs.org>.
 * All rights reserved.
 *
 * $Log: hub.c,v $
 * Revision 1.5  2000/11/23 23:45:16  root
 * #
 *
 * Revision 1.4  2000/02/21 04:13:33  root
 * #
 *
 * Revision 1.3  2000/02/21 04:11:26  root
 * #
 *
 * Revision 1.2  2000/02/21 04:01:01  root
 * #
 *
 * Revision 1.1  2000/02/21 02:53:46  root
 * #
 *
 *
 */

static char rcsid[] = "$Id: hub.c,v 1.5 2000/11/23 23:45:16 root Exp $";

#include "hifimsg.h"
#include "hifimsg_private.h"

#include <linux/limits.h>


static void
hangup (Connexion c)
{
  int w = getdtablesize ();
  int *used;
  int len;
  Connexion p;

  if (w < 0)
    w = OPEN_MAX;

  used = (int *) malloc (sizeof (int) * w);
  bzero (used, sizeof (int) * w);

  p = c;

  while (p)
    {
      if (p->fd)
        used[p->fd]++;
      if (p->fd2)
        used[p->fd2]++;

      p = p->next;
    }

  for (len = 0; len < w; ++len)
    {
      if (!used[len])
        close (len);
    }

  free (used);

  hifimsg_disinherit ();


}
static void
hub (Connexion c)
{
  Connexion p, q;
  int w = getdtablesize ();
  unsigned char *buf;
  fd_set read_fds;
  int len;

  buf = malloc (HIFIMSG_MAXLEN);

  while (1)
    {
      FD_ZERO (&read_fds);

      p = c;
      while (p)
        {
          FD_SET (p->fd, &read_fds);
          p = p->next;
        }

      select (w, &read_fds, 0, 0, NULL);

      p = c;
      while (p)
        {
          if (FD_ISSET (p->fd, &read_fds))
            {
              len = (p->recv) (p->h, buf, HIFIMSG_MAXLEN);


//              if ((len > 2) && (buf[0]=='H') && (buf[1]=='i'))
              if (len > 0)
                {
//New message ship out...
                  q = c;
                  while (q)
                    {
                      if (q != p)
                        {
                          (q->send) (q->h, buf, len);
                        }
                      q = q->next;
                    }
                }

            }
          p = p->next;
        }


    }

}

void
hifimsg_spawn_hub (void)
{
  Connexion c = NULL, d;

//Avoid a race condition start the server
  //sockets before returning.
  c = hifimsg_udp_server_open (c);
  c = hifimsg_irda_server_open (c);
  c = hifimsg_unix_server_open (c);

  switch (fork ())
    {
    case 0:
      hangup (c);
      hub (c);
      break;
    case -1:
      hifimsg_moan ("fork failed");
      break;
    }


//Release our copy of server fds
  while (c)
    {
      d = c->next;
      (c->close) (c->h);
      free (c);
      c = d;
    }

}

void
hifimsg_fg_hub (void)
{
  Connexion c = NULL;

  c = hifimsg_udp_server_open (c);
  c = hifimsg_irda_server_open (c);
  c = hifimsg_unix_server_open (c);

  hub (c);


}
