|
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: 30095 (0x758f) Types: TextFile Names: »rt2ps.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/rtsap/rt2ps.c«
/* rt2ps.c - RTPM: AcSAP/PSAP interface */ #ifndef lint static char *rcsid = "$Header: /f/osi/rtsap/RCS/rt2ps.c,v 7.1 90/01/16 20:45:14 mrose Exp $"; #endif /* * $Header: /f/osi/rtsap/RCS/rt2ps.c,v 7.1 90/01/16 20:45:14 mrose Exp $ * * * $Log: rt2ps.c,v $ * Revision 7.1 90/01/16 20:45:14 mrose * last check-out * * Revision 7.0 89/11/23 22:22:18 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 "rtpkt.h" #include "tailor.h" /* \f DATA */ int psDATAser (), psTOKENser (), psSYNCser (), psACTIVITYser (), psREPORTser (), psFINISHser (), psABORTser (); long time (); /* \f */ int rt2pspturn (acb, priority, rti) register struct assocblk *acb; int priority; register struct RtSAPindication *rti; { int result; PE pe; struct PSAPindication pis; struct PSAPindication *pi = &pis; struct PSAPabort *pa = &pi -> pi_abort; if (!(acb -> acb_flags & ACB_TWA)) return rtsaplose (rti, RTS_OPERATION, NULLCP, "mode of association is monologue"); if (acb -> acb_flags & ACB_TURN) return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn owned by you"); /* begin RTTP APDU */ if ((pe = int2prim (priority)) == NULLPE) return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP); pe -> pe_context = acb -> acb_rtsid; /* end RTTP APDU */ PLOG (rtsap_log, print_RTS_RTTPapdu, pe, "RTTPapdu", 0); result = PPTokenRequest (acb -> acb_fd, ST_DAT_TOKEN, &pe, 1, pi); pe_free (pe); if (result == NOTOK) { (void) ps2rtslose (acb, rti, "PPTokenRequest", pa); freeacblk (acb); } return result; } /* \f */ int rt2psgturn (acb, rti) register struct assocblk *acb; register struct RtSAPindication *rti; { struct PSAPindication pis; struct PSAPindication *pi = &pis; struct PSAPabort *pa = &pi -> pi_abort; if (!(acb -> acb_flags & ACB_TWA)) return rtsaplose (rti, RTS_OPERATION, NULLCP, "mode of association is monologue"); if (!(acb -> acb_flags & ACB_TURN)) return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn not owned by you"); if (acb -> acb_flags & ACB_ACT) return rtsaplose (rti, RTS_OPERATION, NULLCP, "transfer in progress"); if (PGControlRequest (acb -> acb_fd, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PGControlRequest", pa); freeacblk (acb); return NOTOK; } acb -> acb_flags &= ~(ACB_TURN | ACB_PLEASE); return OK; } /* \f */ int rt2pstrans (acb, data, secs, rti) register struct assocblk *acb; register PE data; int secs; register struct RtSAPindication *rti; { register int cc, size; int result, len; long clock, limit; register char *dp; char *base; PE pe; struct SSAPactid ids; register struct SSAPactid *id = &ids; struct PSAPindication pis; struct PSAPindication *pi = &pis; struct PSAPabort *pa = &pi -> pi_abort; struct RtSAPabort *rta = &rti -> rti_abort; if (!(acb -> acb_flags & ACB_TURN)) return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn not owned by you"); if (acb -> acb_flags & ACB_ACT) return rtsaplose (rti, RTS_OPERATION, NULLCP, "transfer in progress"); if ((pe = int2prim (acb -> acb_actno)) == NULLPE) return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP); result = pe2ssdu (pe, &base, &len); pe_free (pe); if (result == NOTOK) return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP); bcopy (base, id -> sd_data, (int) (id -> sd_len = len)); free (base); base = NULL; if (pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_OCTS)) { pe -> pe_inline = 1; pe -> pe_context = acb -> acb_rtsid; } else { (void) rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP); goto out; } if (PActStartRequest (acb -> acb_fd, id, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActStartRequest", pa); goto out; } acb -> acb_flags |= ACB_ACT; if (data && pe2ssdu (data, &base, &len) == NOTOK) { (void) rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP); goto out; } result = OK; if (acb -> acb_ckpoint == 0) { if (data == NULLPE) { if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, 0, 0L, 0L, rti) == NOTOK) { bad_trans: ; if (PActDiscRequest (acb -> acb_fd, SP_LOCAL, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActDiscRequest", pa); goto out; } goto done; } if (len == 0) { base = NULL; goto done; } } pe -> pe_prim = (PElementData) base, pe -> pe_len = (PElementLen) len; if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PDataRequest", pa); goto out; } } else { size = acb -> acb_ckpoint << 10; /* units of 1024 octets */ #ifdef notdef if (acb -> acb_ssdusize >= 0x0100) /* at least 256 octets */ size = min (size, acb -> acb_ssdusize); #endif acb -> acb_ssn = acb -> acb_ack = 0L; if (secs != NOTOK) { (void) time (&limit); limit += secs; } if (data == NULLPE) { if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, size, acb -> acb_ssn, acb -> acb_ack, rti) == NOTOK) goto bad_trans; if (len == 0) { base = NULL; goto done; } } dp = base, cc = min (len, size); pe -> pe_prim = (PElementData) dp, pe -> pe_len = (PElementLen) cc; if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PDataRequest", pa); goto out; } for (dp += cc, len -= cc; data == NULLPE || len > 0; dp += cc, len -= cc) { if (data == NULLPE && len == 0) { if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, size, acb -> acb_ssn, acb -> acb_ack, rti) == NOTOK) goto bad_trans; if (len == 0) { base = NULL; break; } dp = base; } if (secs != NOTOK) { (void) time (&clock); if (limit < clock) { result = NOTOK; break; } } if (PMinSyncRequest (acb -> acb_fd, SYNC_CONFIRM, &acb -> acb_ssn, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PMinSyncRequest", pa); goto out; } if (acb -> acb_ssn - acb -> acb_ack > acb -> acb_window) { do { if (RtWaitRequestAux (acb, NOTOK, 1, rti) == NOTOK) { if (RTS_FATAL (rta -> rta_reason)) acb = NULLACB; goto out; } } while (acb -> acb_ssn - acb -> acb_ack > acb -> acb_window); #ifdef notdef /* avoid silly window syndrome */ while (acb -> acb_ssn != acb -> acb_ack) if (RtWaitRequestAux (acb, OK, 1, rti) == NOTOK) if (rta -> rta_reason != RTS_TIMER) { if (RTS_FATAL (rta -> rta_reason)) acb = NULLACB; goto out; } else break; #endif } cc = min (len, size); pe -> pe_prim = (PElementData) dp, pe -> pe_len = cc; if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PDataRequest", pa); goto out; } } } if (data) free (base); base = NULL; done: ; switch (result) { case OK: if (PActEndRequest (acb -> acb_fd, &acb -> acb_ssn, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActEndRequest", pa); goto out; } break; default: acb -> acb_flags |= ACB_TIMER; if (PActDiscRequest (acb -> acb_fd, SP_LOCAL, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActDiscRequest", pa); goto out; } break; } while (acb -> acb_flags & ACB_ACT) if (RtWaitRequestAux (acb, NOTOK, 1, rti) == NOTOK) { if (RTS_FATAL (rta -> rta_reason)) acb = NULLACB; goto out; } acb -> acb_flags &= ~ACB_TIMER; acb -> acb_actno++; if (pe) pe_free (pe); return result; out: ; if (data && base) free (base); if (pe) pe_free (pe); if (acb) freeacblk (acb); return NOTOK; } /* \f */ int rt2pswait (acb, secs, trans, rti) register struct assocblk *acb; int secs, trans; register struct RtSAPindication *rti; { int result; struct PSAPdata pxs; register struct PSAPdata *px = &pxs; struct PSAPindication pis; register struct PSAPindication *pi = &pis; for (;;) { switch (result = PReadRequest (acb -> acb_fd, px, secs, pi)) { case NOTOK: return doPSabort (acb, &pi -> pi_abort, rti); case OK: if (doPSdata (acb, px, rti) == NOTOK) return NOTOK; continue; case DONE: switch (pi -> pi_type) { case PI_TOKEN: if ((result = doPStoken (acb, &pi -> pi_token, trans, rti)) != OK) return result; continue; case PI_SYNC: if ((result = doPSsync (acb, &pi -> pi_sync, rti)) != OK || trans) return result; continue; case PI_ACTIVITY: if ((result = doPSactivity (acb, &pi -> pi_activity, rti)) != OK || trans) return (result != DONE ? result : OK); continue; case PI_REPORT: if (doPSreport (acb, &pi -> pi_report, rti) == NOTOK) return NOTOK; continue; case PI_FINISH: return doPSfinish (acb, &pi -> pi_finish, rti); default: (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unknown indication (0x%x) from presentation", pi -> pi_type); break; } break; default: (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected return from PReadRequest=%d", result); break; } break; } freeacblk (acb); return NOTOK; } /* \f define vectors for INDICATION events */ #define e(i) (indication ? (i) : NULLIFP) int rt2psasync (acb, indication, rti) register struct assocblk *acb; IFP indication; struct RtSAPindication *rti; { struct PSAPindication pis; struct PSAPindication *pi = &pis; struct PSAPabort *pa = &pi -> pi_abort; if (PSetIndications (acb -> acb_fd, e (psDATAser), e (psTOKENser), e (psSYNCser), e (psACTIVITYser), e (psREPORTser), e (psFINISHser), e (psABORTser), pi) == NOTOK) switch (pa -> pa_reason) { case PC_WAITING: return rtsaplose (rti, RTS_WAITING, NULLCP, NULLCP); default: (void) ps2rtslose (acb, rti, "PSetIndications", pa); freeacblk (acb); return NOTOK; } if (acb -> acb_rtsindication = indication) acb -> acb_flags |= ACB_ASYN; else acb -> acb_flags &= ~ACB_ASYN; return OK; } #undef e /* \f map association descriptors for select() */ int rt2psmask (acb, mask, nfds, rti) register struct assocblk *acb; fd_set *mask; int *nfds; struct RtSAPindication *rti; { struct PSAPindication pis; struct PSAPindication *pi = &pis; struct PSAPabort *pa = &pi -> pi_abort; if (PSelectMask (acb -> acb_fd, mask, nfds, pi) == NOTOK) switch (pa -> pa_reason) { case PC_WAITING: return rtsaplose (rti, RTS_WAITING, NULLCP, NULLCP); default: (void) ps2rtslose (acb, rti, "PSelectMask", pa); freeacblk (acb); return NOTOK; } return OK; } /* \f protocol-level abort */ int rt2pslose (acb, result) register struct assocblk *acb; int result; { PE pe; struct AcSAPindication acis; /* begin RTAB APDU */ if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SET)) && set_add (pe, num2prim (result, PE_CLASS_CONT, RTAB_REASON)) != NOTOK) { pe -> pe_context = acb -> acb_rtsid; PLOG (rtsap_log, print_RTS_RTABapdu, pe, "RTABapdu", 0); (void) AcUAbortRequest (acb -> acb_fd, &pe, 1, &acis); pe_free (pe); } /* end RTAB APDU */ } /* \f AcSAP interface */ int acs2rtslose (acb, rti, event, aca) register struct assocblk *acb; register struct RtSAPindication *rti; char *event; register struct AcSAPabort *aca; { int reason; char *cp, buffer[BUFSIZ]; if (event) SLOG (rtsap_log, LLOG_EXCEPTIONS, NULLCP, (aca -> aca_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event, AcErrString (aca -> aca_reason), aca -> aca_cc, aca -> aca_cc, aca -> aca_data)); cp = ""; switch (aca -> aca_reason) { case ACS_ADDRESS: reason = RTS_ADDRESS; break; case ACS_REFUSED: reason = RTS_REFUSED; break; case ACS_CONGEST: reason = RTS_CONGEST; break; case ACS_PARAMETER: reason = RTS_PARAMETER; break; case ACS_OPERATION: reason = RTS_OPERATION; break; default: (void) sprintf (cp = buffer, " (%s at association control)", AcErrString (aca -> aca_reason)); case ACS_PRESENTATION: reason = RTS_ACS; break; } if (acb) { if (aca -> aca_cc > 0) return rtpktlose (acb, rti, reason, NULLCP, "%*.*s%s", aca -> aca_cc, aca -> aca_cc, aca -> aca_data, cp); else return rtpktlose (acb, rti, reason, NULLCP, "%s", cp); } else if (aca -> aca_cc > 0) return rtsaplose (rti, reason, NULLCP, "%*.*s%s", aca -> aca_cc, aca -> aca_cc, aca -> aca_data, cp); else return rtsaplose (rti, reason, NULLCP, "%s", cp); } /* \f */ int acs2rtsabort (acb, aca, rti) register struct assocblk *acb; register struct AcSAPabort *aca; struct RtSAPindication *rti; { int result; PE pe; if (aca -> aca_source != ACA_USER) { (void) acs2rtslose (acb, rti, NULLCP, aca); goto out; } if (aca -> aca_ninfo == 0) { (void) rtsaplose (rti, RTS_ABORTED, NULLCP, NULLCP); goto out; } pe = aca -> aca_info[0]; acsap_abort = ABORT_PERM, acsap_data = NULLPE; result = parse_RTS_RTABapdu (pe, 1, NULLIP, NULLVP, NULLCP); #ifdef DEBUG if (result != NOTOK && (rtsap_log -> ll_events & LLOG_PDUS)) vpdu (rtsap_log, print_RTS_RTABapdu, pe, "RTABapdu", 1); #endif (void) pe_extract (pe, acsap_data); ACAFREE (aca); if (result == NOTOK) { (void) rtsaplose (rti, RTS_PROTOCOL, "%s", PY_pepy); goto out; } switch (acsap_abort) { case ABORT_LSP: case ABORT_TMP: result = RTS_REMOTE; break; default: result = RTS_PROTOCOL; break; case ABORT_USER: result = RTS_ABORTED; break; } if (result == RTS_ABORTED) { register struct RtSAPabort *rta = &rti -> rti_abort; rti -> rti_type = RTI_ABORT; bzero ((char *) rta, sizeof *rta); rta -> rta_peer = 1; rta -> rta_reason = RTS_ABORTED; rta -> rta_udata = acsap_data; } else { (void) rtsaplose (rti, result, NULLCP, NULLCP); if (acsap_data) pe_free (acsap_data); } out: ; if (acb) { if (!(acb -> acb_flags & ACB_STICKY)) acb -> acb_fd = NOTOK; freeacblk (acb); } return NOTOK; } /* \f PSAP interface */ static int doPSdata (acb, px, rti) register struct assocblk *acb; register struct PSAPdata *px; struct RtSAPindication *rti; { unsigned int i; register char *dp; register PE pe; struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; pe = NULLPE; if (!(acb -> acb_flags & ACB_ACT) || (acb -> acb_flags & ACB_TURN) || px -> px_type != SX_NORMAL) { (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected data indication (0x%x)", px -> px_type); PXFREE (px); goto out; } pe = px -> px_info[0], px -> px_info[0] = NULLPE; PXFREE (px); if (acb -> acb_uptrans) { int result; register struct qbuf *qb; if ((qb = prim2qb (pe)) == NULL) goto congested; result = (*acb -> acb_uptrans) (acb -> acb_fd, SI_DATA, (caddr_t) qb, rti); qb_free (qb); if (result == NOTOK) goto congested; goto done; } if (pe -> pe_form == PE_FORM_CONS && pe_pullup (pe) == NOTOK) goto congested; if (acb -> acb_len > 0) { i = acb -> acb_len + pe -> pe_len; if (acb -> acb_realbase) { if ((dp = malloc (i)) == NULL) { congested: ; if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest", pa); goto out; } FREEACB (acb); return OK; } bcopy (acb -> acb_base, dp, acb -> acb_len); free (acb -> acb_realbase), acb -> acb_realbase = NULL; } else if ((dp = realloc (acb -> acb_base, i)) == NULL) goto congested; bcopy ((char *) pe -> pe_prim, dp + acb -> acb_len, pe -> pe_len); acb -> acb_base = dp; acb -> acb_len = i; } else { acb -> acb_base = (char *) pe -> pe_prim; acb -> acb_len = pe -> pe_len; pe -> pe_prim = NULLPED, pe -> pe_len = 0; acb -> acb_realbase = pe -> pe_realbase, pe -> pe_realbase = NULLCP; } done: ; pe_free (pe); return OK; out: ; if (pe) pe_free (pe); freeacblk (acb); return NOTOK; } /* \f */ static int doPStoken (acb, pt, trans, rti) register struct assocblk *acb; register struct PSAPtoken *pt; int trans; struct RtSAPindication *rti; { register PE pe; struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; if (acb -> acb_flags & ACB_TWA) switch (pt -> pt_type) { case ST_CONTROL: if (acb -> acb_flags & ACB_ACT) break; PTFREE (pt); acb -> acb_owned = pt -> pt_owned; acb -> acb_flags |= ACB_TURN; rti -> rti_type = RTI_TURN; { register struct RtSAPturn *rtu = &rti -> rti_turn; rtu -> rtu_please = 0; } return DONE; case ST_PLEASE: pe = pt -> pt_info[0]; if (parse_RTS_RTTPapdu (pe, 1, NULLIP, NULLVP, NULLCP) == NOTOK) { (void) pylose (); goto out; } PLOG (rtsap_log, print_RTS_RTTPapdu, pe, "RTTPapdu", 1); PTFREE (pt); if (trans) { if (acb -> acb_downtrans) { if ((*acb -> acb_downtrans) (acb -> acb_fd, NULLVP, NULLIP, acsap_priority, 0L, 0L, rti) == NOTOK && PActIntrRequest (acb -> acb_fd, SP_LOCAL, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActIntrRequest",pa); goto out; } } else { acb -> acb_flags |= ACB_PLEASE; acb -> acb_priority = rtsap_priority; } return OK; } rti -> rti_type = RTI_TURN; { register struct RtSAPturn *rtu = &rti -> rti_turn; rtu -> rtu_please = 1; rtu -> rtu_priority = rtsap_priority; } return DONE; default: break; } (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected token indication (0x%x)", pt -> pt_type); out: ; PTFREE (pt); freeacblk (acb); return NOTOK; } /* \f */ static int doPSsync (acb, pn, rti) register struct assocblk *acb; register struct PSAPsync *pn; struct RtSAPindication *rti; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; PNFREE (pn); if (acb -> acb_flags & ACB_ACT) switch (pn -> pn_type) { case SN_MINORIND: /* always confirm it */ if (acb -> acb_flags & ACB_TURN) break; if (acb -> acb_uptrans) { if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_SYNC, (caddr_t) pn, rti) == NOTOK) { if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest",pa); goto out; } return OK; } } if (PMinSyncResponse (acb -> acb_fd, pn -> pn_ssn, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PMinSyncResponse", pa); goto out; } return OK; case SN_MINORCNF: if (!(acb -> acb_flags & ACB_TURN)) break; acb -> acb_ack = pn -> pn_ssn; return OK; default: break; } (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected sync indication (0x%x)", pn -> pn_type); out: ; freeacblk (acb); return NOTOK; } /* \f */ static int doPSactivity (acb, pv, rti) register struct assocblk *acb; register struct PSAPactivity *pv; struct RtSAPindication *rti; { int result; register PE pe; struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; PVFREE (pv); switch (pv -> pv_type) { case SV_START: if (acb -> acb_flags & (ACB_ACT | ACB_TURN)) break; if (acb -> acb_uptrans) { if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY, (caddr_t) pv, rti) == NOTOK) { if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest", pa); goto out; } return OK; } } acb -> acb_flags |= ACB_ACT; return OK; case SV_RESUME: /* XXX: will support this later */ if (acb -> acb_flags & (ACB_ACT | ACB_TURN)) break; if (PUReportRequest (acb -> acb_fd, SP_PROCEDURAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest", pa); goto out; } acb -> acb_flags |= ACB_ACT; return OK; case SV_INTRIND: case SV_DISCIND: if (!(acb -> acb_flags & ACB_ACT) || (acb -> acb_flags & ACB_TURN)) break; if (acb -> acb_uptrans) (void) (*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY, (caddr_t) pv, rti); if ((pv -> pv_type == SV_INTRIND ? PActIntrResponse (acb -> acb_fd, pi) : PActDiscResponse (acb -> acb_fd, pi)) == NOTOK) { (void) ps2rtslose (acb, rti, pv -> pv_type == SV_INTRIND ? "PActIntrResponse" : "PActDiscResponse", pa); goto out; } FREEACB (acb); acb -> acb_flags &= ~ACB_ACT; return OK; case SV_INTRCNF: case SV_DISCCNF: if (!(acb -> acb_flags & ACB_ACT) || !(acb -> acb_flags & ACB_TURN)) break; acb -> acb_flags &= ~ACB_ACT; (void) rtsaplose (rti, acb -> acb_flags & ACB_TIMER ? RTS_TIMER : RTS_TRANSFER, NULLCP, NULLCP); return OK; case SV_ENDIND: if (!(acb -> acb_flags & ACB_ACT) || (acb -> acb_flags & ACB_TURN)) break; if (acb -> acb_uptrans) { if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY, (caddr_t) pv, rti) == NOTOK) { if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest", pa); goto out; } return OK; } pe = NULLPE; goto end_it; } if (acb -> acb_base) { if (pe = ssdu2pe (acb -> acb_base, acb -> acb_len, acb -> acb_realbase ? acb -> acb_realbase : acb -> acb_base, &result)) acb -> acb_realbase = acb -> acb_base = NULL; } else pe = NULLPE, result = PS_ERR_EOF; FREEACB (acb); if (pe == NULLPE) { if (result != PS_ERR_NMEM) { (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "%s", ps_error (result)); goto out; } if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PUReportRequest", pa); goto out; } return OK; } end_it: ; if (PActEndResponse (acb -> acb_fd, NULLPEP, 0, pi) == NOTOK) { (void) ps2rtslose (acb, rti, "PActEndResponse", pa); if (pe) pe_free (pe); goto out; } acb -> acb_flags &= ~ACB_ACT; rti -> rti_type = RTI_TRANSFER; { register struct RtSAPtransfer *rtt = &rti -> rti_transfer; rtt -> rtt_data = pe; } return DONE; case SV_ENDCNF: if (!(acb -> acb_flags & ACB_ACT) || !(acb -> acb_flags & ACB_TURN)) break; acb -> acb_flags &= ~ACB_ACT; return OK; default: break; } (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected activity indication (0x%x)", pv -> pv_type); out: ; freeacblk (acb); return NOTOK; } /* \f */ static int doPSreport (acb, pp, rti) register struct assocblk *acb; register struct PSAPreport *pp; struct RtSAPindication *rti; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; PPFREE (pp); if (!pp -> pp_peer) { if (!(acb -> acb_flags & ACB_ACT)) goto out2; if (!(acb -> acb_flags & ACB_TURN)) return OK; /* XXX: should try lots of things here, based on how many checkpoints have been acknowledged, but, for now we'll treate everything as severe... */ (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unrecoverable provider-initiated exception report"); } if ((acb -> acb_flags & ACB_ACT) || !(acb -> acb_flags & ACB_TURN)) { out2: ; (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected exception report indication (0x%x)", pp -> pp_peer); goto out1; } /* XXX: should try lots of things here, based on pp_reason, but, for now we'll treat everything as SP_NOREASON... */ if (acb -> acb_uptrans) (void) (*acb -> acb_uptrans) (acb -> acb_fd, SI_REPORT, (caddr_t) pp, rti); if (PActDiscRequest (acb -> acb_fd, SP_NOREASON, pi) != NOTOK) return OK; (void) ps2rtslose (acb, rti, "PActDiscRequest", pa); out1: ; freeacblk (acb); return NOTOK; } /* \f */ static int doPSfinish (acb, pf, rti) register struct assocblk *acb; struct PSAPfinish *pf; struct RtSAPindication *rti; { struct AcSAPindication acis; register struct AcSAPabort *aca = &acis.aci_abort; if (((acb -> acb_flags & ACB_INIT) && (acb -> acb_flags & ACB_TWA)) || (acb -> acb_flags & ACB_TURN)) { (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "association management botched"); PFFREE (pf); goto out; } if (acb -> acb_flags & ACB_ACT) { (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "unexpected release indication"); PFFREE (pf); goto out; } rti -> rti_type = RTI_FINISH; { register struct AcSAPfinish *acf = &rti -> rti_finish; if (AcFINISHser (acb -> acb_fd, pf, &acis) == NOTOK) return acs2rtslose (acb, rti, "AcFINISHser", aca); *acf = acis.aci_finish; /* struct copy */ } return DONE; out: ; freeacblk (acb); return NOTOK; } /* \f */ static int doPSabort (acb, pa, rti) register struct assocblk *acb; register struct PSAPabort *pa; struct RtSAPindication *rti; { struct AcSAPindication acis; register struct AcSAPabort *aca = &acis.aci_abort; if (!pa -> pa_peer && pa -> pa_reason == PC_TIMER) return rtsaplose (rti, RTS_TIMER, NULLCP, NULLCP); if (AcABORTser (acb -> acb_fd, pa, &acis) == NOTOK) { (void) acs2rtslose (acb, rti, "AcABORTser", aca); if (!(acb -> acb_flags & ACB_STICKY)) acb -> acb_fd = NOTOK; freeacblk (acb); return NOTOK; } return acs2rtsabort (acb, aca, rti); } /* \f */ static int psDATAser (sd, px) int sd; register struct PSAPdata *px; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; if (doPSdata (acb, px, rti) != OK) (*handler) (sd, rti); } /* \f */ static int psTOKENser (sd, pt) int sd; register struct PSAPtoken *pt; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; if (doPStoken (acb, pt, 0, rti) != OK) (*handler) (sd, rti); } /* \f */ static int psSYNCser (sd, pn) int sd; register struct PSAPsync *pn; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; if (doPSsync (acb, pn, rti) != OK) (*handler) (sd, rti); } /* \f */ static int psACTIVITYser (sd, pv) int sd; register struct PSAPactivity *pv; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; if (doPSactivity (acb, pv, rti) != OK) (*handler) (sd, rti); } /* \f */ static int psREPORTser (sd, pp) int sd; register struct PSAPreport *pp; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; if (doPSreport (acb, pp, rti) != OK) (*handler) (sd, rti); } /* \f */ static int psFINISHser (sd, pf) int sd; struct PSAPfinish *pf; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; (void) doPSfinish (acb, pf, rti); (*handler) (sd, rti); } /* \f */ static int psABORTser (sd, pa) int sd; register struct PSAPabort *pa; { IFP handler; register struct assocblk *acb; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; if ((acb = findacblk (sd)) == NULL) return; handler = acb -> acb_rtsindication; (void) doPSabort (acb, pa, rti); (*handler) (sd, rti); } /* \f */ int ps2rtslose (acb, rti, event, pa) register struct assocblk *acb; register struct RtSAPindication *rti; char *event; register struct PSAPabort *pa; { int reason; char *cp, buffer[BUFSIZ]; if (event) SLOG (rtsap_log, LLOG_EXCEPTIONS, NULLCP, (pa -> pa_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event, PErrString (pa -> pa_reason), pa -> pa_cc, pa -> pa_cc, pa -> pa_data)); cp = ""; switch (pa -> pa_reason) { case PC_ADDRESS: reason = RTS_ADDRESS; break; case PC_REFUSED: reason = RTS_REFUSED; break; case PC_CONGEST: reason = RTS_CONGEST; break; default: (void) sprintf (cp = buffer, " (%s at presentation)", PErrString (pa -> pa_reason)); case PC_SESSION: reason = RTS_PRESENTATION; break; } if (pa -> pa_cc > 0) return rtpktlose (acb, rti, reason, NULLCP, "%*.*s%s", pa -> pa_cc, pa -> pa_cc, pa -> pa_data, cp); else return rtpktlose (acb, rti, reason, NULLCP, "%s", *cp ? cp + 1 : cp); }