|
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 t
Length: 15160 (0x3b38) Types: TextFile Names: »tp0ts.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/tsap/tp0ts.c«
/* tp0ts.c - TPM: TP0 engine */ #ifndef lint static char *rcsid = "$Header: /f/osi/tsap/RCS/tp0ts.c,v 6.1 89/03/23 22:28:09 mrose Exp $"; #endif /* * $Header: /f/osi/tsap/RCS/tp0ts.c,v 6.1 89/03/23 22:28:09 mrose Exp $ * * * $Log: tp0ts.c,v $ * Revision 6.1 89/03/23 22:28:09 mrose * out-the-door * * Revision 6.0 89/03/18 23:45:16 mrose * Release 5.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 "tpkt.h" #include "tailor.h" #undef TP0 #ifdef TCP #define TP0 #endif #if defined(X25) || defined(CONS) #define TP0 #endif #ifdef TP0 /* \f */ static int TConnect (tb, expedited, data, cc, td) register struct tsapblk *tb; char *data; int expedited, cc; struct TSAPdisconnect *td; { register struct tsapkt *t; if (!(tb -> tb_flags & TB_TCP)) { expedited = 0; if (cc > 0) return tsaplose (td, DR_PARAMETER, NULLCP, "initial user data not allowed with class 0"); } tb -> tb_srcref = htons ((u_short) (getpid () & 0xffff)); tb -> tb_dstref = htons ((u_short) 0); if ((t = newtpkt (TPDU_CR)) == NULL) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); t -> t_cr.cr_dstref = tb -> tb_dstref; t -> t_cr.cr_srcref = tb -> tb_srcref; t -> t_cr.cr_class = CR_CLASS_TP0; if (!(tb -> tb_flags & TB_TCP)) { register int i, j; int k; i = k = tb -> tb_tsdusize + tb -> tb_tpduslop; if (i > 1024) i = k = 1024; /* XXX: temporary fix for ISODE 4.0... */ for (j = 0; i > 0; j++) i >>= 1; if (k == (1 << (j - 1))) j--; if (j > SIZE_MAXTP0) { j = SIZE_MAXTP0; tb -> tb_tsdusize = (1 << j) - tb -> tb_tpduslop; } if (j != SIZE_DFLT) t -> t_tpdusize = j; } bcopy (tb -> tb_initiating.ta_selector, t -> t_calling, t -> t_callinglen = tb -> tb_initiating.ta_selectlen); bcopy (tb -> tb_responding.ta_selector, t -> t_called, t -> t_calledlen = tb -> tb_responding.ta_selectlen); if (expedited) { tb -> tb_flags |= TB_EXPD; t -> t_options |= OPT_TEXPEDITE; } copyTPKTdata (t, data, cc); /* XXX: user musn't touch! */ tb -> tb_retry = t; return OK; } /* \f */ static int TRetry (tb, async, tc, td) register struct tsapblk *tb; int async; struct TSAPconnect *tc; struct TSAPdisconnect *td; { int len; register struct tsapkt *t; if (t = tb -> tb_retry) { tb -> tb_retry = NULL; if (async) switch ((*tb -> tb_retryfnx) (tb, td)) { case NOTOK: goto out; case OK: tb -> tb_retry = t; return OK; case DONE: break; } if (tpkt2fd (tb -> tb_fd, t, tb -> tb_writefnx) == NOTOK) { (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); goto out; } freetpkt (t), t = NULL; } if (async) { fd_set mask; FD_ZERO (&mask); FD_SET (tb -> tb_fd, &mask); if (xselect (tb -> tb_fd + 1, &mask, NULLFD, NULLFD, 0) == OK) return OK; } if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL || t -> t_errno != OK) { (void) tsaplose (td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); goto out; } switch (TPDU_CODE (t)) { case TPDU_CC: tc -> tc_sd = tb -> tb_fd; if (CR_CLASS (t) != CR_CLASS_TP0) { (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "proposed class 0, got back 0x%x", CR_CLASS (t)); goto out; } if (tb -> tb_srcref != t -> t_cc.cc_dstref) { (void) tpktlose (tb, td, DR_MISMATCH, NULLCP, "sent srcref of 0x%x, got 0x%x", ntohs (tb -> tb_srcref), ntohs (t -> t_cc.cc_dstref)); goto out; } tb -> tb_dstref = t -> t_cc.cc_srcref; if (!(tb -> tb_flags & TB_TCP)) { if (t -> t_tpdusize == 0) t -> t_tpdusize = SIZE_DFLT; else if (t -> t_tpdusize > SIZE_MAXTP0) t -> t_tpdusize = SIZE_MAXTP0; tb -> tb_tsdusize = (1 << t -> t_tpdusize) - tb -> tb_tpduslop; } if ((len = t -> t_calledlen) > 0) { if (len > sizeof tb -> tb_responding.ta_selector) len = sizeof tb -> tb_responding.ta_selector; bcopy (t -> t_called, tb -> tb_responding.ta_selector, tb -> tb_responding.ta_selectlen = len); } tc -> tc_responding = tb -> tb_responding; /* struct copy */ if (!(t -> t_options & OPT_TEXPEDITE) || !(tb -> tb_flags & TB_TCP)) tb -> tb_flags &= ~TB_EXPD; tc -> tc_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; tc -> tc_tsdusize = tb -> tb_tsdusize; tc -> tc_qos = tb -> tb_qos; /* struct copy */ if (t -> t_qbuf) { copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, tc); } else tc -> tc_cc = 0; freetpkt (t); tb -> tb_flags |= TB_CONN; return DONE; case TPDU_DR: td -> td_reason = t -> t_dr.dr_reason; if (t -> t_qbuf) { copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, td); } else td -> td_cc = 0; goto out; case TPDU_ER: switch (t -> t_er.er_reject) { case ER_REJ_NOTSPECIFIED: default: td -> td_reason = DR_CONNECT; break; case ER_REJ_CODE: case ER_REJ_TPDU: case ER_REJ_VALUE: td -> td_reason = DR_PROTOCOL; break; } td -> td_cc = 0; goto out; default: (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "transport protocol mangled: expecting 0x%x, got 0x%x", TPDU_CC, TPDU_CODE (t)); goto out; } out: ; freetpkt (t); freetblk (tb); return NOTOK; } /* \f */ static int TStart (tb, cp, ts, td) register struct tsapblk *tb; char *cp; struct TSAPstart *ts; struct TSAPdisconnect *td; { int len, result; register struct tsapkt *t; if ((t = str2tpkt (cp)) == NULL || t -> t_errno != OK) { result = tsaplose (td, DR_PARAMETER, NULLCP, "bad initialization vector"); goto out; } if (CR_CLASS (t) != CR_CLASS_TP0) { if (t -> t_cr.cr_alternate & (ALT_TP0 | ALT_TP1)) t -> t_cr.cr_class = CR_CLASS_TP0; else { result = tpktlose (tb, td, DR_CONNECT, NULLCP, "only class 0 supported, not 0x%x", CR_CLASS (t)); goto out; } } tb -> tb_srcref = htons ((u_short) (getpid () & 0xffff)); tb -> tb_dstref = t -> t_cr.cr_srcref; if (!(tb -> tb_flags & TB_TCP)) { if (t -> t_tpdusize == 0) t -> t_tpdusize = SIZE_DFLT; else if (t -> t_tpdusize > SIZE_MAXTP0) t -> t_tpdusize = SIZE_MAXTP0; tb -> tb_tsdusize = (1 << t -> t_tpdusize) - tb -> tb_tpduslop; } if ((len = t -> t_callinglen) > 0) { if (len > sizeof tb -> tb_initiating.ta_selector) len = sizeof tb -> tb_initiating.ta_selector; bcopy (t -> t_calling, tb -> tb_initiating.ta_selector, tb -> tb_initiating.ta_selectlen = len); } if ((len = t -> t_calledlen) > 0) { if (len > sizeof tb -> tb_responding.ta_selector) len = sizeof tb -> tb_responding.ta_selector; bcopy (t -> t_called, tb -> tb_responding.ta_selector, tb -> tb_responding.ta_selectlen = len); } if ((t -> t_options & OPT_TEXPEDITE) && (tb -> tb_flags & TB_TCP)) tb -> tb_flags |= TB_EXPD; ts -> ts_sd = tb -> tb_fd; ts -> ts_calling = tb -> tb_initiating; /* struct copy */ ts -> ts_called = tb -> tb_responding; /* struct copy */ ts -> ts_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; ts -> ts_tsdusize = tb -> tb_tsdusize; ts -> ts_qos = tb -> tb_qos; /* struct copy */ if (t -> t_qbuf) { copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, ts); } else ts -> ts_cc = 0; result = OK; out: ; freetpkt (t); return result; } /* \f */ /* ARGSUSED */ static int TAccept (tb, responding, data, cc, qos, td) register struct tsapblk *tb; char *data; int responding, cc; struct QOStype *qos; struct TSAPdisconnect *td; { int result; register struct tsapkt *t; if (!(tb -> tb_flags & TB_TCP) && cc > 0) return tsaplose (td, DR_PARAMETER, NULLCP, "initial user data not allowed with class 0"); if ((t = newtpkt (TPDU_CC)) == NULL) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); t -> t_cc.cc_dstref = tb -> tb_dstref; t -> t_cc.cc_srcref = tb -> tb_srcref; t -> t_cc.cc_class = CR_CLASS_TP0; if (!(tb -> tb_flags & TB_TCP)) { register int i, j; int k; i = k = tb -> tb_tsdusize + tb -> tb_tpduslop; for (j = 0; i > 0; j++) i >>= 1; if (k == (1 << (j - 1))) j--; if (j > SIZE_MAXTP0) { j = SIZE_MAXTP0; tb -> tb_tsdusize = (1 << j) - tb -> tb_tpduslop; } if (j != SIZE_DFLT) t -> t_tpdusize = j; } if (responding) bcopy (tb -> tb_responding.ta_selector, t -> t_called, t -> t_calledlen = tb -> tb_responding.ta_selectlen); if (tb -> tb_flags & TB_EXPD) t -> t_options |= OPT_TEXPEDITE; copyTPKTdata (t, data, cc); if ((result = tpkt2fd (tb -> tb_fd, t, tb -> tb_writefnx)) == NOTOK) (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); else tb -> tb_flags |= TB_CONN; freetpkt (t); return result; } /* \f */ static int TWrite (tb, uv, expedited, td) register struct tsapblk *tb; register struct udvec *uv; int expedited; struct TSAPdisconnect *td; { int cc, j, len, result; #ifdef X25 register int dlen; #endif register char *bp, *ep; register struct tsapkt *t; register struct udvec *vv, *wv; ep = (bp = uv -> uv_base) + (cc = uv -> uv_len); while (uv -> uv_base) { if ((t = newtpkt (expedited ? TPDU_ED : TPDU_DT)) == NULL) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); #ifdef X25 dlen = 0; #endif wv = (vv = t -> t_udvec) + NTPUV - 1; for (len = tb -> tb_tsdusize; len > 0 && vv < wv; len -= j) { j = min (cc, len); #ifdef X25 dlen += j; #endif vv -> uv_base = bp, vv -> uv_len = j, vv++; bp += j, cc -= j; if (bp >= ep) { if ((bp = (++uv) -> uv_base) == NULL) break; ep = bp + (cc = uv -> uv_len); } } if (uv -> uv_base == NULL) t -> t_dt.dt_nr |= DT_EOT; if ((result = tpkt2fd (tb -> tb_fd, t, tb -> tb_writefnx)) == NOTOK) { (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); #ifdef X25 if (tb -> tb_flags & TB_X25) LLOG (x25_log, LLOG_NOTICE, ("connection %d broken, %d/%d octets sent/recv", tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); #endif freetblk (tb); } freetpkt (t); if (result == NOTOK) return NOTOK; #ifdef X25 tb -> tb_sent += dlen; #endif } return OK; } /* \f */ /* ARGSUSED */ static int TRead (tb, tx, td, async, oob) register struct tsapblk *tb; register struct TSAPdata *tx; struct TSAPdisconnect *td; int async, oob; { int eot; register struct tsapkt *t; bzero ((char *) tx, sizeof *tx); tx -> tx_qbuf.qb_forw = tx -> tx_qbuf.qb_back = &tx -> tx_qbuf; for (;;) { if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL || t -> t_errno != OK) { (void) tsaplose (td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); #ifdef X25 if (tb -> tb_flags & TB_X25) LLOG (x25_log, LLOG_NOTICE, ("connection %d broken, %d/%d octets sent/recv", tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); #endif break; } switch (TPDU_CODE (t)) { case TPDU_DT: eot = t -> t_dt.dt_nr & DT_EOT; if (t -> t_qbuf) { insque (t -> t_qbuf, tb -> tb_qbuf.qb_back); tb -> tb_len += t -> t_qbuf -> qb_len; #ifdef X25 tb -> tb_recv += t -> t_qbuf -> qb_len; #endif t -> t_qbuf = NULL; } freetpkt (t); if (!eot) { if (async) return DONE; continue; } tx -> tx_expedited = 0; if (tb -> tb_qbuf.qb_forw != &tb -> tb_qbuf) { tx -> tx_qbuf = tb -> tb_qbuf;/* struct copy */ tx -> tx_qbuf.qb_forw -> qb_back = tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf; tx -> tx_cc = tb -> tb_len; tb -> tb_qbuf.qb_forw = tb -> tb_qbuf.qb_back = &tb -> tb_qbuf; tb -> tb_len = 0; } return OK; case TPDU_ED: if (t -> t_qbuf) { insque (t -> t_qbuf, tx -> tx_qbuf.qb_back); tx -> tx_cc = t -> t_qbuf -> qb_len; t -> t_qbuf = NULL; } freetpkt (t); tx -> tx_expedited = 1; return OK; case TPDU_DR: td -> td_reason = t -> t_dr.dr_reason; if (t -> t_qbuf) { copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, td); } else td -> td_cc = 0; break; case TPDU_ER: switch (t -> t_er.er_reject) { case ER_REJ_NOTSPECIFIED: default: td -> td_reason = DR_UNKNOWN; break; case ER_REJ_CODE: case ER_REJ_TPDU: case ER_REJ_VALUE: td -> td_reason = DR_PROTOCOL; break; } td -> td_cc = 0; break; default: (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "transport protocol mangled: not expecting 0x%x", TPDU_CODE (t)); break; } break; } freetpkt (t); freetblk (tb); return NOTOK; } /* \f */ static int TDisconnect (tb, data, cc, td) register struct tsapblk *tb; char *data; int cc; struct TSAPdisconnect *td; { int result; register struct tsapkt *t; result = OK; if (tb -> tb_flags & TB_TCP) { if (t = newtpkt (TPDU_DR)) { t -> t_dr.dr_srcref = tb -> tb_srcref; t -> t_dr.dr_dstref = tb -> tb_dstref; t -> t_dr.dr_reason = DR_NORMAL; copyTPKTdata (t, data, cc); if ((result = tpkt2fd (tb -> tb_fd, t, tb -> tb_writefnx)) == NOTOK) (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); freetpkt (t); } else result = tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); } #ifdef X25 if (tb -> tb_flags & TB_X25) LLOG (x25_log, LLOG_NOTICE, ("connection %d closed, %d/%d octets sent/recv", tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); #endif freetblk (tb); return result; } /* \f */ static TLose (tb, reason, td) register struct tsapblk *tb; int reason; struct TSAPdisconnect *td; { struct tsapkt *t; switch (reason) { case DR_UNKNOWN: case DR_CONGEST: case DR_SESSION: case DR_ADDRESS: if ((t = newtpkt (TPDU_DR)) == NULLPKT) break; t -> t_dr.dr_srcref = tb -> tb_srcref; t -> t_dr.dr_dstref = tb -> tb_dstref; t -> t_dr.dr_reason = reason; copyTPKTdata (t, td -> td_data, td -> td_cc); break; default: if ((t = newtpkt (TPDU_ER)) == NULLPKT) break; t -> t_er.er_dstref = tb -> tb_dstref; switch (reason) { case DR_PROTOCOL: t -> t_er.er_reject = ER_REJ_TPDU; break; default: t -> t_er.er_reject = ER_REJ_NOTSPECIFIED; break; } break; } if (t) { (void) tpkt2fd (tb -> tb_fd, t, tb -> tb_writefnx); freetpkt (t); } } /* \f */ int tp0init (tb) register struct tsapblk *tb; { tb -> tb_connPfnx = TConnect; tb -> tb_retryPfnx = TRetry; tb -> tb_startPfnx = TStart; tb -> tb_acceptPfnx = TAccept; tb -> tb_writePfnx = TWrite; tb -> tb_readPfnx = TRead; tb -> tb_discPfnx = TDisconnect; tb -> tb_losePfnx = TLose; } #endif