|
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: 22470 (0x57c6) Types: TextFile Names: »tp0ts.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦e83f91978⟧ »EurOpenD22/isode/osimis-2.0.tar.Z« └─⟦d846658bd⟧ └─⟦this⟧ »osimis/misode/tsap/tp0ts.c« └─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/tsap/tp0ts.c«
/* tp0ts.c - TPM: TP0 engine */ #ifndef lint static char *rcsid = "$Header: /f/osi/tsap/RCS/tp0ts.c,v 7.4 89/12/19 10:18:22 mrose Exp $"; #endif /* * $Header: /f/osi/tsap/RCS/tp0ts.c,v 7.4 89/12/19 10:18:22 mrose Exp $ * * * $Log: tp0ts.c,v $ * Revision 7.4 89/12/19 10:18:22 mrose * DLOG * * Revision 7.3 89/12/08 09:41:23 mrose * touch-up * * Revision 7.2 89/12/07 22:15:39 mrose * touch-up * * Revision 7.1 89/12/07 01:07:30 mrose * queued writes * * Revision 7.0 89/11/23 22:30:33 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 "tpkt.h" #include "mpkt.h" #include "tailor.h" #if defined(TCP) || defined(X25) /* \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; 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 CONNECTING_1; case DONE: break; } if (tpkt2fd (tb, 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 CONNECTING_2; } 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; #ifdef MGMT if (tb -> tb_manfnx) (*tb -> tb_manfnx) (OPREQOUT, tb); #endif 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, t, tb -> tb_writefnx)) == NOTOK) (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); else { tb -> tb_flags |= TB_CONN; #ifdef MGMT if (tb -> tb_manfnx) (*tb -> tb_manfnx) (OPREQIN, tb); #endif } 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; #if defined(X25) || defined(MGMT) int dlen; #endif register char *bp, *ep; register struct tsapkt *t; register struct udvec *vv, *wv; #if defined(X25) || defined(MGMT) dlen = 0; #endif 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"); wv = (vv = t -> t_udvec) + NTPUV - 1; for (len = tb -> tb_tsdusize; len > 0 && vv < wv; len -= j) { j = min (cc, len); #if defined(X25) || defined(MGMT) 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, 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 #ifdef MGMT if (tb -> tb_manfnx) (*tb -> tb_manfnx) (USERDT, tb, 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); #ifdef MGMT if (tb -> tb_manfnx) (*tb -> tb_manfnx) (USERDR, tb, tb -> tb_len); #endif 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; #ifdef TCP register struct tsapkt *t; #endif result = OK; #ifdef TCP 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, 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"); } #endif #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, t, tb -> tb_writefnx); freetpkt (t); } } /* \f */ /* at present, used by TCP, X.25 and BRG back-ends... */ #ifndef TCP #undef WRITEV #endif #include <errno.h> #include <sys/ioctl.h> #ifdef WRITEV #include <sys/uio.h> #endif #ifdef TCP #include "internet.h" #else #define write_tcp_socket NULLIFP #endif #ifdef X25 #include "x25.h" #else #define write_x25_socket NULLIFP #endif extern int errno; /* \f */ int tp0write (tb, t, cp, n) register struct tsapblk *tb; register struct tsapkt *t; char *cp; int n; { register int cc; register char *p, *q; register struct qbuf *qb; register struct udvec *uv; #if defined(WRITEV) || defined(SUN_X25) || defined(CAMTEC_CCL) struct iovec iovs[NTPUV + 4]; register struct iovec *iov; #endif #if defined(WRITEV) || defined(SUN_X25) || defined(CAMTEC_CCL) #ifdef FIONBIO if (tb -> tb_flags & TB_QWRITES) goto single; #endif iov = iovs; cc = 0; if (tb -> tb_flags & TB_X25) { iov -> iov_base = (char *) &t -> t_li; cc += (iov -> iov_len = sizeof t -> t_li); iov++; iov -> iov_base = (char *) &t -> t_code; cc += (iov -> iov_len = sizeof t -> t_code); iov++; } else { iov -> iov_base = (char *) &t -> t_pkthdr; cc += (iov -> iov_len = TPKT_HDRLEN (t)); iov++; } iov -> iov_base = cp; cc += (iov -> iov_len = n); iov++; if (t -> t_vdata) { iov -> iov_base = t -> t_vdata; cc += (iov -> iov_len = t -> t_vlen); iov++; } for (uv = t -> t_udvec; uv -> uv_base; uv++) { iov -> iov_base = uv -> uv_base; cc += (iov -> iov_len = uv -> uv_len); iov++; } if ((n = writev (tb -> tb_fd, iovs, iov - iovs)) != cc) { cc = NOTOK; #ifdef SUN_X25 if (tb -> tb_flags & TB_X25 && compat_log -> ll_events & LLOG_EXCEPTIONS) (void) log_cause_and_diag (tb -> tb_fd); #endif } else if (tb -> tb_flags & TB_X25) { DLOG (compat_log, LLOG_DEBUG, ("X.25 write %d bytes", cc)); } goto out; single: ; #endif cc = ((tb -> tb_flags & TB_X25) ? sizeof t -> t_li + sizeof t -> t_code : TPKT_HDRLEN (t)) + n; if (t -> t_vdata) cc += t -> t_vlen; for (uv = t -> t_udvec; uv -> uv_base; uv++) cc += uv -> uv_len; if (p = malloc (sizeof *qb + (unsigned) cc)) { int nc, onoff; IFP wfnx = (tb -> tb_flags & TB_X25) ? write_x25_socket : write_tcp_socket; #ifdef FIONBIO if (tb -> tb_flags & TB_QWRITES) { qb = (struct qbuf *) p; qb -> qb_forw = qb -> qb_back = qb; qb -> qb_data = qb -> qb_base, qb -> qb_len = cc; p = qb -> qb_data; } #endif if (tb -> tb_flags & TB_X25) { bcopy ((char *) &t -> t_li, q = p, sizeof t -> t_li); q += sizeof t -> t_li; bcopy ((char *) &t -> t_code, q, sizeof t -> t_code); q += sizeof t -> t_code; } else { bcopy ((char *) &t -> t_pkthdr, q = p, TPKT_HDRLEN (t)); q += TPKT_HDRLEN (t); } bcopy (cp, q, n); q += n; if (t -> t_vdata) { bcopy (t -> t_vdata, q, t -> t_vlen); q += t -> t_vlen; } for (uv = t -> t_udvec; uv -> uv_base; uv++) { bcopy (uv -> uv_base, q, uv -> uv_len); q += uv -> uv_len; } #ifdef FIONBIO if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) { nc = 0; goto insert; } if (tb -> tb_flags & TB_QWRITES) (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); #endif nc = (*wfnx) (tb -> tb_fd, p, cc); #ifdef FIONBIO if (tb -> tb_flags & TB_QWRITES) (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); #endif if (nc != cc) { #ifdef FIONBIO if (tb -> tb_flags & TB_QWRITES) { if (nc == NOTOK) { if (errno != EWOULDBLOCK) goto losing; nc = 0; } else if (nc > 0 && (tb -> tb_flags & TB_X25)) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("partial write (%d of %d octets) to X.25", nc, cc)); goto losing; } if ((*tb -> tb_queuePfnx) (tb, 1, (struct TSAPdisconnect *) 0) == NOTOK) goto losing; qb -> qb_data += nc, qb -> qb_len -= nc; insert: ; insque (qb, tb -> tb_qwrites.qb_back); DLOG (tsap_log, LLOG_TRACE, ("queueing blocked write of %d of %d octets", nc, cc)); qb = NULL; } else #endif { losing: ; cc = NOTOK; } } #ifdef FIONBIO if (tb -> tb_flags & TB_QWRITES) { if (qb) free ((char *) qb); } else #endif free (p); goto out; } if ((tb -> tb_flags & TB_X25) || tb -> tb_flags & TB_QWRITES) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("unable to malloc %d octets for pseudo-writev, failing...", cc)); cc = NOTOK; goto out; } #ifdef TCP SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("unable to malloc %d octets for pseudo-writev, continuing...", cc)); cc = TPKT_HDRLEN (t); if (write_tcp_socket (tb -> tb_fd, (char *) &t -> t_pkthdr, cc) != cc) { err: ; cc = NOTOK; goto out; } if (write_tcp_socket (tb -> tb_fd, cp, n) != n) goto err; cc += n; if (t -> t_vdata && write_tcp_socket (tb -> tb_fd, t -> t_vdata, t -> t_vlen) != t -> t_vlen) goto err; cc += t -> t_vlen; for (uv = t -> t_udvec; uv -> uv_base; uv++) { if (write_tcp_socket (tb -> tb_fd, uv -> uv_base, uv -> uv_len) != uv -> uv_len) goto err; cc += uv -> uv_len; } #endif out: ; return cc; } /* \f */ #ifdef FIONBIO static int TDrain (tb, td) register struct tsapblk *tb; struct TSAPdisconnect *td; { int nc, onoff, result; register struct qbuf *qb; IFP wfnx = (tb -> tb_flags & TB_X25) ? write_x25_socket : write_tcp_socket; (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); while ((qb = tb -> tb_qwrites.qb_forw) != &tb -> tb_qwrites) { if ((nc = (*wfnx) (tb -> tb_fd, qb -> qb_data, qb -> qb_len)) != qb -> qb_len) { if (nc == NOTOK) { if (errno != EWOULDBLOCK) { result = tsaplose (td, DR_NETWORK, "failed", "write to network"); goto out; } nc = 0; } else if (nc > 0 && (tb -> tb_flags & TB_X25)) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("partial write (%d of %d octets) to X.25", nc, qb -> qb_len)); result = tsaplose (td, DR_NETWORK, NULLCP, "partial write (%d of %d octets) to X.25", nc, qb -> qb_len); goto out; } DLOG (tsap_log, LLOG_TRACE, ("wrote %d of %d octets from blocked write", nc, qb -> qb_len)); qb -> qb_data += nc, qb -> qb_len -= nc; result = OK; goto out; } DLOG (tsap_log, LLOG_TRACE, ("finished blocked write of %d octets", qb -> qb_len)); remque (qb); free ((char *) qb); } result = DONE; out: ; (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); return result; } #endif /* \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; #ifdef FIONBIO tb -> tb_drainPfnx = TDrain; #endif #ifdef MGMT tb -> tb_manfnx = TManGen; #endif } #endif