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