|
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 r
Length: 17403 (0x43fb) Types: TextFile Names: »ro2ss.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/rosap/ro2ss.c«
/* ro2ss.c - ROPM: SSAP interface */ #ifndef lint static char *rcsid = "$Header: /f/osi/rosap/RCS/ro2ss.c,v 7.0 89/11/23 22:21:17 mrose Rel $"; #endif /* * $Header: /f/osi/rosap/RCS/ro2ss.c,v 7.0 89/11/23 22:21:17 mrose Rel $ * * Based on an TCP-based implementation by George Michaelson of University * College London. * * * $Log: ro2ss.c,v $ * Revision 7.0 89/11/23 22:21:17 mrose * Release 6.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ /* LINTLIBRARY */ #include <stdio.h> #include "ropkt.h" #include "tailor.h" /* \f DATA */ #define doSSabort ss2rosabort int ssDATAser (), ssTOKENser (), ssSYNCser (), ssACTIVITYser (), ssREPORTser (), ssFINISHser (), ssABORTser (); /* \f bind underlying service */ int RoSService (acb, roi) register struct assocblk *acb; struct RoSAPindication *roi; { if (acb -> acb_flags & (ACB_ACS | ACB_RTS)) return rosaplose (roi, ROS_OPERATION, NULLCP, "not an association descriptor for ROS on session"); acb -> acb_putosdu = ro2sswrite; acb -> acb_rowaitrequest = ro2sswait; acb -> acb_getosdu = qbuf2pe; acb -> acb_ready = ro2ssready; acb -> acb_rosetindications = ro2ssasync; acb -> acb_roselectmask = ro2ssmask; acb -> acb_ropktlose = ro2sslose; return OK; } /* \f define vectors for INDICATION events */ #define e(i) (indication ? (i) : NULLIFP) /* ARGSUSED */ int ro2ssasync (acb, indication, roi) register struct assocblk *acb; IFP indication; struct RoSAPindication *roi; { struct SSAPindication sis; register struct SSAPabort *sa = &sis.si_abort; if (SSetIndications (acb -> acb_fd, e (ssDATAser), e (ssTOKENser), e (ssSYNCser), e (ssACTIVITYser), e (ssREPORTser), e (ssFINISHser), e (ssABORTser), &sis) == NOTOK) switch (sa -> sa_reason) { case SC_WAITING: return rosaplose (roi, ROS_WAITING, NULLCP, NULLCP); default: (void) ss2roslose (acb, roi, "SSetIndications", sa); freeacblk (acb); return NOTOK; } if (acb -> acb_rosindication = indication) acb -> acb_flags |= ACB_ASYN; else acb -> acb_flags &= ~ACB_ASYN; return OK; } #undef e /* \f map association descriptors for select() */ /* ARGSUSED */ int ro2ssmask (acb, mask, nfds, roi) register struct assocblk *acb; fd_set *mask; int *nfds; struct RoSAPindication *roi; { struct SSAPindication sis; register struct SSAPabort *sa = &sis.si_abort; if (SSelectMask (acb -> acb_fd, mask, nfds, &sis) == NOTOK) switch (sa -> sa_reason) { case SC_WAITING: return rosaplose (roi, ROS_WAITING, NULLCP, NULLCP); default: (void) ss2roslose (acb, roi, "SSelectMask", sa); freeacblk (acb); return NOTOK; } return OK; } /* \f protocol-level abort */ int ro2sslose (acb, result) register struct assocblk *acb; int result; { int len; char *base; PE pe; struct SSAPindication sis; base = NULL, len = 0; /* begin AbortInformation PSDU (pseudo) */ if (pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SET)) { if (set_add (pe, num2prim (result, PE_CLASS_CONT, 0)) != NOTOK) (void) pe2ssdu (pe, &base, &len); PLOG (rosap_log, print_OACS_AbortInformation, pe, "AbortInformation", 0); pe_free (pe); } /* end AbortInformation PSDU */ (void) SUAbortRequest (acb -> acb_fd, base, len, &sis); acb -> acb_fd = NOTOK; if (base) free (base); } /* \f SSAP interface */ int ro2sswait (acb, invokeID, secs, roi) register struct assocblk *acb; int *invokeID, secs; register struct RoSAPindication *roi; { int result; struct SSAPdata sxs; register struct SSAPdata *sx = &sxs; struct SSAPindication sis; register struct SSAPindication *si = &sis; if (acb -> acb_apdu) { result = acb2osdu (acb, NULLIP, acb -> acb_apdu, roi); acb -> acb_apdu = NULLPE; return result; } for (;;) { switch (result = SReadRequest (acb -> acb_fd, sx, secs, si)) { case NOTOK: return doSSabort (acb, &si -> si_abort, roi); case OK: if ((result = doSSdata (acb, invokeID, sx, roi)) != OK) return (result != DONE ? result : OK); continue; case DONE: switch (si -> si_type) { case SI_TOKEN: if (doSStokens (acb, &si -> si_token, roi) == NOTOK) return NOTOK; continue; case SI_SYNC: if (doSSsync (acb, &si -> si_sync, roi) == NOTOK) return NOTOK; continue; case SI_ACTIVITY: if (doSSactivity (acb, &si -> si_activity, roi) == NOTOK) return NOTOK; continue; case SI_REPORT: if (doSSreport (acb, &si -> si_report, roi) == NOTOK) return NOTOK; continue; case SI_FINISH: if (doSSfinish (acb, &si -> si_finish, roi) == NOTOK) return NOTOK; return DONE; default: (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unknown indication (0x%x) from session", si -> si_type); break; } break; default: (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected return from SReadRequest=%d", result); break; } break; } freeacblk (acb); return NOTOK; } /* \f */ /* ARGSUSED */ int ro2ssready (acb, priority, roi) register struct assocblk *acb; int priority; struct RoSAPindication *roi; { int result; PE pe; struct SSAPdata sxs; register struct SSAPdata *sx = &sxs; struct SSAPindication sis; struct SSAPindication *si = &sis; struct SSAPabort *sa = &si -> si_abort; if (acb -> acb_apdu || (acb -> acb_flags & ACB_CLOSING)) return rosaplose (roi, ROS_WAITING, NULLCP, NULLCP); if (!(acb -> acb_requirements & SR_HALFDUPLEX) || (acb -> acb_flags & ACB_TURN)) return OK; if (!(acb -> acb_flags & ACB_PLEASE)) { if (SPTokenRequest (acb -> acb_fd, ST_DAT_TOKEN, NULLCP, 0, si) == NOTOK) { (void) ss2roslose (acb, roi, "SPTokenRequest", sa); goto out; } acb -> acb_flags |= ACB_PLEASE; } for (;;) { switch (result = SReadRequest (acb -> acb_fd, sx, NOTOK, si)) { case NOTOK: return doSSabort (acb, &si -> si_abort, roi); case OK: if (sx -> sx_type != SX_NORMAL) { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected data indication (0x%x)", sx -> sx_type); goto bad_sx; } if (pe = qbuf2pe (&sx -> sx_qbuf, sx -> sx_cc, &result)) { acb -> acb_apdu = pe; return rosaplose (roi, ROS_WAITING, NULLCP, NULLCP); } if (result != PS_ERR_NMEM) { (void) rosapreject (acb, roi, ROS_GP_STRUCT, NULLCP, "%s", ps_error (result)); continue; } (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "%s", ps_error (result)); bad_sx: ; SXFREE (sx); goto out; case DONE: switch (si -> si_type) { case SI_TOKEN: if (doSStokens (acb, &si -> si_token, roi) == NOTOK) return NOTOK; return OK; case SI_SYNC: if (doSSsync (acb, &si -> si_sync, roi) == NOTOK) return NOTOK; continue; case SI_ACTIVITY: if (doSSactivity (acb, &si -> si_activity, roi) == NOTOK) return NOTOK; continue; case SI_REPORT: if (doSSreport (acb, &si -> si_report, roi) == NOTOK) return NOTOK; continue; case SI_FINISH: if (doSSfinish (acb, &si -> si_finish, roi) == NOTOK) return NOTOK; return DONE; default: (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unknown indication (0x%x) from session", si -> si_type); break; } break; default: (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected return from SReadRequest=%d", result); break; } break; } out: ; freeacblk (acb); return NOTOK; } /* \f */ /* ARGSUSED */ int ro2sswrite (acb, pe, fe, priority, roi) register struct assocblk *acb; register PE pe; PE fe; int priority; struct RoSAPindication *roi; { int result; register struct udvec *vv; struct udvec *uv; struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; PLOG (rosap_log, print_ROS_OPDU, pe, "OPDU", 0); uv = NULL; if ((result = pe2uvec (pe, &uv)) == NOTOK) (void) rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory"); else if ((result = SWriteRequest (acb -> acb_fd, 0, uv, si)) == NOTOK) (void) ss2roslose (acb, roi, "SWriteRequest", sa); else result = OK; if (fe) (void) pe_extract (pe, fe); pe_free (pe); if (uv) { for (vv = uv; vv -> uv_base; vv++) if (!vv -> uv_inline) free ((char *) vv -> uv_base); free ((char *) uv); } if (result == NOTOK) freeacblk (acb); return result; } /* \f */ static int doSSdata (acb, invokeID, sx, roi) register struct assocblk *acb; int *invokeID; register struct SSAPdata *sx; struct RoSAPindication *roi; { int result; register PE pe; if (sx -> sx_type != SX_NORMAL) { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected data indication (0x%x)", sx -> sx_type); goto out; } if (pe = (*acb -> acb_getosdu) (&sx -> sx_qbuf, sx -> sx_cc, &result)) return acb2osdu (acb, invokeID, pe, roi); if (result != PS_ERR_NMEM) return rosapreject (acb, roi, ROS_GP_STRUCT, NULLCP, "%s", ps_error (result)); (void) ropktlose (acb, roi, ROS_CONGEST, NULLCP, "%s", ps_error (result)); out: ; SXFREE (sx); freeacblk (acb); return NOTOK; } /* \f */ static int doSStokens (acb, st, roi) register struct assocblk *acb; register struct SSAPtoken *st; struct RoSAPindication *roi; { int result; struct SSAPindication sis; struct SSAPindication *si = &sis; struct SSAPabort *sa = &si -> si_abort; switch (st -> st_type) { case ST_CONTROL: break; case ST_PLEASE: if (!(acb -> acb_requirements & SR_HALFDUPLEX)) break; if (!(acb -> acb_flags & ACB_TURN)) break; /* error - do not have turn */ result = SGTokenRequest (acb -> acb_fd, ST_DAT_TOKEN, si); if (result == NOTOK) { (void) ss2roslose (acb, roi, "SGTokenRequest", sa); goto out; } acb -> acb_flags &= ~ACB_TURN; STFREE (st); return result; case ST_GIVE: if (!(acb -> acb_requirements & SR_HALFDUPLEX)) break; if (acb -> acb_flags & ACB_TURN) break; /* error - have turn already */ if (st -> st_tokens & ST_DAT_TOKEN) { acb -> acb_flags |= ACB_TURN; acb -> acb_flags &= ~ACB_PLEASE; } return result; default: break; } (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected token indication (0x%x)", st -> st_type); out: ; STFREE (st); freeacblk (acb); return NOTOK; } /* \f */ static int doSSsync (acb, sn, roi) register struct assocblk *acb; register struct SSAPsync *sn; struct RoSAPindication *roi; { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected sync indication (0x%x)", sn -> sn_type); SNFREE (sn); freeacblk (acb); return NOTOK; } /* \f */ static int doSSactivity (acb, sv, roi) register struct assocblk *acb; register struct SSAPactivity *sv; struct RoSAPindication *roi; { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected activity indication (0x%x)", sv -> sv_type); SVFREE (sv); freeacblk (acb); return NOTOK; } /* \f */ static int doSSreport (acb, sp, roi) register struct assocblk *acb; register struct SSAPreport *sp; struct RoSAPindication *roi; { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "unexpected exception report indication (0x%x)", sp -> sp_peer); SPFREE (sp); freeacblk (acb); return NOTOK; } /* \f */ static int doSSfinish (acb, sf, roi) register struct assocblk *acb; struct SSAPfinish *sf; struct RoSAPindication *roi; { SFFREE (sf); if (acb -> acb_flags & ACB_INIT) { (void) ropktlose (acb, roi, ROS_PROTOCOL, NULLCP, "association management botched"); freeacblk (acb); return NOTOK; } acb -> acb_flags |= ACB_FINN; roi -> roi_type = ROI_END; { register struct RoSAPend *roe = &roi -> roi_end; bzero ((char *) roe, sizeof *roe); } return DONE; } /* \f */ int ss2rosabort (acb, sa, roi) register struct assocblk *acb; register struct SSAPabort *sa; struct RoSAPindication *roi; { int result; register PE pe; if (!sa -> sa_peer) { if (sa -> sa_reason == SC_TIMER) return rosaplose (roi, ROS_TIMER, NULLCP, NULLCP); (void) ss2roslose (acb, roi, NULLCP, sa); goto out; } if (sa -> sa_cc == 0) { (void) rosaplose (roi, ROS_ABORTED, NULLCP, NULLCP); goto out; } if ((pe = ssdu2pe (sa -> sa_info, sa -> sa_cc, NULLCP, &result)) == NULLPE) { (void) rosaplose (roi, ROS_PROTOCOL, NULLCP, NULLCP); goto out; } acsap_abort = -1; result = parse_OACS_AbortInformation (pe, 1, NULLIP, NULLVP, NULLCP); #ifdef DEBUG if (result != NOTOK && (rosap_log -> ll_events & LLOG_PDUS)) vpdu (rosap_log, print_OACS_AbortInformation, pe, "AbortInformation", 1); #endif pe_free (pe); if (result == NOTOK) { (void) rosaplose (roi, ROS_PROTOCOL, "%s", PY_pepy); goto out; } switch (acsap_abort) { case ABORT_LSP: case ABORT_TMP: result = ROS_REMOTE; break; default: result = ROS_PROTOCOL; break; } (void) rosaplose (roi, result, NULLCP, NULLCP); out: ; SAFREE (sa); acb -> acb_fd = NOTOK; freeacblk (acb); return NOTOK; } /* \f */ static int ssDATAser (sd, sx) int sd; register struct SSAPdata *sx; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; if (doSSdata (acb, NULLIP, sx, roi) != OK) (*handler) (sd, roi); } /* \f */ static int ssTOKENser (sd, st) int sd; register struct SSAPtoken *st; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; if (doSStokens (acb, st, roi) != OK) (*handler) (sd, roi); } /* \f */ static int ssSYNCser (sd, sn) int sd; register struct SSAPsync *sn; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; if (doSSsync (acb, sn, roi) != OK) (*handler) (sd, roi); } /* \f */ static int ssACTIVITYser (sd, sv) int sd; register struct SSAPactivity *sv; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; if (doSSactivity (acb, sv, roi) != OK) (*handler) (sd, roi); } /* \f */ static int ssREPORTser (sd, sp) int sd; register struct SSAPreport *sp; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; if (doSSreport (acb, sp, roi) != OK) (*handler) (sd, roi); } /* \f */ static int ssFINISHser (sd, sf) int sd; struct SSAPfinish *sf; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; (void) doSSfinish (acb, sf, roi); (*handler) (sd, roi); } /* \f */ static int ssABORTser (sd, sa) int sd; register struct SSAPabort *sa; { IFP handler; register struct assocblk *acb; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rosindication; (void) doSSabort (acb, sa, roi); (*handler) (sd, roi); } /* \f */ int ss2roslose (acb, roi, event, sa) register struct assocblk *acb; register struct RoSAPindication *roi; char *event; register struct SSAPabort *sa; { int reason; char *cp, buffer[BUFSIZ]; if (event) SLOG (rosap_log, LLOG_EXCEPTIONS, NULLCP, (sa -> sa_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event, SErrString (sa -> sa_reason), sa -> sa_cc, sa -> sa_cc, sa -> sa_data)); cp = ""; switch (sa -> sa_reason) { case SC_SSAPID: case SC_SSUSER: case SC_ADDRESS: reason = ROS_ADDRESS; break; case SC_REFUSED: reason = ROS_REFUSED; break; case SC_CONGEST: reason = ROS_CONGEST; break; default: (void) sprintf (cp = buffer, " (%s at session)", SErrString (sa -> sa_reason)); case SC_TRANSPORT: case SC_ABORT: reason = ROS_SESSION; break; } if (sa -> sa_cc > 0) return ropktlose (acb, roi, reason, NULLCP, "%*.*s%s", sa -> sa_cc, sa -> sa_cc, sa -> sa_data, cp); else return ropktlose (acb, roi, reason, NULLCP, "%s", *cp ? cp + 1 : cp); }