|
|
1.1 root 1: #include "../chunix/chsys.h"
2: #include "../chunix/chconf.h"
3: #include "../chaos/chaos.h"
4:
5: /*
6: * This file contains code for a stream level (as opposed to packet level)
7: * interface to the chaosnet. It is written to be general enough to fit into
8: * various systems where such an interface in desirable. This has been the
9: * case both in UNIX and in FEZ, although UNIX also needs its own "tty"
10: * interface.
11: *
12: * Several macros must be supplied in chsys.h(they can do nothing of course):
13: * LOCK, UNLOCK - mask out chaos interrupts (send, receive, clock)
14: * NOINPUT - a LOCK'd hook for indicating that there is no input
15: * available on a channel (used in FEZ...)
16: * NOOUTPUT - a hook for indicating when no output is possible
17: * (window is full) (unused in UNIX, used in FEZ...)
18: * CHRCOPY - read copy routine (from, to, count) which should
19: * return the (to) ptr after copying is done.
20: * CHWCOPY - write copy routine (from, to, count) like CHRCOPY
21: */
22:
23: /*
24: * Stream read routine - given connection, ptr and number of chars
25: * As many of the desired characters are transferred as are available
26: * in the received packet list. If any have been read, the number
27: * transferred is return. If none were transferred then if
28: * an EOF has been encountered, CHEOF is returned, otherwise if the
29: * connection is still open, zero is returned, otherwise CHERROR is
30: * returned (connection no longer open).
31: * Note that answer (ANSOP) packets read just like data at act like
32: * an EOF was encountered after the ANSOP.
33: * UNCOP (uncontrolled data) packets are treated just like data packets.
34: * An EOF packet just terminates a read that has made some progress
35: * and is specifically indicated (by zero chars read) in the next read
36: * call. After this indication a bit (CHEOFSEEN) is set which causes
37: * end-of-file indications to be read as long as the connection
38: * is open. If more data packets arrive, this bit is turned off.
39: */
40: ch_sread(conn, ptr, nchars)
41: register struct connection *conn;
42: char *ptr;
43: unsigned nchars;
44: {
45: register struct packet *pkt;
46: register unsigned count;
47: unsigned ntodo = nchars;
48:
49: while (ntodo != 0 && (pkt = conn->cn_rhead) != NOPKT)
50: switch(pkt->pk_op) {
51: case EOFOP:
52: if (ntodo != nchars)
53: return(nchars - ntodo);
54: LOCK;
55: ch_read(conn); /* consume it */
56: ch_sts(conn); /* ensure immediately ack */
57: UNLOCK;
58: conn->cn_flags |= CHEOFSEEN;
59: return (CHEOF);
60: default:
61: if (!ISDATOP(pkt)) {
62: LOCK;
63: ch_read(conn);
64: UNLOCK;
65: break;
66: }
67: /* Fall into... */
68: case ANSOP:
69: case UNCOP:
70: conn->cn_flags &= ~CHEOFSEEN;
71: count = pkt->pk_len >= ntodo ? ntodo : pkt->pk_len;
72: ptr = CHRCOPY(&pkt->pk_cdata[conn->cn_roffset], ptr, count);
73: ntodo -= count;
74: if ((pkt->pk_len -= count) == 0) {
75: LOCK;
76: ch_read(conn);
77: UNLOCK;
78: conn->cn_roffset = 0;
79: if (pkt->pk_op == ANSOP)
80: conn->cn_flags |= CHEOFSEEN;
81: } else
82: conn->cn_roffset += count;
83: }
84: if (ntodo != 0) {
85: LOCK;
86: NOINPUT(conn);
87: UNLOCK;
88: }
89: return (ntodo != nchars ? nchars - ntodo :
90: conn->cn_flags & CHEOFSEEN ? CHEOF :
91: conn->cn_state == CSOPEN ? 0 : CHERROR);
92: }
93:
94: /*
95: * Stream write routine - given connection, ptr and number of characters
96: * Characters are written until exhausted or until the window is full.
97: * The number of characters not read is returned, unless this connection
98: * closes, in which case CHERROR is returned. If no buffers are avaiable
99: * (presumably a temporary condition), CHTEMP is returned.
100: * ANS packets are sent if the flag is set.
101: */
102: ch_swrite(conn, ptr, nchars)
103: register struct connection *conn;
104: char *ptr;
105: unsigned nchars;
106: {
107: register struct packet *pkt;
108: register unsigned count;
109: unsigned ntodo = nchars;
110:
111: LOCK;
112: for (;;) {
113: if (conn->cn_state != CSOPEN &&
114: (conn->cn_state != CSRFCRCVD ||
115: (conn->cn_flags & CHANSWER) == 0)) {
116: UNLOCK;
117: return CHERROR;
118: }
119: if (ntodo == 0 || chtfull(conn))
120: break;
121: if ((pkt = conn->cn_toutput) == NOPKT) {
122: UNLOCK;
123: if ((pkt = pkalloc(CHMAXDATA, 0)) == NOPKT)
124: return (ntodo == nchars ? CHTEMP :
125: nchars - ntodo);
126: pkt->pk_op = conn->cn_flags & CHANSWER ? ANSOP : DATOP;
127: pkt->pk_lenword = 0;
128: conn->cn_troom = CHMAXDATA;
129: } else {
130: conn->cn_toutput = NOPKT;
131: UNLOCK;
132: }
133: count = ntodo > conn->cn_troom ? conn->cn_troom : ntodo;
134: ptr = CHWCOPY(ptr, &pkt->pk_cdata[pkt->pk_len], count);
135: pkt->pk_lenword += count;
136: ntodo -= count;
137: LOCK;
138: if ((conn->cn_troom -= count) == 0) {
139: if (ch_write(conn, pkt))
140: return CHERROR;
141: } else {
142: conn->cn_toutput = pkt;
143: pkt->pk_time = Chclock;
144: }
145: }
146: if (ntodo != 0)
147: NOOUTPUT(conn);
148: UNLOCK;
149: return(nchars - ntodo);
150: }
151: /*
152: * Output flush routine - release the currently-being-filled packet for
153: * transmission immediately.
154: * Called at high priority.
155: * If output window is full, CHTEMP is returned.
156: * If connection is not open, CHERROR is returned from ch_write.
157: */
158: ch_sflush(conn)
159: register struct connection *conn;
160: {
161: register struct packet *pkt;
162:
163: if ((pkt = conn->cn_toutput) != NOPKT)
164: if (chtfull(conn))
165: return CHTEMP;
166: else {
167: conn->cn_toutput = NOPKT;
168: return ch_write(conn, pkt);
169: }
170: return 0;
171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.