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