|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 16803 (0x41a3)
Types: TextFile
Names: »ch_bind.c«
└─⟦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«
/* 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;
}