DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T t

⟦a9763a788⟧ TextFile

    Length: 15160 (0x3b38)
    Types: TextFile
    Names: »tp0ts.c«

Derivation

└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape
    └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« 
        └─⟦d3ac74d73⟧ 
            └─⟦this⟧ »isode-5.0/tsap/tp0ts.c« 

TextFile

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