Annotation of researchv8dc/sys/chncp/chuser.c, revision 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.