DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦7d8a6f60f⟧ TextFile

    Length: 16803 (0x41a3)
    Types: TextFile
    Names: »ch_bind.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Src/submit/ch_bind.c« 

TextFile

/* ch_bind.c - binds reformatting channels to a recipient address */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/ch_bind.c,v 5.0 90/09/20 16:22:53 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/ch_bind.c,v 5.0 90/09/20 16:22:53 pp Exp Locker: pp $
 *
 * $Log:	ch_bind.c,v $
 * Revision 5.0  90/09/20  16:22:53  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "head.h"
#include "q.h"
#include "ch_bind.h"


extern CHAN             *ch_inbound;   
extern Q_struct         Qstruct;
extern void		err_abrt();
extern LIST_BPT		*bodies_all;


/* -- static variables -- */
static FILTER		*filterlist = NULL;
static TYPES		*typelist;
static MAT		*mainmatrix;
static int		matsize;
static FLAT		*flattenlist = NULL, *unflatlist = NULL;


/* -- local routines -- */
int			ch_bind();
void			fmt_init();

static FILTER		*getfilter();
static FILTER		*name2filter();
static FLAT		*add2flatlist();
static FLAT		*flttype2ptr();
static LIST		*additem();
static LIST		*copylist();
static LIST		*getitem();
static LIST		*inslist();
static MAT		*initmat();
static TYPES		*addchantypes();
static TYPES		*name2type();
static int		isinlist();
static void		addmat();
static void		do_calc();
static void		flatten();
static void		format();
static void		freelist();
static void		get_formatters();
static void		initform();
static void		unflat();




/* ---------------------  Begin  Routines --------------------------------- */


/* --- *** Start Description *** ---

ch_bind (ad, p, pfmts, pcost)
	ADDR            *ad;
	LIST_RCHAN	*p;
	LIST_RCHAN	**pfmts;
	int		*pcost;

Parameters required:
	- The channel calling submit (ch_inbound)
	- The flatness of the channel (ch_inbound -> ch_content_in)
	- The channel/mta pair used to get to the Next Hop hostname ( p )
	- The list of Encoded Information Types within the message
	  (Qstruct.encodedinfo.eit_types)
	- A pointer to a list of Reformatting channels (ad->ad_fmtchan)

Example:
	ch_inbound           =  x400in
	ch_inbound->ch_content_in  =  "rfc" or "p2"
	p		     =  li_mta = ukc.ac.uk     li_chan => JANET
				( or li_mta = stl.stc.co.uk li_chan => PSS )
	Qstruct.encodedinfo
	       .eit_types    =  ia5Text, voice
	ad->ad_fmtchan       =  unflattenp2, voice2text, flattenrfc

Routine:
	- Calculates the reformatting channels.
	- Updates ad_fmtchan.
	- Returns OK or NOTOK.


fmt_init ()
	- Initialise reformatting stuff

--- *** End Description *** --- */




/* ------------------------------------------------------------------------ */





void fmt_init ()
{
	PP_TRACE (("ch_bind/fmt_init ()"));

	initform ();
	get_formatters ();
	do_calc (mainmatrix);
}

static FLAT *add2flatlist (list, name, type)
FLAT    *list;
char    *name, *type;
{
	FLAT    *ptr;

	ptr = (FLAT *) smalloc (sizeof (FLAT));
	ptr->flt_type = strdup (type);
	ptr->flt_name = strdup ( name);
	ptr->flt_next = list;
	return (ptr);
}

static void unflat (name, type)	/* Add an unflattening channel to the list */
char    *name, *type;           /* of unflattening channels */
{
	PP_TRACE (("ch_bind/unflat (%s, %s)", name, type));

	if (flttype2ptr (unflatlist, type) != NULL)
	{
		PP_LOG (LLOG_EXCEPTIONS,
			("ch_bind/UNFLAT type %s is in use already", type));
		return;
	}
	unflatlist = add2flatlist (unflatlist, name, type);
}

static void flatten (name, type) /* Add a Flattening channel to the list */
char    *name, *type;           /* of flattening channels */
{
	PP_TRACE (("ch_bind/flatten (%s, %s)", name, type));

	if (flttype2ptr (flattenlist, type) != NULL)
	{
		PP_LOG (LLOG_EXCEPTIONS,
			("ch_bind/FLATTEN type %s is in use already\n",
			type));
		return;
	}
	flattenlist = add2flatlist (flattenlist, name, type);
}

