BSD 4_3_Net_2 release
[unix-history] / usr / src / contrib / isode / rtsap / rt2ps.c
CommitLineData
9e8e5516
C
1/* rt2ps.c - RTPM: AcSAP/PSAP interface */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/rtsap/RCS/rt2ps.c,v 7.7 91/02/22 09:42:15 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/rtsap/RCS/rt2ps.c,v 7.7 91/02/22 09:42:15 mrose Interim $
9 *
10 *
11 * $Log: rt2ps.c,v $
12 * Revision 7.7 91/02/22 09:42:15 mrose
13 * Interim 6.8
14 *
15 * Revision 7.6 91/01/24 14:50:03 mrose
16 * update
17 *
18 * Revision 7.5 90/11/21 11:32:32 mrose
19 * sun
20 *
21 * Revision 7.4 90/10/23 20:43:57 mrose
22 * update
23 *
24 * Revision 7.3 90/07/27 08:47:36 mrose
25 * update
26 *
27 * Revision 7.2 90/07/01 21:06:46 mrose
28 * pepsy
29 *
30 * Revision 6.2 89/06/23 11:28:32 mrose
31 * touch-up
32 *
33 * Revision 6.1 89/05/31 15:02:22 mrose
34 * sek
35 *
36 * Revision 6.0 89/03/18 23:43:06 mrose
37 * Release 5.0
38 *
39 */
40
41/*
42 * NOTICE
43 *
44 * Acquisition, use, and distribution of this module and related
45 * materials are subject to the restrictions of a license agreement.
46 * Consult the Preface in the User's Manual for the full terms of
47 * this agreement.
48 *
49 */
50
51
52/* LINTLIBRARY */
53
54#include <stdio.h>
55#include "RTS-types.h"
56#include "rtpkt.h"
57#include "tailor.h"
58
59/* \f DATA */
60
61int psDATAser (), psTOKENser (), psSYNCser (), psACTIVITYser (),
62 psREPORTser (), psFINISHser (), psABORTser ();
63
64
65long time ();
66
67/* \f */
68
69int rt2pspturn (acb, priority, rti)
70register struct assocblk *acb;
71int priority;
72register struct RtSAPindication *rti;
73{
74 int result;
75 PE pe;
76 struct PSAPindication pis;
77 struct PSAPindication *pi = &pis;
78 struct PSAPabort *pa = &pi -> pi_abort;
79
80 if (!(acb -> acb_flags & ACB_TWA))
81 return rtsaplose (rti, RTS_OPERATION, NULLCP,
82 "mode of association is monologue");
83 if (acb -> acb_flags & ACB_TURN)
84 return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn owned by you");
85
86/* begin RTTP APDU */
87 if ((pe = int2prim (priority)) == NULLPE)
88 return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP);
89 pe -> pe_context = acb -> acb_rtsid;
90/* end RTTP APDU */
91
92 PLOGP (rtsap_log,RTS_RTSE__apdus, pe, "RTTPapdu", 0);
93
94 result = PPTokenRequest (acb -> acb_fd, ST_DAT_TOKEN, &pe, 1, pi);
95
96 pe_free (pe);
97
98 if (result == NOTOK) {
99 (void) ps2rtslose (acb, rti, "PPTokenRequest", pa);
100 freeacblk (acb);
101 }
102
103 return result;
104}
105
106/* \f */
107
108int rt2psgturn (acb, rti)
109register struct assocblk *acb;
110register struct RtSAPindication *rti;
111{
112 struct PSAPindication pis;
113 struct PSAPindication *pi = &pis;
114 struct PSAPabort *pa = &pi -> pi_abort;
115
116 if (!(acb -> acb_flags & ACB_TWA))
117 return rtsaplose (rti, RTS_OPERATION, NULLCP,
118 "mode of association is monologue");
119 if (!(acb -> acb_flags & ACB_TURN))
120 return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn not owned by you");
121 if (acb -> acb_flags & ACB_ACT)
122 return rtsaplose (rti, RTS_OPERATION, NULLCP, "transfer in progress");
123
124 if (PGControlRequest (acb -> acb_fd, pi) == NOTOK) {
125 (void) ps2rtslose (acb, rti, "PGControlRequest", pa);
126 freeacblk (acb);
127 return NOTOK;
128 }
129
130 acb -> acb_flags &= ~(ACB_TURN | ACB_PLEASE);
131
132 return OK;
133}
134
135/* \f */
136
137int rt2pstrans (acb, data, secs, rti)
138register struct assocblk *acb;
139register PE data;
140int secs;
141register struct RtSAPindication *rti;
142{
143 register int cc,
144 size;
145 int result,
146 len;
147 long clock,
148 limit;
149 register char *dp;
150 char *base;
151 PE pe;
152 struct SSAPactid ids;
153 register struct SSAPactid *id = &ids;
154 struct PSAPindication pis;
155 struct PSAPindication *pi = &pis;
156 struct PSAPabort *pa = &pi -> pi_abort;
157 struct RtSAPabort *rta = &rti -> rti_abort;
158
159 if (!(acb -> acb_flags & ACB_TURN))
160 return rtsaplose (rti, RTS_OPERATION, NULLCP, "turn not owned by you");
161 if (acb -> acb_flags & ACB_ACT)
162 return rtsaplose (rti, RTS_OPERATION, NULLCP, "transfer in progress");
163
164 if ((pe = int2prim (acb -> acb_actno)) == NULLPE)
165 return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP);
166 result = pe2ssdu (pe, &base, &len);
167 pe_free (pe);
168 if (result == NOTOK)
169 return rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP);
170 bcopy (base, id -> sd_data, (int) (id -> sd_len = len));
171 free (base);
172 base = NULL;
173
174 if (pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_OCTS)) {
175 pe -> pe_inline = 1;
176 pe -> pe_context = acb -> acb_rtsid;
177 }
178 else {
179 (void) rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP);
180 goto out;
181 }
182 if (PActStartRequest (acb -> acb_fd, id, NULLPEP, 0, pi) == NOTOK) {
183 (void) ps2rtslose (acb, rti, "PActStartRequest", pa);
184 goto out;
185 }
186
187 acb -> acb_flags |= ACB_ACT;
188
189 if (data && pe2ssdu (data, &base, &len) == NOTOK) {
190 (void) rtsaplose (rti, RTS_CONGEST, NULLCP, NULLCP);
191 goto out;
192 }
193
194 result = OK;
195 if (acb -> acb_ckpoint == 0) {
196 if (data == NULLPE) {
197 if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, 0, 0L,
198 0L, rti) == NOTOK) {
199bad_trans: ;
200 if (PActDiscRequest (acb -> acb_fd, SP_LOCAL, pi) == NOTOK) {
201 (void) ps2rtslose (acb, rti, "PActDiscRequest", pa);
202 goto out;
203 }
204 goto done;
205 }
206 if (len == 0) {
207 base = NULL;
208 goto done;
209 }
210 }
211
212 pe -> pe_prim = (PElementData) base, pe -> pe_len = (PElementLen) len;
213
214 if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) {
215 (void) ps2rtslose (acb, rti, "PDataRequest", pa);
216 goto out;
217 }
218 }
219 else {
220 size = acb -> acb_ckpoint << 10; /* units of 1024 octets */
221 if (acb -> acb_ssdusize >= 0x0100) /* at least 256 octets */
222 size = min (size, acb -> acb_ssdusize);
223 acb -> acb_ssn = acb -> acb_ack = 0L;
224 if (secs != NOTOK) {
225 (void) time (&limit);
226 limit += secs;
227 }
228
229 if (data == NULLPE) {
230 if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, size,
231 acb -> acb_ssn, acb -> acb_ack,
232 rti) == NOTOK)
233 goto bad_trans;
234 if (len == 0) {
235 base = NULL;
236 goto done;
237 }
238 }
239
240 dp = base, cc = min (len, size);
241 pe -> pe_prim = (PElementData) dp, pe -> pe_len = (PElementLen) cc;
242 if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) {
243 (void) ps2rtslose (acb, rti, "PDataRequest", pa);
244 goto out;
245 }
246
247 for (dp += cc, len -= cc;
248 data == NULLPE || len > 0;
249 dp += cc, len -= cc) {
250 if (data == NULLPE && len == 0) {
251 if ((*acb -> acb_downtrans) (acb -> acb_fd, &base, &len, size,
252 acb -> acb_ssn, acb -> acb_ack,
253 rti) == NOTOK)
254 goto bad_trans;
255 if (len == 0) {
256 base = NULL;
257 break;
258 }
259 dp = base;
260 }
261
262 if (secs != NOTOK) {
263 (void) time (&clock);
264 if (limit < clock) {
265 result = NOTOK;
266 break;
267 }
268 }
269
270 if (PMinSyncRequest (acb -> acb_fd, SYNC_CONFIRM,
271 &acb -> acb_ssn, NULLPEP, 0, pi) == NOTOK) {
272 (void) ps2rtslose (acb, rti, "PMinSyncRequest", pa);
273 goto out;
274 }
275
276 if (acb -> acb_ssn - acb -> acb_ack > acb -> acb_window) {
277 do {
278 if (RtWaitRequestAux (acb, NOTOK, 1, rti) == NOTOK) {
279 if (RTS_FATAL (rta -> rta_reason))
280 acb = NULLACB;
281 goto out;
282 }
283 }
284 while (acb -> acb_ssn - acb -> acb_ack > acb -> acb_window);
285
286#ifdef notdef
287 /* avoid silly window syndrome */
288 while (acb -> acb_ssn != acb -> acb_ack)
289 if (RtWaitRequestAux (acb, OK, 1, rti) == NOTOK)
290 if (rta -> rta_reason != RTS_TIMER) {
291 if (RTS_FATAL (rta -> rta_reason))
292 acb = NULLACB;
293 goto out;
294 }
295 else
296 break;
297#endif
298 }
299
300 cc = min (len, size);
301 pe -> pe_prim = (PElementData) dp, pe -> pe_len = cc;
302 if (PDataRequest (acb -> acb_fd, &pe, 1, pi) == NOTOK) {
303 (void) ps2rtslose (acb, rti, "PDataRequest", pa);
304 goto out;
305 }
306 }
307 }
308 if (data)
309 free (base);
310 base = NULL;
311
312done: ;
313 switch (result) {
314 case OK:
315 if (PActEndRequest (acb -> acb_fd, &acb -> acb_ssn, NULLPEP, 0,
316 pi) == NOTOK) {
317 (void) ps2rtslose (acb, rti, "PActEndRequest", pa);
318 goto out;
319 }
320 break;
321
322 default:
323 acb -> acb_flags |= ACB_TIMER;
324 if (PActDiscRequest (acb -> acb_fd, SP_LOCAL, pi) == NOTOK) {
325 (void) ps2rtslose (acb, rti, "PActDiscRequest", pa);
326 goto out;
327 }
328 break;
329 }
330
331 while (acb -> acb_flags & ACB_ACT)
332 if (RtWaitRequestAux (acb, NOTOK, 1, rti) == NOTOK) {
333 if (RTS_FATAL (rta -> rta_reason))
334 acb = NULLACB;
335 goto out;
336 }
337
338 acb -> acb_flags &= ~ACB_TIMER;
339 acb -> acb_actno++;
340
341 if (pe)
342 pe_free (pe);
343
344 return result;
345
346out: ;
347 if (data && base)
348 free (base);
349 if (pe)
350 pe_free (pe);
351 if (acb)
352 freeacblk (acb);
353
354 return NOTOK;
355}
356
357/* \f */
358
359int rt2pswait (acb, secs, trans, rti)
360register struct assocblk *acb;
361int secs,
362 trans;
363register struct RtSAPindication *rti;
364{
365 int result;
366 struct PSAPdata pxs;
367 register struct PSAPdata *px = &pxs;
368 struct PSAPindication pis;
369 register struct PSAPindication *pi = &pis;
370
371 for (;;) {
372 switch (result = PReadRequest (acb -> acb_fd, px, secs, pi)) {
373 case NOTOK:
374 return doPSabort (acb, &pi -> pi_abort, rti);
375
376 case OK:
377 if (doPSdata (acb, px, rti) == NOTOK)
378 return NOTOK;
379 continue;
380
381 case DONE:
382 switch (pi -> pi_type) {
383 case PI_TOKEN:
384 if ((result = doPStoken (acb, &pi -> pi_token, trans,
385 rti)) != OK)
386 return result;
387 continue;
388
389 case PI_SYNC:
390 if ((result = doPSsync (acb, &pi -> pi_sync, rti)) != OK
391 || trans)
392 return result;
393 continue;
394
395 case PI_ACTIVITY:
396 if ((result = doPSactivity (acb, &pi -> pi_activity, rti)) != OK
397 || trans)
398 return (result != DONE ? result : OK);
399 continue;
400
401 case PI_REPORT:
402 if (doPSreport (acb, &pi -> pi_report, rti) == NOTOK)
403 return NOTOK;
404 continue;
405
406 case PI_FINISH:
407 return doPSfinish (acb, &pi -> pi_finish, rti);
408
409 default:
410 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
411 "unknown indication (0x%x) from presentation",
412 pi -> pi_type);
413 break;
414 }
415 break;
416
417 default:
418 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
419 "unexpected return from PReadRequest=%d", result);
420 break;
421 }
422 break;
423 }
424
425 freeacblk (acb);
426 return NOTOK;
427}
428
429/* \f define vectors for INDICATION events */
430
431#define e(i) (indication ? (i) : NULLIFP)
432
433
434int rt2psasync (acb, indication, rti)
435register struct assocblk *acb;
436IFP indication;
437struct RtSAPindication *rti;
438{
439 struct PSAPindication pis;
440 struct PSAPindication *pi = &pis;
441 struct PSAPabort *pa = &pi -> pi_abort;
442
443 if (acb -> acb_rtsindication = indication)
444 acb -> acb_flags |= ACB_ASYN;
445 else
446 acb -> acb_flags &= ~ACB_ASYN;
447
448 if (PSetIndications (acb -> acb_fd, e (psDATAser), e (psTOKENser),
449 e (psSYNCser), e (psACTIVITYser), e (psREPORTser),
450 e (psFINISHser), e (psABORTser), pi) == NOTOK) {
451 acb -> acb_flags &= ~ACB_ASYN;
452 switch (pa -> pa_reason) {
453 case PC_WAITING:
454 return rtsaplose (rti, RTS_WAITING, NULLCP, NULLCP);
455
456 default:
457 (void) ps2rtslose (acb, rti, "PSetIndications", pa);
458 freeacblk (acb);
459 return NOTOK;
460 }
461 }
462
463 return OK;
464}
465
466#undef e
467
468/* \f map association descriptors for select() */
469
470int rt2psmask (acb, mask, nfds, rti)
471register struct assocblk *acb;
472fd_set *mask;
473int *nfds;
474struct RtSAPindication *rti;
475{
476 struct PSAPindication pis;
477 struct PSAPindication *pi = &pis;
478 struct PSAPabort *pa = &pi -> pi_abort;
479
480 if (PSelectMask (acb -> acb_fd, mask, nfds, pi) == NOTOK)
481 switch (pa -> pa_reason) {
482 case PC_WAITING:
483 return rtsaplose (rti, RTS_WAITING, NULLCP, NULLCP);
484
485 default:
486 (void) ps2rtslose (acb, rti, "PSelectMask", pa);
487 freeacblk (acb);
488 return NOTOK;
489 }
490
491 return OK;
492}
493
494/* \f protocol-level abort */
495
496int rt2pslose (acb, result)
497register struct assocblk *acb;
498int result;
499{
500 PE pe;
501 struct AcSAPindication acis;
502
503/* begin RTAB APDU */
504 if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, 22))
505 && set_add (pe, num2prim ((integer) result, PE_CLASS_CONT,
506 RTAB_REASON)) != NOTOK) {
507 pe -> pe_context = acb -> acb_rtsid;
508
509 PLOGP (rtsap_log,RTS_RTSE__apdus, pe, "RTABapdu", 0);
510
511 (void) AcUAbortRequest (acb -> acb_fd, &pe, 1, &acis);
512 pe_free (pe);
513 }
514/* end RTAB APDU */
515}
516
517/* \f AcSAP interface */
518
519int acs2rtslose (acb, rti, event, aca)
520register struct assocblk *acb;
521register struct RtSAPindication *rti;
522char *event;
523register struct AcSAPabort *aca;
524{
525 int reason;
526 char *cp,
527 buffer[BUFSIZ];
528
529 if (event)
530 SLOG (rtsap_log, LLOG_EXCEPTIONS, NULLCP,
531 (aca -> aca_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event,
532 AcErrString (aca -> aca_reason), aca -> aca_cc, aca -> aca_cc,
533 aca -> aca_data));
534
535 cp = "";
536 switch (aca -> aca_reason) {
537 case ACS_ADDRESS:
538 reason = RTS_ADDRESS;
539 break;
540
541 case ACS_REFUSED:
542 reason = RTS_REFUSED;
543 break;
544
545 case ACS_CONGEST:
546 reason = RTS_CONGEST;
547 break;
548
549 case ACS_PARAMETER:
550 reason = RTS_PARAMETER;
551 break;
552
553 case ACS_OPERATION:
554 reason = RTS_OPERATION;
555 break;
556
557 default:
558 (void) sprintf (cp = buffer, " (%s at association control)",
559 AcErrString (aca -> aca_reason));
560 case ACS_PRESENTATION:
561 reason = RTS_ACS;
562 break;
563 }
564
565 if (acb) {
566 if (aca -> aca_cc > 0)
567 return rtpktlose (acb, rti, reason, NULLCP, "%*.*s%s",
568 aca -> aca_cc, aca -> aca_cc, aca -> aca_data, cp);
569 else
570 return rtpktlose (acb, rti, reason, NULLCP, "%s", cp);
571 }
572 else
573 if (aca -> aca_cc > 0)
574 return rtsaplose (rti, reason, NULLCP, "%*.*s%s",
575 aca -> aca_cc, aca -> aca_cc, aca -> aca_data, cp);
576 else
577 return rtsaplose (rti, reason, NULLCP, "%s", cp);
578}
579
580/* \f */
581
582int acs2rtsabort (acb, aca, rti)
583register struct assocblk *acb;
584register struct AcSAPabort *aca;
585struct RtSAPindication *rti;
586{
587 int result;
588 PE pe;
589 struct type_RTS_RTSE__apdus *rtpdu = NULL;
590 struct type_RTS_RTABapdu *prtab;
591
592 if (aca -> aca_source != ACA_USER) {
593 (void) acs2rtslose (acb, rti, NULLCP, aca);
594 goto out;
595 }
596
597 if (aca -> aca_ninfo == 0) {
598 (void) rtsaplose (rti, RTS_ABORTED, NULLCP, NULLCP);
599 goto out;
600 }
601
602 pe = aca -> aca_info[0];
603 /* acsap_abort = ABORT_PERM, acsap_data = NULLPE; */
604 result = decode_RTS_RTSE__apdus (pe, 1, NULLIP, NULLVP, &rtpdu);
605
606#ifdef DEBUG
607 if (result != NOTOK && (rtsap_log -> ll_events & LLOG_PDUS))
608 pvpdu (rtsap_log, print_RTS_RTSE__apdus_P, pe, "RTABapdu", 1);
609#endif
610 if (result != NOTOK) {
611 if (rtpdu -> offset != type_RTS_RTSE__apdus_rtab__apdu) {
612 (void) rtsaplose (rti, RTS_PROTOCOL, "Unexpected PDU");
613 ACAFREE (aca);
614 goto out;
615 }
616 prtab = rtpdu -> un.rtab__apdu;
617
618 if (prtab->userdataAB != NULLPE)
619 (void) pe_extract (pe, prtab->userdataAB);
620 else
621 pe = NULLPE;
622 }
623 ACAFREE (aca);
624
625 if (result == NOTOK) {
626 (void) rtsaplose (rti, RTS_PROTOCOL, "%s", PY_pepy);
627 goto out;
628 }
629 if (prtab->abortReason) {
630 result = prtab -> abortReason -> parm;
631 } else {
632 result = ABORT_PERM;
633 }
634 switch (result) {
635 case ABORT_LSP:
636 case ABORT_TMP:
637 result = RTS_REMOTE;
638 break;
639
640 default:
641 result = RTS_PROTOCOL;
642 break;
643
644 case ABORT_USER:
645 result = RTS_ABORTED;
646 break;
647 }
648 if (result == RTS_ABORTED) {
649 register struct RtSAPabort *rta = &rti -> rti_abort;
650
651 rti -> rti_type = RTI_ABORT;
652 bzero ((char *) rta, sizeof *rta);
653
654 rta -> rta_peer = 1;
655 rta -> rta_reason = RTS_ABORTED;
656 rta -> rta_udata = prtab->userdataAB;
657 prtab->userdataAB = NULLPE;
658 }
659 else {
660 (void) rtsaplose (rti, result, NULLCP, NULLCP);
661 }
662
663out: ;
664 if (rtpdu)
665 free_RTS_RTSE__apdus (rtpdu);
666 if (acb) {
667 if (!(acb -> acb_flags & ACB_STICKY))
668 acb -> acb_fd = NOTOK;
669 freeacblk (acb);
670 }
671
672 return NOTOK;
673}
674
675/* \f PSAP interface */
676
677static int doPSdata (acb, px, rti)
678register struct assocblk *acb;
679register struct PSAPdata *px;
680struct RtSAPindication *rti;
681{
682 unsigned int i;
683 register char *dp;
684 register PE pe;
685 struct PSAPindication pis;
686 register struct PSAPindication *pi = &pis;
687 register struct PSAPabort *pa = &pi -> pi_abort;
688
689 pe = NULLPE;
690 if (!(acb -> acb_flags & ACB_ACT)
691 || (acb -> acb_flags & ACB_TURN)
692 || px -> px_type != SX_NORMAL) {
693 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
694 "unexpected data indication (0x%x)", px -> px_type);
695 PXFREE (px);
696 goto out;
697 }
698
699 pe = px -> px_info[0], px -> px_info[0] = NULLPE;
700 PXFREE (px);
701
702 if (acb -> acb_uptrans) {
703 int result;
704 register struct qbuf *qb;
705
706 if ((qb = prim2qb (pe)) == NULL)
707 goto congested;
708 result = (*acb -> acb_uptrans) (acb -> acb_fd, SI_DATA, (caddr_t) qb,
709 rti);
710 qb_free (qb);
711 if (result == NOTOK)
712 goto congested;
713 goto done;
714 }
715
716 if (pe -> pe_form == PE_FORM_CONS && pe_pullup (pe) == NOTOK)
717 goto congested;
718
719 if (acb -> acb_len > 0) {
720 i = acb -> acb_len + pe -> pe_len;
721 if (acb -> acb_realbase) {
722 if ((dp = malloc (i)) == NULL) {
723 congested: ;
724 if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi)
725 == NOTOK) {
726 (void) ps2rtslose (acb, rti, "PUReportRequest", pa);
727 goto out;
728 }
729 FREEACB (acb);
730 return OK;
731 }
732 bcopy (acb -> acb_base, dp, acb -> acb_len);
733 free (acb -> acb_realbase), acb -> acb_realbase = NULL;
734 }
735 else
736 if ((dp = realloc (acb -> acb_base, i)) == NULL)
737 goto congested;
738 bcopy ((char *) pe -> pe_prim, dp + acb -> acb_len, pe -> pe_len);
739 acb -> acb_base = dp;
740 acb -> acb_len = i;
741 }
742 else {
743 if (pe -> pe_inline) {
744 if ((acb -> acb_realbase = acb -> acb_base =
745 malloc ((unsigned int) pe -> pe_len))
746 == NULL)
747 goto congested;
748 bcopy (pe -> pe_prim, acb -> acb_base,
749 acb -> acb_len = pe -> pe_len);
750 }
751 else {
752 acb -> acb_base = (char *) pe -> pe_prim;
753 acb -> acb_len = pe -> pe_len;
754 pe -> pe_prim = NULLPED, pe -> pe_len = 0;
755 acb -> acb_realbase = pe -> pe_realbase,
756 pe -> pe_realbase = NULLCP;
757 }
758 }
759done: ;
760 pe_free (pe);
761 return OK;
762
763out: ;
764 if (pe)
765 pe_free (pe);
766
767 freeacblk (acb);
768 return NOTOK;
769}
770
771/* \f */
772
773static int doPStoken (acb, pt, trans, rti)
774register struct assocblk *acb;
775register struct PSAPtoken *pt;
776int trans;
777struct RtSAPindication *rti;
778{
779 register PE pe;
780 struct PSAPindication pis;
781 register struct PSAPindication *pi = &pis;
782 register struct PSAPabort *pa = &pi -> pi_abort;
783 struct type_RTS_RTSE__apdus *rtpdu;
784 struct type_RTS_RTTPapdu *prttp;
785
786 if (acb -> acb_flags & ACB_TWA)
787 switch (pt -> pt_type) {
788 case ST_CONTROL:
789 if (acb -> acb_flags & ACB_ACT)
790 break;
791
792 PTFREE (pt);
793
794 acb -> acb_owned = pt -> pt_owned;
795 acb -> acb_flags |= ACB_TURN;
796
797 rti -> rti_type = RTI_TURN;
798 {
799 register struct RtSAPturn *rtu = &rti -> rti_turn;
800
801 rtu -> rtu_please = 0;
802 }
803 return DONE;
804
805 case ST_PLEASE:
806 pe = pt -> pt_info[0];
807 if (decode_RTS_RTSE__apdus (pe, 1, NULLIP, NULLVP, &rtpdu) == NOTOK) {
808 (void) pylose ();
809 goto out;
810 }
811
812 PLOGP (rtsap_log,RTS_RTSE__apdus, pe, "RTTPapdu", 1);
813 if (rtpdu -> offset != type_RTS_RTSE__apdus_rttp__apdu) {
814 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
815 "unexpected PDU");
816 free_RTS_RTSE__apdus (rtpdu);
817 goto out;
818 }
819 prttp = rtpdu -> un.rttp__apdu;
820 PTFREE (pt);
821
822 if (trans) {
823 if (acb -> acb_downtrans) {
824 if ((*acb -> acb_downtrans) (acb -> acb_fd, NULLVP,
825 /* surely this should be rtsap_priority NULLIP, acsap_priority,*/
826 NULLIP, prttp -> parm,
827 0L, 0L, rti) == NOTOK
828 && PActIntrRequest (acb -> acb_fd, SP_LOCAL,
829 pi) == NOTOK) {
830 (void) ps2rtslose (acb, rti, "PActIntrRequest",pa);
831 free_RTS_RTSE__apdus (rtpdu);
832 goto out;
833 }
834 }
835 else {
836 acb -> acb_flags |= ACB_PLEASE;
837 acb -> acb_priority = prttp -> parm;
838 }
839 free_RTS_RTSE__apdus (rtpdu);
840 return OK;
841 }
842
843 rti -> rti_type = RTI_TURN;
844 {
845 register struct RtSAPturn *rtu = &rti -> rti_turn;
846
847 rtu -> rtu_please = 1;
848 rtu -> rtu_priority = prttp -> parm;
849 }
850 free_RTS_RTSE__apdus (rtpdu);
851 return DONE;
852
853 default:
854 break;
855 }
856 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
857 "unexpected token indication (0x%x)", pt -> pt_type);
858
859out: ;
860 PTFREE (pt);
861 freeacblk (acb);
862
863 return NOTOK;
864}
865
866/* \f */
867
868static int doPSsync (acb, pn, rti)
869register struct assocblk *acb;
870register struct PSAPsync *pn;
871struct RtSAPindication *rti;
872{
873 struct PSAPindication pis;
874 register struct PSAPindication *pi = &pis;
875 register struct PSAPabort *pa = &pi -> pi_abort;
876
877 PNFREE (pn);
878
879 if (acb -> acb_flags & ACB_ACT)
880 switch (pn -> pn_type) {
881 case SN_MINORIND: /* always confirm it */
882 if (acb -> acb_flags & ACB_TURN)
883 break;
884 if (acb -> acb_uptrans) {
885 if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_SYNC,
886 (caddr_t) pn, rti) == NOTOK) {
887 if (PUReportRequest (acb -> acb_fd, SP_LOCAL,
888 NULLPEP, 0, pi) == NOTOK) {
889 (void) ps2rtslose (acb, rti, "PUReportRequest",pa);
890 goto out;
891 }
892 return OK;
893 }
894 }
895 if (PMinSyncResponse (acb -> acb_fd, pn -> pn_ssn,
896 NULLPEP, 0, pi) == NOTOK) {
897 (void) ps2rtslose (acb, rti, "PMinSyncResponse", pa);
898 goto out;
899 }
900 return OK;
901
902 case SN_MINORCNF:
903 if (!(acb -> acb_flags & ACB_TURN))
904 break;
905 acb -> acb_ack = pn -> pn_ssn;
906 return OK;
907
908 default:
909 break;
910 }
911 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
912 "unexpected sync indication (0x%x)", pn -> pn_type);
913
914out: ;
915 freeacblk (acb);
916
917 return NOTOK;
918}
919
920/* \f */
921
922static int doPSactivity (acb, pv, rti)
923register struct assocblk *acb;
924register struct PSAPactivity *pv;
925struct RtSAPindication *rti;
926{
927 int result;
928 register PE pe;
929 struct PSAPindication pis;
930 register struct PSAPindication *pi = &pis;
931 register struct PSAPabort *pa = &pi -> pi_abort;
932
933 PVFREE (pv);
934
935 switch (pv -> pv_type) {
936 case SV_START:
937 if (acb -> acb_flags & (ACB_ACT | ACB_TURN))
938 break;
939 if (acb -> acb_uptrans) {
940 if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY,
941 (caddr_t) pv, rti) == NOTOK) {
942 if (PUReportRequest (acb -> acb_fd, SP_LOCAL,
943 NULLPEP, 0, pi) == NOTOK) {
944 (void) ps2rtslose (acb, rti, "PUReportRequest", pa);
945 goto out;
946 }
947 return OK;
948 }
949 }
950 acb -> acb_flags |= ACB_ACT;
951 return OK;
952
953 case SV_RESUME: /* XXX: will support this later */
954 if (acb -> acb_flags & (ACB_ACT | ACB_TURN))
955 break;
956 if (PUReportRequest (acb -> acb_fd, SP_PROCEDURAL, NULLPEP, 0,
957 pi) == NOTOK) {
958 (void) ps2rtslose (acb, rti, "PUReportRequest", pa);
959 goto out;
960 }
961 acb -> acb_flags |= ACB_ACT;
962 return OK;
963
964 case SV_INTRIND:
965 case SV_DISCIND:
966 if (!(acb -> acb_flags & ACB_ACT)
967 || (acb -> acb_flags & ACB_TURN))
968 break;
969 if (acb -> acb_uptrans)
970 (void) (*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY,
971 (caddr_t) pv, rti);
972 if ((pv -> pv_type == SV_INTRIND
973 ? PActIntrResponse (acb -> acb_fd, pi)
974 : PActDiscResponse (acb -> acb_fd, pi)) == NOTOK) {
975 (void) ps2rtslose (acb, rti, pv -> pv_type == SV_INTRIND
976 ? "PActIntrResponse" : "PActDiscResponse", pa);
977 goto out;
978 }
979 FREEACB (acb);
980 acb -> acb_flags &= ~ACB_ACT;
981 return OK;
982
983 case SV_INTRCNF:
984 case SV_DISCCNF:
985 if (!(acb -> acb_flags & ACB_ACT)
986 || !(acb -> acb_flags & ACB_TURN))
987 break;
988 acb -> acb_flags &= ~ACB_ACT;
989 (void) rtsaplose (rti, acb -> acb_flags & ACB_TIMER ? RTS_TIMER
990 : RTS_TRANSFER, NULLCP, NULLCP);
991 return OK;
992
993 case SV_ENDIND:
994 if (!(acb -> acb_flags & ACB_ACT)
995 || (acb -> acb_flags & ACB_TURN))
996 break;
997 if (acb -> acb_uptrans) {
998 if ((*acb -> acb_uptrans) (acb -> acb_fd, SI_ACTIVITY,
999 (caddr_t) pv, rti) == NOTOK) {
1000 if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0,
1001 pi) == NOTOK) {
1002 (void) ps2rtslose (acb, rti, "PUReportRequest", pa);
1003 goto out;
1004 }
1005
1006 return OK;
1007 }
1008
1009 pe = NULLPE;
1010 goto end_it;
1011 }
1012
1013 if (acb -> acb_base) {
1014 if (pe = ssdu2pe (acb -> acb_base, acb -> acb_len,
1015 acb -> acb_realbase ? acb -> acb_realbase
1016 : acb -> acb_base,
1017 &result))
1018 acb -> acb_realbase = acb -> acb_base = NULL;
1019 }
1020 else
1021 pe = NULLPE, result = PS_ERR_EOF;
1022 FREEACB (acb);
1023 if (pe == NULLPE) {
1024 if (result != PS_ERR_NMEM) {
1025 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP, "%s",
1026 ps_error (result));
1027 goto out;
1028 }
1029 if (PUReportRequest (acb -> acb_fd, SP_LOCAL, NULLPEP, 0, pi)
1030 == NOTOK) {
1031 (void) ps2rtslose (acb, rti, "PUReportRequest", pa);
1032 goto out;
1033 }
1034 return OK;
1035 }
1036end_it: ;
1037 if (PActEndResponse (acb -> acb_fd, NULLPEP, 0, pi) == NOTOK) {
1038 (void) ps2rtslose (acb, rti, "PActEndResponse", pa);
1039 if (pe)
1040 pe_free (pe);
1041 goto out;
1042 }
1043 acb -> acb_flags &= ~ACB_ACT;
1044
1045 rti -> rti_type = RTI_TRANSFER;
1046 {
1047 register struct RtSAPtransfer *rtt = &rti -> rti_transfer;
1048
1049 rtt -> rtt_data = pe;
1050 }
1051 return DONE;
1052
1053 case SV_ENDCNF:
1054 if (!(acb -> acb_flags & ACB_ACT)
1055 || !(acb -> acb_flags & ACB_TURN))
1056 break;
1057 acb -> acb_flags &= ~ACB_ACT;
1058 return OK;
1059
1060 default:
1061 break;
1062 }
1063 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
1064 "unexpected activity indication (0x%x)", pv -> pv_type);
1065
1066out: ;
1067 freeacblk (acb);
1068 return NOTOK;
1069}
1070
1071/* \f */
1072
1073static int doPSreport (acb, pp, rti)
1074register struct assocblk *acb;
1075register struct PSAPreport *pp;
1076struct RtSAPindication *rti;
1077{
1078 struct PSAPindication pis;
1079 register struct PSAPindication *pi = &pis;
1080 register struct PSAPabort *pa = &pi -> pi_abort;
1081
1082 PPFREE (pp);
1083
1084 if (!pp -> pp_peer) {
1085 if (!(acb -> acb_flags & ACB_ACT))
1086 goto out2;
1087 if (!(acb -> acb_flags & ACB_TURN))
1088 return OK;
1089
1090/* XXX: should try lots of things here, based on how many checkpoints have
1091 been acknowledged, but, for now we'll treate everything as severe... */
1092
1093 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
1094 "unrecoverable provider-initiated exception report");
1095 }
1096
1097 if ((acb -> acb_flags & ACB_ACT)
1098 || !(acb -> acb_flags & ACB_TURN)) {
1099out2: ;
1100 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
1101 "unexpected exception report indication (0x%x)",
1102 pp -> pp_peer);
1103 goto out1;
1104 }
1105
1106/* XXX: should try lots of things here, based on pp_reason,
1107 but, for now we'll treat everything as SP_NOREASON... */
1108
1109 if (acb -> acb_uptrans)
1110 (void) (*acb -> acb_uptrans) (acb -> acb_fd, SI_REPORT,
1111 (caddr_t) pp, rti);
1112 if (PActDiscRequest (acb -> acb_fd, SP_NOREASON, pi) != NOTOK)
1113 return OK;
1114 (void) ps2rtslose (acb, rti, "PActDiscRequest", pa);
1115
1116out1: ;
1117 freeacblk (acb);
1118 return NOTOK;
1119}
1120
1121/* \f */
1122
1123static int doPSfinish (acb, pf, rti)
1124register struct assocblk *acb;
1125struct PSAPfinish *pf;
1126struct RtSAPindication *rti;
1127{
1128 struct AcSAPindication acis;
1129 register struct AcSAPabort *aca = &acis.aci_abort;
1130
1131 if (((acb -> acb_flags & ACB_INIT) && (acb -> acb_flags & ACB_TWA))
1132 || (acb -> acb_flags & ACB_TURN)) {
1133 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
1134 "association management botched");
1135 PFFREE (pf);
1136 goto out;
1137 }
1138
1139 if (acb -> acb_flags & ACB_ACT) {
1140 (void) rtpktlose (acb, rti, RTS_PROTOCOL, NULLCP,
1141 "unexpected release indication");
1142 PFFREE (pf);
1143 goto out;
1144 }
1145
1146 rti -> rti_type = RTI_FINISH;
1147 {
1148 register struct AcSAPfinish *acf = &rti -> rti_finish;
1149
1150 if (AcFINISHser (acb -> acb_fd, pf, &acis) == NOTOK)
1151 return acs2rtslose (acb, rti, "AcFINISHser", aca);
1152
1153 *acf = acis.aci_finish; /* struct copy */
1154 }
1155
1156 return DONE;
1157
1158out: ;
1159 freeacblk (acb);
1160 return NOTOK;
1161}
1162
1163/* \f */
1164
1165static int doPSabort (acb, pa, rti)
1166register struct assocblk *acb;
1167register struct PSAPabort *pa;
1168struct RtSAPindication *rti;
1169{
1170 struct AcSAPindication acis;
1171 register struct AcSAPabort *aca = &acis.aci_abort;
1172
1173 if (!pa -> pa_peer && pa -> pa_reason == PC_TIMER)
1174 return rtsaplose (rti, RTS_TIMER, NULLCP, NULLCP);
1175
1176 if (AcABORTser (acb -> acb_fd, pa, &acis) == NOTOK) {
1177 (void) acs2rtslose (acb, rti, "AcABORTser", aca);
1178 if (!(acb -> acb_flags & ACB_STICKY))
1179 acb -> acb_fd = NOTOK;
1180 freeacblk (acb);
1181
1182 return NOTOK;
1183 }
1184
1185 return acs2rtsabort (acb, aca, rti);
1186}
1187
1188/* \f */
1189
1190static int psDATAser (sd, px)
1191int sd;
1192register struct PSAPdata *px;
1193{
1194 IFP handler;
1195 register struct assocblk *acb;
1196 struct RtSAPindication rtis;
1197 register struct RtSAPindication *rti = &rtis;
1198
1199 if ((acb = findacblk (sd)) == NULL)
1200 return;
1201 handler = acb -> acb_rtsindication;
1202
1203 if (doPSdata (acb, px, rti) != OK)
1204 (*handler) (sd, rti);
1205}
1206
1207/* \f */
1208
1209static int psTOKENser (sd, pt)
1210int sd;
1211register struct PSAPtoken *pt;
1212{
1213 IFP handler;
1214 register struct assocblk *acb;
1215 struct RtSAPindication rtis;
1216 register struct RtSAPindication *rti = &rtis;
1217
1218 if ((acb = findacblk (sd)) == NULL)
1219 return;
1220 handler = acb -> acb_rtsindication;
1221
1222 if (doPStoken (acb, pt, 0, rti) != OK)
1223 (*handler) (sd, rti);
1224}
1225
1226/* \f */
1227
1228static int psSYNCser (sd, pn)
1229int sd;
1230register struct PSAPsync *pn;
1231{
1232 IFP handler;
1233 register struct assocblk *acb;
1234 struct RtSAPindication rtis;
1235 register struct RtSAPindication *rti = &rtis;
1236
1237 if ((acb = findacblk (sd)) == NULL)
1238 return;
1239 handler = acb -> acb_rtsindication;
1240
1241 if (doPSsync (acb, pn, rti) != OK)
1242 (*handler) (sd, rti);
1243}
1244
1245/* \f */
1246
1247static int psACTIVITYser (sd, pv)
1248int sd;
1249register struct PSAPactivity *pv;
1250{
1251 IFP handler;
1252 register struct assocblk *acb;
1253 struct RtSAPindication rtis;
1254 register struct RtSAPindication *rti = &rtis;
1255
1256 if ((acb = findacblk (sd)) == NULL)
1257 return;
1258 handler = acb -> acb_rtsindication;
1259
1260 if (doPSactivity (acb, pv, rti) != OK)
1261 (*handler) (sd, rti);
1262}
1263
1264/* \f */
1265
1266static int psREPORTser (sd, pp)
1267int sd;
1268register struct PSAPreport *pp;
1269{
1270 IFP handler;
1271 register struct assocblk *acb;
1272 struct RtSAPindication rtis;
1273 register struct RtSAPindication *rti = &rtis;
1274
1275 if ((acb = findacblk (sd)) == NULL)
1276 return;
1277 handler = acb -> acb_rtsindication;
1278
1279 if (doPSreport (acb, pp, rti) != OK)
1280 (*handler) (sd, rti);
1281}
1282
1283/* \f */
1284
1285static int psFINISHser (sd, pf)
1286int sd;
1287struct PSAPfinish *pf;
1288{
1289 IFP handler;
1290 register struct assocblk *acb;
1291 struct RtSAPindication rtis;
1292 register struct RtSAPindication *rti = &rtis;
1293
1294 if ((acb = findacblk (sd)) == NULL)
1295 return;
1296 handler = acb -> acb_rtsindication;
1297
1298 (void) doPSfinish (acb, pf, rti);
1299
1300 (*handler) (sd, rti);
1301}
1302
1303/* \f */
1304
1305static int psABORTser (sd, pa)
1306int sd;
1307register struct PSAPabort *pa;
1308{
1309 IFP handler;
1310 register struct assocblk *acb;
1311 struct RtSAPindication rtis;
1312 register struct RtSAPindication *rti = &rtis;
1313
1314 if ((acb = findacblk (sd)) == NULL)
1315 return;
1316 handler = acb -> acb_rtsindication;
1317
1318 (void) doPSabort (acb, pa, rti);
1319
1320 (*handler) (sd, rti);
1321}
1322
1323/* \f */
1324
1325int ps2rtslose (acb, rti, event, pa)
1326register struct assocblk *acb;
1327register struct RtSAPindication *rti;
1328char *event;
1329register struct PSAPabort *pa;
1330{
1331 int reason;
1332 char *cp,
1333 buffer[BUFSIZ];
1334
1335 if (event)
1336 SLOG (rtsap_log, LLOG_EXCEPTIONS, NULLCP,
1337 (pa -> pa_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event,
1338 PErrString (pa -> pa_reason), pa -> pa_cc, pa -> pa_cc,
1339 pa -> pa_data));
1340
1341 cp = "";
1342 switch (pa -> pa_reason) {
1343 case PC_ADDRESS:
1344 reason = RTS_ADDRESS;
1345 break;
1346
1347 case PC_REFUSED:
1348 reason = RTS_REFUSED;
1349 break;
1350
1351 case PC_CONGEST:
1352 reason = RTS_CONGEST;
1353 break;
1354
1355 default:
1356 (void) sprintf (cp = buffer, " (%s at presentation)",
1357 PErrString (pa -> pa_reason));
1358 case PC_SESSION:
1359 reason = RTS_PRESENTATION;
1360 break;
1361 }
1362
1363 if (pa -> pa_cc > 0)
1364 return rtpktlose (acb, rti, reason, NULLCP, "%*.*s%s",
1365 pa -> pa_cc, pa -> pa_cc, pa -> pa_data, cp);
1366 else
1367 return rtpktlose (acb, rti, reason, NULLCP, "%s", *cp ? cp + 1 : cp);
1368}
1369