|
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; }