static FLAT *flttype2ptr (list, type)
char    *type;
FLAT    *list;
{
	PP_DBG (("ch_bind/flttype2ptr (list, %s)", type));

	if (type == NULLCP)
		return NULL;
	for (; list != NULL; list = list->flt_next)
		if (strcmp (list->flt_type, type) == 0)
			return (list);
	PP_TRACE (("ch_bind/flttype2ptr - NO match"));
	return (NULL);
}

static FILTER *name2filter (name) /* Format Channel name to pointer to struct */
char    *name;
{
	FILTER  *ptr;

	PP_TRACE (("ch_bind/name2filter (%s)", name));

	for (ptr = filterlist; ptr != NULL; ptr = ptr->fil_next)
		if (strcmp (name, ptr->fil_name) == 0)
			return (ptr);
	return (NULL);
}


static LIST *inslist (list, new)
LIST    *list, *new;
{

	if (new == NULL)
	{
		PP_TRACE (("ch_bind/inslist (NULL)"));
		return (list);
	}
	
	PP_TRACE (("ch_bind/inslist (%s)", new -> li_name ));
	list = inslist (list, new->li_next);
	     /* SEK - should replace with for loop */
	if (!isinlist (list, new))
	{
		new->li_next = list;
		list = new;
	}
	return (list);
}

static int isinlist (list, item)
LIST    *list, *item;
{

	for (; list != NULL; list = list->li_next)
		if (strcmp (list->li_name, item->li_name) == 0)
			return (1);
	return (0);
}


static TYPES *addchantypes (atypelist)
LIST_BPT        *atypelist;
{
	register TYPES  *list, *all, *storenum;

	PP_TRACE (("ch_bind/addchantypes (atypelist)"));

	list = NULL;
	for (; atypelist != NULL; atypelist = atypelist->li_next)
	{
		if ((storenum = name2type (atypelist->li_name)) == NULL)
		{
			PP_LOG (LLOG_EXCEPTIONS,
				("ch_bind/%s is not a defined type",
				 atypelist->li_name));
			continue;
		}
		all = (TYPES *) smalloc (sizeof (TYPES));
		all->ty_next = list;
		list = all;
		all->ty_name = atypelist->li_name;
		all->ty_number = storenum->ty_number;
	}
	return (list);
}


static TYPES *name2type (str)
char    *str;
{
	TYPES   *ptr;

	PP_TRACE (("ch_bind/name2type (%s)", str));
	for (ptr = typelist; ptr != NULL; ptr = ptr->ty_next)
		if (strcmp (str, ptr->ty_name) == 0)
			return (ptr);
	return (NULL);
}

static void format (fname, fcost, ffrom, fto)
int     fcost;
char    *fname, *ffrom, *fto;   /* Don't use FNAME, pass the CHAN pointer */
{
	int     x, y;
	FILTER  *ptr;
	TYPES   *type;

	PP_TRACE (("ch_bind/format (%s, %d, %s, %s)",
		fname, fcost, ffrom, fto));

	if ((type = name2type (ffrom)) == NULL)
	{
		PP_LOG (LLOG_EXCEPTIONS,
			("ch_bind/%s is not a defined type", ffrom));
		return;
	}
	x = type->ty_number;
	if ((type = name2type (fto)) == NULL)
	{
		PP_LOG (LLOG_EXCEPTIONS,
			("ch_bind/%s is not a defined type", fto));
		return;
	}
	y = type->ty_number;
	addmat (mainmatrix, x, y, fcost, fname);
	ptr = getfilter ();
	ptr->fil_next = filterlist;
	filterlist = ptr;
	ptr->fil_name = fname;
	ptr->fil_from = ffrom;
	ptr->fil_to = fto;
}

static LIST *copylist (list)
register LIST   *list;
{
	register LIST   *tmpitem, *ptr;

	PP_DBG (("ch_bind/copylist (list)"));

	for (tmpitem = NULL; list != NULL; list = list->li_next)
	{
		ptr = getitem ();
		ptr->li_name = list->li_name;
		tmpitem = additem (tmpitem, ptr);
	}
	return (tmpitem);
}


