Annotation of researchv8dc/sys/chncp/chuser.c, revision 1.1.1.1

1.1       root        1: #include "../chunix/chsys.h"
                      2: #include "../chunix/chconf.h"
                      3: #include "../chaos/chaos.h"
                      4: 
                      5: /*
                      6:  * User (top level) interface routines. Mostly assumed called from low
                      7:  * priority unless otherwise mentioned.
                      8:  */
                      9: static struct packet *rfcseen; /* used by ch_rnext and ch_listen */
                     10: /*
                     11:  * Open a connection (send a RFC) given a destination host a RFC
                     12:  * packet, and a default receive window size.
                     13:  * Return the connection, on which the RFC has been sent.
                     14:  * The connection is not necessarily open at this point.
                     15:  */
                     16: struct connection *
                     17: ch_open(destaddr, rwsize, pkt)
                     18: struct packet *pkt;
                     19: {
                     20:        register struct connection *conn;
                     21: 
                     22:        if ((conn = allconn()) == NOCONN) {
                     23:                ch_free((char *)pkt);
                     24:                return(NOCONN);
                     25:        }
                     26:        conn->cn_faddr = destaddr;
                     27:        conn->cn_state = CSRFCSENT;
                     28:        conn->cn_fidx = 0;
                     29:        conn->cn_rwsize = rwsize;
                     30:        conn->cn_rsts = rwsize / 2;
                     31:        conn->cn_active = Chclock;
                     32:        pkt->pk_op = RFCOP;
                     33:        pkt->pk_fc = 0;
                     34:        pkt->pk_ackn = 0;
                     35:        debug(DCONN,printf("Conn #%x: RFCS state\n", conn->cn_lidx));
                     36:        /*
                     37:         * By making the RFC packet written like a data packet,
                     38:         * it will be freed by the normal receipting mechanism, enabling
                     39:         * to easily be kept around for automatic retransmission.
                     40:         * xmitdone (first half) and rcvpkt (handling OPEN pkts) help here.
                     41:         * Since allconn clears the connection (including cn_tlast) the
                     42:         * packet number of the RFC will be 1 (ch_write does pkn = ++tlast)
                     43:         */
                     44:        LOCK;
                     45:        (void)ch_write(conn, pkt);      /* No errors possible */
                     46:        UNLOCK;
                     47:        return(conn);
                     48: }
                     49: /*
                     50:  * Start a listener, given a packet with the contact name in it.
                     51:  * In all cases packet is consumed.
                     52:  * Connection returned is in the listen state.
                     53:  */
                     54: struct connection *
                     55: ch_listen(pkt)
                     56: struct packet *pkt;
                     57: {
                     58:        register struct connection *conn;
                     59:        register struct packet *pktl, *opkt;
                     60: 
                     61:        if ((conn = allconn()) == NOCONN) {
                     62:                ch_free((char *)pkt);
                     63:                return(NOCONN);
                     64:        }
                     65:        conn->cn_state = CSLISTEN;
                     66:        pkt->pk_op = LSNOP;
                     67:        setpkt(conn, pkt);
                     68:        LOCK;
                     69:        opkt = NOPKT;
                     70:        for (pktl = Chrfclist; pktl != NOPKT; pktl = (opkt = pktl)->pk_next)
                     71:                if (concmp(pktl, pkt->pk_cdata, (int)pkt->pk_len)) {
                     72:                        if(opkt == NOPKT)
                     73:                                Chrfclist = pktl->pk_next;
                     74:                        else
                     75:                                opkt->pk_next = pktl->pk_next;
                     76:                        if (pktl == Chrfctail)
                     77:                                Chrfctail = opkt;
                     78:                        if (pktl == rfcseen)
                     79:                                rfcseen = NOPKT;
                     80:                        ch_free((char *)pkt);
                     81:                        lsnmatch(pktl, conn);
                     82:                        UNLOCK;
                     83:                        return(conn);
                     84:                }
                     85:        /*
                     86:         * Should we check for duplicate listeners??
                     87:         * Or is it better to allow more than one?
                     88:         */
                     89:        pkt->pk_next = Chlsnlist;
                     90:        Chlsnlist = pkt;
                     91:        debug(DCONN,printf("Conn #%x: LISTEN state\n", conn->cn_lidx));
                     92:        UNLOCK;
                     93:        return(conn);
                     94: }
                     95: /*
                     96:  * Send a new data packet on a connection.
                     97:  * Called at high priority since window size check is elsewhere.
                     98:  */
                     99: ch_write(conn, pkt)
                    100: register struct connection *conn;
                    101: register struct packet *pkt;
                    102: {
                    103:        setpkt(conn, pkt);
                    104:        pkt->pk_next = NOPKT;   /* just to be sure! */
                    105:        switch (pkt->pk_op) {
                    106:        case ANSOP:
                    107:        case FWDOP:
                    108:                if (conn->cn_state != CSRFCRCVD ||
                    109:                    (conn->cn_flags & CHANSWER) == 0)
                    110:                        goto err;
                    111:                ch_close(conn, pkt, 0);
                    112:                return 0;
                    113:        case RFCOP:
                    114:                if (conn->cn_state != CSRFCSENT)
                    115:                        goto err;
                    116:                break;
                    117:        case UNCOP:
                    118:                pkt->pk_pkn = 0;
                    119:                senddata(pkt);
                    120:                return 0;
                    121:        default:
                    122:                if (!ISDATOP(pkt))
                    123:                        goto err;
                    124:        case OPNOP:
                    125:        case EOFOP:
                    126:                if (conn->cn_state != CSOPEN)
                    127:                        goto err;
                    128:                break;
                    129:        }
                    130:        pkt->pk_pkn = ++conn->cn_tlast;
                    131:        senddata(pkt);
                    132:        return 0;
                    133: err:
                    134:        ch_free((char *)pkt);
                    135:        return CHERROR;
                    136: }
                    137: /*
                    138:  * Consume the packet at the head of the received packet queue (rhead).
                    139:  * Assumes high priority because check for available is elsewhere
                    140:  */
                    141: ch_read(conn)
                    142: register struct connection *conn;
                    143: {
                    144:        register struct packet *pkt;
                    145: 
                    146:        if ((pkt = conn->cn_rhead) == NOPKT)
                    147:                return;
                    148:        conn->cn_rhead = pkt->pk_next;
                    149:        if (conn->cn_rtail == pkt)
                    150:                conn->cn_rtail = NOPKT;
                    151:        if (CONTPKT(pkt)) {
                    152:                conn->cn_rread = pkt->pk_pkn;
                    153:                if (pkt->pk_op == EOFOP ||
                    154:                    3 * (short)(conn->cn_rread - conn->cn_racked) > conn->cn_rwsize) {
                    155:                        debug(DPKT,
                    156:                                printf("Conn#%x: rread=%d rackd=%d rsts=%d\n",
                    157:                                conn->cn_lidx, conn->cn_rread,
                    158:                                conn->cn_racked, conn->cn_rsts));
                    159:                        pkt->pk_next = NOPKT;
                    160:                        makests(conn, pkt);
                    161:                        reflect(pkt);
                    162:                        return;
                    163:                }
                    164:        }
                    165:        ch_free((char *)pkt);
                    166: }
                    167: /*
                    168:  * Send an eof packet on a channel.
                    169:  */
                    170: ch_eof(conn)
                    171: struct connection *conn;
                    172: {
                    173:        register struct packet *pkt;
                    174:        register int ret = 0;
                    175: 
                    176:        if ((pkt = pkalloc(0, 0)) != NOPKT) {
                    177:                pkt->pk_op = EOFOP;
                    178:                pkt->pk_len = 0;
                    179:                ret = ch_write(conn, pkt);
                    180:        }
                    181:        return ret;
                    182: }
                    183: /*
                    184:  * Close a connection, giving close pkt to send (CLS or ANS).
                    185:  */
                    186: ch_close(conn, pkt, release)
                    187: register struct connection *conn;
                    188: register struct packet *pkt;
                    189: {
                    190:        int s = spl6();
                    191: 
                    192:        switch (conn->cn_state) {
                    193:            case CSOPEN:
                    194:            case CSRFCRCVD:
                    195:                if (pkt != NOPKT) {
                    196:                        pkt->pk_ackn = pkt->pk_pkn = 0;
                    197:                        setpkt(conn, pkt);
                    198:                        sendctl(pkt);
                    199:                        pkt = NOPKT;
                    200:                }
                    201:                /* Fall into... */
                    202:            case CSRFCSENT:
                    203:                clsconn(conn, CSCLOSED, NOPKT);
                    204:                break;
                    205:            case CSLISTEN:
                    206:                rmlisten(conn);
                    207:                break;
                    208:            default:
                    209:                break;
                    210:        }
                    211:        if (pkt)
                    212:                ch_free((char *)pkt);
                    213:        splx(s);
                    214:        if (release)
                    215:                rlsconn(conn);
                    216: }
                    217: /*
                    218:  * Top level raw sts sender - at high priority, like ch_write.
                    219:  */
                    220: ch_sts(conn)
                    221: struct connection *conn;
                    222: {
                    223:        sendsts(conn);          /* This must be locked */
                    224: }
                    225: /*
                    226:  * Accept an RFC, called on a connection in the CSRFCRCVD state.
                    227:  */
                    228: ch_accept(conn)
                    229: struct connection *conn;
                    230: {
                    231:        conn->cn_state = CSOPEN;
                    232:        sendopn(conn);
                    233: }
                    234: /*
                    235:  * Return the next rfc packet on the list, flushing the one previously
                    236:  * looked at if it hasn't been consumed (or skipped) yet.
                    237:  * Flushed RFC's get a Close packet sent back.
                    238:  * LOCK must be in effect when called. - High priority.
                    239:  */
                    240: struct packet *
                    241: ch_rnext()
                    242: {
                    243:        register struct packet *pkt, *lpkt;
                    244: 
                    245:        if ((pkt = Chrfclist) != NOPKT && rfcseen == pkt) {
                    246:                if ((Chrfclist = pkt->pk_next) == NOPKT)
                    247:                        Chrfctail = NOPKT;
                    248:                UNLOCK;
                    249:                if ((pkt = pktstr(pkt, "Contact name refused", 20)) != NOPKT) {
                    250:                        pkt->pk_op = CLSOP;
                    251:                        pkt->pk_fc = 0;
                    252:                        pkt->pk_ackn = pkt->pk_pkn = 0;
                    253:                        reflect(pkt);
                    254:                }
                    255:                LOCK;
                    256:                pkt = Chrfclist;
                    257:                rfcseen = NOPKT;
                    258:        }
                    259:        for (lpkt = pkt; pkt != NOPKT && pkt->pk_ackn != 0; pkt = pkt->pk_next)
                    260:                lpkt = pkt;
                    261:        if (pkt != NOPKT) {
                    262:                if (pkt != Chrfclist) {
                    263:                        Chrfctail->pk_next = Chrfclist;
                    264:                        Chrfclist = pkt;
                    265:                        lpkt->pk_next = NOPKT;
                    266:                        Chrfctail = lpkt;
                    267:                }
                    268:                rfcseen = pkt;
                    269:        }
                    270:        return (pkt);
                    271: }
                    272: /*
                    273:  * Skip the RFC at the head of the unmatched-rfc list, and mark it so that
                    274:  * ch_rnext never sees it again.  This is to allow an unmatched rfc server
                    275:  * to basically say that the RFC should be handled by a specific listener.
                    276:  * This would be necessary in the case where two calls for a given
                    277:  * specific listener - say login - came so close together that the
                    278:  * login server did not get done with the first one, and back inside the
                    279:  * listen before the next one came in. Called at low priority from top level.
                    280:  * To mark te RFC we set the pk_ackn to non-zero.  It is assured to be zero
                    281:  * when first queued.
                    282:  */
                    283: ch_rskip()
                    284: {
                    285:        register struct packet *pkt;
                    286: 
                    287:        if ((pkt = Chrfclist) != NOPKT && rfcseen == pkt) {
                    288:                pkt->pk_ackn = 1;
                    289:                rfcseen = NOPKT;
                    290:        }
                    291: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.