|
|
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