static LIST *additem (list, item)   /* Adds LIST item onto end of LIST list */
register LIST   *list;
LIST            *item;
{
	PP_DBG (("ch_bind/additem (list, item)"));

	if (list == NULL)
		return (item);
	list->li_next = additem (list->li_next, item);
	return (list);
}

static void freelist (list)
register LIST   *list;
{
	PP_TRACE (("ch_bind/freelist (list)"));

	if (list == NULL)
		return;
	freelist (list->li_next);
	free ((char *)list);
}

static void do_calc (mat)
MAT     mat [];
{
	register MAT    *ptr1, *ptr2, *ptr3;
	register int    i, j, k;

	PP_TRACE (("ch_bind/do_calc (mat)"));
	for (i = 0; i < matsize; i++)
		for (j = 0; j < matsize; j++)
		{
			ptr3 = &mat [j * matsize + i];
			if (ptr3->m_int != 0)
				for (k = 0; k < matsize; k++)
				{
					ptr2 = &mat [i * matsize + k];
					if (ptr2->m_int != 0)
					{
						ptr1 = &mat [j * matsize + k];
						if (ptr1->m_int == 0)
						{
							ptr1->m_int = ptr2->m_int + ptr3->m_int;
							ptr1->m_list = additem (ptr1->m_list, copylist (ptr3->m_list));
							ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list));
						}
						else
						{
							if (ptr2->m_int + ptr3->m_int < ptr1->m_int)
							{
								freelist (ptr1->m_list);
								ptr1->m_list = copylist (ptr3->m_list);
								ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list));
								ptr1->m_int = ptr2->m_int + ptr3->m_int;
							}
						}
					}
				}
		}
}

static MAT *initmat (size)
int     size;
{
	MAT     *mat;
	int     i, j;

	PP_TRACE (("ch_bind/initmat (%d)", size));
	matsize = size;
	mat = (MAT *) smalloc (size * size * sizeof (MAT));

	for (i = 0; i < size; i++)
		for (j = 0; j < size; j++)
		{
			mat [i * matsize + j].m_int = (i == j) ? 1 : 0;
			mat [i * matsize + j].m_list = NULL;
		}
	return (mat);
}

static void addmat (mat, x, y, cost, name)
MAT     mat [];
int     x, y, cost;
char    *name;                          /* Should be Pointer to CHAN struct */
{
	register MAT    *tmp;
	register LIST   *ptr;

	PP_TRACE (("ch_bind/addmat (mat, %d, %d, %d, %s)", x, y, cost, name));
	ptr = getitem ();
	ptr->li_name = name;
	tmp = &mat [x * matsize + y];
	tmp->m_int = cost;
	tmp->m_list = additem (tmp->m_list, ptr);
}

static FILTER *getfilter ()
{
	register FILTER *ptr;

	PP_DBG (("ch_bind/getfilter ()"));
	ptr = (FILTER *) smalloc (sizeof (FILTER));

	ptr->fil_next = NULL;
	return (ptr);
}

static LIST *getitem ()
{
	register LIST   *ptr;

	PP_DBG (("ch_bind/getitem ()"));
	ptr = (LIST *) smalloc (sizeof (LIST));
	ptr->li_name = NULL;
	ptr->li_next = NULL;
	return (ptr);
}

/*              initform
 *      This routine goes through the body parts
 */


static void initform ()
{
	register LIST_BPT       *bptptr;
	TYPES                   *all, *list;
	int                     count;

	PP_TRACE (("ch_bind/initform ()"));

	list = NULL;
	count = 0;
	for (bptptr = bodies_all; bptptr != NULLIST_BPT;
	     bptptr = bptptr -> li_next)
	{
		PP_TRACE (("ch_bind/doing body part %s",
			   bptptr -> li_name));
		all = (TYPES *) smalloc (sizeof (TYPES));
		all->ty_next = list;
		list = all;
		all->ty_name = bptptr->li_name;
		all->ty_number = count++;
	}
	mainmatrix = initmat (count);
	typelist = list;
}

/*              get_formatters
 * This routine will go through the list of Channels and put the
 * formatters, flatteners and un-flatteners into the matrix.
 */

