/**********************************************************************
**
** route.c - handles the sending of routing message to agents.
**
**********************************************************************/

/*
 * $Log: route.c,v $
 * Revision 1.5  1991/11/15  19:44:20  jplevyak
 * Add definition for FALSE (removed indirect dependacy on dtmint.h).
 *
 * Revision 1.4  1991/10/29  17:17:00  jplevyak
 * Modified establishAllRoutes to return TRUE/FALSE as to whether it
 * has made all the connections.
 *
 * Revision 1.3  1991/10/17  13:03:15  jplevyak
 * Changed error message on not finding output port to debug message.
 *
 * Revision 1.2  1991/10/16  23:23:14  jplevyak
 * Added some debugging statements.
 *
 * Revision 1.1  1991/10/11  23:16:07  jefft
 * Initial revision
 *
 */

#include	<stdio.h>
#include	<string.h>
#include	<sys/types.h>
#include	<dtm.h>

#include	"route.h"
#include	"debug.h"

#define		FALSE		0

extern int	server_fd;
extern char	*getPortAddress();


static ROUTE	*listhead = NULL;



static int send_routing(ptr)
  ROUTE	*ptr;
{
  char	*out, *in[64];
  char	**cpptr;
  int	count = 0;


  if ((out = getPortAddress(ptr->outport)) == NULL)  {
    DBGMSG1( "send_routing: could not locate port '%s'\n", ptr->outport);
    return 0;
    }
  else
    out = strdup(out);


  cpptr = ptr->destination;
  while (*cpptr != NULL)
    if ((in[count] = getPortAddress(*cpptr++)) == NULL) {
      DBGMSG1("send_routing: could not locate port '%s'\n", *(cpptr-1));
      return 0;
      }
    else  {
      in[count] = strdup(in[count]);
      count += 1;
      }


  DTMsendRoute(server_fd, out, count, in, 0, 0);
  return 1;
}


static int list_count(list)
  char	**list;
{
  int	count = 0;

  while (*list++ != NULL)
    count += 1;

  /* including the NULL */
  return ++count;
}


ROUTE *makeRouting(src, dstlist)
  char	*src, **dstlist;
{
  int	count;
  ROUTE	*ptr;

  if ((ptr = (ROUTE *)malloc(sizeof (ROUTE))) == NULL)  {
    fprintf(stderr, "Error: out of memory!\n");
    exit(-1);
    }

  ptr->outport = strdup(src);

  count = list_count(dstlist);
  if ((ptr->destination = (char **)malloc(count * sizeof (char *))) == NULL) {
    fprintf(stderr, "Error: out of memory\n");
    exit(-1);
    }
  memcpy(ptr->destination, dstlist, count * sizeof (char *));

  ptr->status = INITIAL;

  ptr->next = listhead;
  listhead = ptr;

  ptr->status = (send_routing(ptr)) ? PENDING : INITIAL;

  return ptr;
}


void addRoute(src, dst)
  char	*src, *dst;
{
  char	*dstlist[2];

  dstlist[0] = dst;
  dstlist[1] = NULL;

  makeRouting(src, dstlist);
}

void deleteRoute(src, dst)
  char	*src, *dst;
{
  char	*dstlist[2];

  dstlist[0] = dst;
  dstlist[1] = NULL;

}

/*
	establishAllRoutes

	returns: done - when each inport has been mapped to 
		its outports.
*/
int establishAllRoutes(fd)
  int           fd;
{
  int           i, count;
  char          **cpptr;
  char          *address[32];
  ROUTE			*ptr = listhead;
  int			done = 1;


  while (ptr != NULL)  {

    if (ptr->status == INITIAL)  {
      count = 0;

      /* lookup outport address */
      if ((address[count++] = getPortAddress(ptr->outport)) == NULL)
        goto ENDOFLOOP;

      /* lookup one or more inport addresses */
      cpptr = ptr->destination;
      while (*cpptr != NULL)
        if ((address[count++] = getPortAddress(*(cpptr++))) == NULL)
          goto ENDOFLOOP;

      /* everything should be OK, shoot the message */
      DTMsendRoute(fd, address[0], count-1, &address[1], 0, 0);

      /* mark the route as pending */
      ptr->status = PENDING;
      }
	
    ptr = ptr->next;
	continue;	

 ENDOFLOOP:
	done = FALSE;
    ptr = ptr->next;
    }
  return done;
}


/*
 * backgroundRouting - this is work procedure that sends routing
 *	message for newly resolved port address.
 */
int backgroundRouting(unused)
  caddr_t	unused;
{
  ROUTE	*ptr = listhead;


  while (ptr != NULL)  {
    if (ptr->status == INITIAL)
      send_routing(ptr);
    ptr = ptr->next;
    }

  return 0;
}