static void get_formatters ()
{
	register CHAN           **chanptr;

	PP_TRACE (("ch_bind/get_formatters"));
	for (chanptr = ch_all; (*chanptr) != NULL; chanptr++)
	{
		if ((*chanptr)->ch_chan_type != CH_SHAPER)
			continue;
		if ((*chanptr)->ch_bpt_in == NULL 
				&& (*chanptr)->ch_bpt_out == NULL)
					/* Flatten/Unfflatten */
			if ((*chanptr)->ch_content_out == NULL
				&& (*chanptr)->ch_content_in == NULL)
			{
				PP_LOG (LLOG_EXCEPTIONS,
					("ch_bind/no content definitions for %s",
					 (*chanptr)-> ch_name));
			}
			else if ((*chanptr)->ch_content_in != NULL)
			{       /* This is Unflattener */
				unflat ((*chanptr)->ch_name,
					(*chanptr)->ch_content_in);
			}
		        else
			{       /* This is a flattener */
				flatten ((*chanptr)->ch_name,
					 (*chanptr)->ch_content_out);
			}
		else if ((*chanptr)->ch_bpt_in != NULL 
				&& (*chanptr)->ch_bpt_out != NULL)

		{       /* This is Formatter */
			format ((*chanptr)->ch_name,
				(*chanptr)->ch_cost + 2,
				(*chanptr)->ch_bpt_in->li_name,
				(*chanptr)->ch_bpt_out->li_name);
		}
		else
		{
			PP_LOG (LLOG_EXCEPTIONS,
				("ch_bind/ erroneous definitions for %s",
				 (*chanptr)-> ch_name));
		}

	}
}


int ch_bind (ad, p,pfmts, pbpts, pcost)
ADDR    	*ad;
LIST_RCHAN	*p;
LIST_RCHAN	**pfmts;
LIST_BPT	**pbpts;
int		*pcost;
{
	MAT     *mat;
	CHAN    *out_chan;
	TYPES   *chan, *messty, *t2, *ty = NULL;
	LIST    *list = NULL, *worklist;
	LIST_BPT	*new_bpt = NULLIST_BPT;
	LIST_RCHAN	*new_chan;
	FILTER  *filt;
	FLAT	*flat;
	char    *filtername, *in_content;
	int     cost, ind;

	*pfmts = NULLIST_RCHAN;
	*pcost = 0;
	*pbpts = NULLIST_BPT;

	PP_TRACE (("ch_bind ()"));


/*	in_content = ch_inbound->ch_content_in; */
	in_content = Qstruct.cont_type;
	if (p == NULLIST_RCHAN)
		err_abrt (RP_MECH, "No channel in address for %s",
			ad -> ad_value);
	out_chan = p->li_chan;

	/* Messty - EITs within the message */
	messty = addchantypes (Qstruct.encodedinfo.eit_types);

#if PP_DEBUG > 1
	if (pp_log_norm -> ll_events & LLOG_DEBUG) {
		/* Testing Blurb */
		chan = addchantypes (out_chan->ch_bpt_out);
		PP_DBG (("ch_bind/Channel %s supports ->", out_chan->ch_name));
		for (; chan != NULL; chan = chan->ty_next)
			PP_DBG (("\t`%s'", chan->ty_name));
		PP_DBG (("EOL"));
		/* End of Testing Blurb */
	}
#endif
	worklist = NULL;
	if (out_chan -> ch_bpt_out != NULLIST_BPT) {
		for (chan = messty; chan != NULL; chan = chan->ty_next)
		{
			cost = 0;
			t2 = addchantypes (out_chan->ch_bpt_out);
			/* SEK addchantypes is called 4 times
			   once on each channel - this seems excessive */

			/* SEK this loop initialises for inbound  */
			for (; t2 != NULL; t2 = t2->ty_next)
			{
				ind = chan->ty_number * matsize + t2->ty_number;
				mat = &mainmatrix[ind];
				if ((cost == 0 && mat->m_int != 0) ||
				    (cost != 0 && cost > mat->m_int
				     && mat->m_int != 0))
				{
					list = mat->m_list;
					cost = mat->m_int;
					ty = t2;
				}
			}
			if (cost == 0) {
				PP_LOG (LLOG_NOTICE,
					("ch_bind/Can't convert %s", chan->ty_name));
			
				return NOTOK;
			}
			else {
				if (list_bpt_find (new_bpt, ty->ty_name) ==
				    NULLIST_BPT)
					list_bpt_add (&new_bpt,
						      list_bpt_new (ty->ty_name));
				if (cost == 1) {
					PP_TRACE (("Cost = 1"));
					continue;
				}
				else {
					worklist = inslist (worklist, list);
				}
			}
		}
	}
	/* SEK - unflatten flat message if there is work to do */
	if (worklist != NULL && isstr(in_content)) {
		flat = flttype2ptr (unflatlist, in_content);
		if (flat != NULL) {
			filtername = flat -> flt_name;
			PP_DBG (("ch_bind/UNFLATTEN with %s", filtername));
			new_chan = list_rchan_new (NULLCP, filtername);
			*pcost += new_chan -> li_chan -> ch_cost;
			list_rchan_add (pfmts, new_chan);
		}
		else
			PP_LOG (LLOG_EXCEPTIONS,
				("Can't find unflattener for %s", in_content));
	}
	/* SEK unflatten if content changes */
	else if (worklist == NULL &&
		 (isstr (in_content) && 
		   isstr (out_chan -> ch_content_out) &&
		   strcmp (in_content, out_chan->ch_content_out) != 0)) {
/* ||
		  (!isstr (in_content) && 
		   !isstr (out_chan->ch_content_out)))) {*/

		flat = flttype2ptr (unflatlist, in_content);
		if (flat != NULL) {
			filtername = flat -> flt_name;
			PP_DBG (("ch_bind/UNFLATTEN with %s", filtername));
			new_chan = list_rchan_new (NULLCP, filtername);
			*pcost += new_chan -> li_chan -> ch_cost;
			list_rchan_add (pfmts, new_chan);
		}
		else
			PP_LOG (LLOG_EXCEPTIONS,
				("Can't find unflattener for %s", in_content));
	}

	/* SEK - calculate real work */
	for (list = worklist; list != NULL; list = list->li_next)
	{
		filt = name2filter (list->li_name);
		if (filt == NULL) {
			PP_LOG (LLOG_EXCEPTIONS, ("No filter defined for %s",
						  list -> li_name));
			continue;
		}
		PP_DBG (("ch_bind/%s  [%s to %s]\n", filt->fil_name,
			 filt->fil_from, filt->fil_to));
		new_chan = list_rchan_new (NULLCP, filt -> fil_name);
		*pcost += new_chan -> li_chan -> ch_cost;
		list_rchan_add (pfmts, new_chan);
	}

	/* flatten if work done and out is flat */
	if (worklist != NULL && isstr(out_chan->ch_content_out)) {
		flat = flttype2ptr (flattenlist, out_chan->ch_content_out);
		if (flat != NULL) {
			filtername = flat -> flt_name;
			PP_DBG (("ch_bind/FLATTEN with %s", filtername));
			new_chan = list_rchan_new (NULLCP, filtername);
			*pcost += new_chan -> li_chan -> ch_cost;
			list_rchan_add (pfmts, new_chan);
		}
		else
			PP_LOG (LLOG_EXCEPTIONS,
				("Can't find flattener for %s",
				 out_chan -> ch_content_out));
	}
	/* flatten if no work and content changes */
	else if (worklist == NULL &&
		 (isstr (in_content) && 
	      isstr (out_chan -> ch_content_out) &&
	      strcmp (in_content, out_chan->ch_content_out) != 0)) {
/* ||
	     (!isstr(in_content) && !isstr (out_chan->ch_content_out)))) {*/

		flat = flttype2ptr (flattenlist, out_chan->ch_content_out);

		if (flat != NULL) {
			filtername = flat -> flt_name;
			PP_DBG (("ch_bind/FLATTEN with %s", filtername));
			new_chan = list_rchan_new (NULLCP, filtername);
			*pcost += new_chan -> li_chan -> ch_cost;
			list_rchan_add (pfmts, new_chan);
		}
		else
			PP_LOG (LLOG_EXCEPTIONS,
				("Can't find flattener for %s",
				 out_chan -> ch_content_out));
	}
	if (ad -> ad_content == NULLCP
	    && isstr (in_content) && isstr (out_chan -> ch_content_out) &&
	    strcmp (in_content, out_chan -> ch_content_out) != 0)
		ad -> ad_content = strdup (out_chan -> ch_content_out);
	else if (ad -> ad_content == NULLCP && 
		 isstr(out_chan -> ch_content_out))
		ad -> ad_content = strdup (out_chan -> ch_content_out);

        *pbpts = new_bpt;
	return OK;
}