home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / uucp / pk0.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  9.8 KB  |  655 lines

  1. #define USER    1
  2. #include <stdio.h>
  3. #include <sys/pk.p>
  4. #include <sys/param.h>
  5. #include <sys/pk.h>
  6. #include <sys/buf.h>
  7.  
  8. /*
  9.  * packet driver
  10.  */
  11.  
  12. char next[8]    ={ 1,2,3,4,5,6,7,0};    /* packet sequence numbers */
  13. char mask[8]    ={ 1,2,4,010,020,040,0100,0200 };
  14.  
  15. struct pack *pklines[NPLINES];
  16.  
  17.  
  18.  
  19. /*
  20.  * receive control messages
  21.  */
  22. pkcntl(c, pk)
  23. register struct pack *pk;
  24. {
  25. register cntl, val;
  26.  
  27.     val = c & MOD8;
  28.     cntl = (c>>3) & MOD8;
  29.  
  30.     if ( ! ISCNTL(c) ) {
  31.         fprintf(stderr, "not cntl\n");
  32.         return;
  33.     }
  34.  
  35.     if (pk->p_mode & 02)
  36.         fprintf(stderr, "%o ",c);
  37.     switch(cntl) {
  38.  
  39.     case INITB:
  40.         val++;
  41.         pk->p_xsize = pksizes[val];
  42.         pk->p_lpsize = val;
  43.         pk->p_bits = DTOM(pk->p_xsize);
  44.         if (pk->p_state & LIVE) {
  45.             pk->p_msg |= M_INITC;
  46.             break;
  47.         }
  48.         pk->p_state |= INITb;
  49.         if ((pk->p_state & INITa)==0) {
  50.             break;
  51.         }
  52.         pk->p_rmsg &= ~M_INITA;
  53.         pk->p_msg |= M_INITC;
  54.         break;
  55.  
  56.     case INITC:
  57.         if ((pk->p_state&INITab)==INITab) {
  58.             pk->p_state = LIVE;
  59.             WAKEUP(&pk->p_state);
  60.             pk->p_rmsg &= ~M_INITB;
  61.         } else
  62.             pk->p_msg |= M_INITB;
  63.         if (val)
  64.             pk->p_swindow = val;
  65.         break;
  66.     case INITA:
  67.         if (val==0 && pk->p_state&LIVE) {
  68.             fprintf(stderr, "alloc change not implemented\n");
  69.             break;
  70.         }
  71.         if (val) {
  72.             pk->p_state |= INITa;
  73.             pk->p_msg |= M_INITB;
  74.             pk->p_rmsg |= M_INITB;
  75.             pk->p_swindow = val;
  76.         }
  77.         break;
  78.     case RJ:
  79.         pk->p_state |= RXMIT;
  80.         pk->p_msg |= M_RR;
  81.     case RR:
  82.         pk->p_rpr = val;
  83.         if (pksack(pk)==0) {
  84.             WAKEUP(&pk->p_ps);
  85.         }
  86.         break;
  87.     case SRJ:
  88.         fprintf(stderr, "srj not implemented\n");
  89.         break;
  90.     case CLOSE:
  91.         pk->p_state = DOWN+RCLOSE;
  92.         SIGNAL;
  93.         WAKEUP(&pk->p_pr);
  94.         WAKEUP(&pk->p_ps);
  95.         WAKEUP(&pk->p_state);
  96.         return;
  97.     }
  98. out:
  99.     if (pk->p_msg)
  100.         pkoutput(pk);
  101. }
  102.  
  103.  
  104.  
  105. pkaccept(pk)
  106. register struct pack *pk;
  107. {
  108. register x,seq;
  109. char m, cntl, *p, imask, **bp;
  110. int bad,accept,skip,s,t,h,cc;
  111. unsigned short sum;
  112.  
  113.     bad = accept = skip = 0;
  114.     /*
  115.      * wait for input
  116.      */
  117.     LOCK;
  118.     x = next[pk->p_pr];
  119.     while ((imask=pk->p_imap) == 0 && pk->p_rcount==0) {
  120.         PKGETPKT(pk);
  121.         SLEEP(&pk->p_pr, PKIPRI);
  122.     }
  123.     pk->p_imap = 0;
  124.     UNLOCK;
  125.  
  126.  
  127.     /*
  128.      * determine input window in m.
  129.      */
  130.     t = (~(-1<<pk->p_rwindow)) <<x;
  131.     m = t;
  132.     m |= t>>8;
  133.  
  134.  
  135.     /*
  136.      * mark newly accepted input buffers
  137.      */
  138.     for(x=0; x<8; x++) {
  139.  
  140.         if ((imask & mask[x]) == 0)
  141.             continue;
  142.  
  143.         if (((cntl=pk->p_is[x])&0200)==0) {
  144.             bad++;
  145. free:
  146.             bp = (char **)pk->p_ib[x];
  147.             LOCK;
  148.             *bp = (char *)pk->p_ipool;
  149.             pk->p_ipool = bp;
  150.             pk->p_is[x] = 0;
  151.             UNLOCK;
  152.             continue;
  153.         }
  154.  
  155.         pk->p_is[x] = ~(B_COPY+B_MARK);
  156.         sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl;
  157.         sum += pk->p_isum[x];
  158.         if (sum == CHECK) {
  159.             seq = (cntl>>3) & MOD8;
  160.             if (m & mask[seq]) {
  161.                 if (pk->p_is[seq] & (B_COPY | B_MARK)) {
  162.                 dup:
  163.                     pk->p_msg |= M_RR;
  164.                     skip++;
  165.                     goto free;
  166.                 }
  167.                 if (x != seq) {
  168.                     LOCK;
  169.                     p = pk->p_ib[x];
  170.                     pk->p_ib[x] = pk->p_ib[seq];
  171.                     pk->p_is[x] = pk->p_is[seq];
  172.                     pk->p_ib[seq] = p;
  173.                     UNLOCK;
  174.                 }
  175.                 pk->p_is[seq] = B_MARK;
  176.                 accept++;
  177.                 cc = 0;
  178.                 if (cntl&B_SHORT) {
  179.                     pk->p_is[seq] = B_MARK+B_SHORT;
  180.                     p = pk->p_ib[seq];
  181.                     cc = (unsigned)*p++;
  182.                     if (cc & 0200) {
  183.                         cc &= 0177;
  184.                         cc |= *p << 7;
  185.                     }
  186.                 }
  187.                 pk->p_isum[seq] = pk->p_rsize - cc;
  188.             } else {
  189.                 goto dup;
  190.             }
  191.         } else {
  192.             bad++;
  193.             goto free;
  194.         }
  195.     }
  196.  
  197.     /*
  198.      * scan window again turning marked buffers into
  199.      * COPY buffers and looking for missing sequence
  200.      * numbers.
  201.      */
  202.     accept = 0;
  203.     for(x=next[pk->p_pr],t=h= -1; m & mask[x]; x = next[x]) {
  204.         if (pk->p_is[x] & B_MARK)
  205.             pk->p_is[x] |= B_COPY;
  206.     /*  hole code 
  207.         if (pk->p_is[x] & B_COPY) {
  208.             if (h<0 && t>=0)
  209.                 h = x;
  210.         } else {
  211.             if (t<0)
  212.                 t = x;
  213.         }
  214.     */
  215.         if (pk->p_is[x] & B_COPY) {
  216.             if (t >= 0) {
  217.                 bp = (char **)pk->p_ib[x];
  218.                 LOCK;
  219.                 *bp = (char *)pk->p_ipool;
  220.                 pk->p_ipool = bp;
  221.                 pk->p_is[x] = 0;
  222.                 UNLOCK;
  223.                 skip++;
  224.             } else 
  225.                 accept++;
  226.         } else {
  227.             if (t<0)
  228.                 t = x;
  229.         }
  230.     }
  231.  
  232.     if (bad) {
  233.         pk->p_msg |= M_RJ;
  234.     }
  235.  
  236.     if (skip) {
  237.         pk->p_msg |= M_RR;
  238.     }
  239.  
  240.     pk->p_rcount = accept;
  241.     return(accept);
  242. }
  243.  
  244.  
  245. pkread(S)
  246. SDEF;
  247. {
  248. register struct pack *pk;
  249. register x,s;
  250. int is,cc,xfr,count;
  251. char *cp, **bp;
  252.  
  253.     pk = PADDR;
  254.     xfr = 0;
  255.     count = 0;
  256.     while (pkaccept(pk)==0);
  257.  
  258.  
  259.     while (UCOUNT) {
  260.  
  261.         x = next[pk->p_pr];
  262.         is = pk->p_is[x];
  263.  
  264.         if (is & B_COPY) {
  265.             cc = MIN(pk->p_isum[x], UCOUNT);
  266.             if (cc==0 && xfr) {
  267.                 break;
  268.             }
  269.             if (is & B_RESID)
  270.                 cp = pk->p_rptr;
  271.             else {
  272.                 cp = pk->p_ib[x];
  273.                 if (is & B_SHORT) {
  274.                     if (*cp++ & 0200)
  275.                         *cp++;
  276.                 }
  277.             }
  278.             IOMOVE(cp,cc,B_READ);
  279.             count += cc;
  280.             xfr++;
  281.             pk->p_isum[x] -= cc;
  282.             if (pk->p_isum[x] == 0) {
  283.                 pk->p_pr = x;
  284.                 bp = (char **)pk->p_ib[x];
  285.                 LOCK;
  286.                 *bp = (char *)pk->p_ipool;
  287.                 pk->p_ipool = bp;
  288.                 pk->p_is[x] = 0;
  289.                 pk->p_rcount--;
  290.                 UNLOCK;
  291.                 pk->p_msg |= M_RR;
  292.             } else {
  293.                 pk->p_rptr = cp+cc;
  294.                 pk->p_is[x] |= B_RESID;
  295.             }
  296.             if (cc==0)
  297.                 break;
  298.         } else
  299.             break;
  300.     }
  301.     pkoutput(pk);
  302.     return(count);
  303. }
  304.  
  305.  
  306.  
  307.  
  308. pkwrite(S)
  309. SDEF;
  310. {
  311. register struct pack *pk;
  312. register x;
  313. int partial;
  314. caddr_t cp;
  315. int cc, s, fc, count;
  316. int pktimeout();
  317.  
  318.     pk = PADDR;
  319.     if (pk->p_state&DOWN || !pk->p_state&LIVE) {
  320.         SETERROR;
  321.         return(-1);
  322.     }
  323.  
  324.     count = UCOUNT;
  325.     do {
  326.         LOCK;
  327.         while (pk->p_xcount>=pk->p_swindow)  {
  328.             pkoutput(pk);
  329.             PKGETPKT(pk);
  330.             SLEEP(&pk->p_ps,PKOPRI);
  331.         }
  332.         x = next[pk->p_pscopy];
  333.         while (pk->p_os[x]!=B_NULL)  {
  334.             PKGETPKT(pk);
  335.             SLEEP(&pk->p_ps,PKOPRI);
  336.         }
  337.         pk->p_os[x] = B_MARK;
  338.         pk->p_pscopy = x;
  339.         pk->p_xcount++;
  340.         UNLOCK;
  341.  
  342.         cp = pk->p_ob[x] = GETEPACK;
  343.         partial = 0;
  344.         if ((int)UCOUNT < pk->p_xsize) {
  345.             cc = UCOUNT;
  346.             fc = pk->p_xsize - cc;
  347.             *cp = fc&0177;
  348.             if (fc > 127) {
  349.                 *cp++ |= 0200;
  350.                 *cp++ = fc>>7;
  351.             } else
  352.                 cp++;
  353.             partial = B_SHORT;
  354.         } else
  355.             cc = pk->p_xsize;
  356.         IOMOVE(cp,cc,B_WRITE);
  357.         pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
  358.         pk->p_os[x] = B_READY+partial;
  359.         pkoutput(pk);
  360.     } while (UCOUNT);
  361.  
  362.     return(count);
  363. }
  364.  
  365. pksack(pk)
  366. register struct pack *pk;
  367. {
  368. register x, i;
  369.  
  370.     i = 0;
  371.     for(x=pk->p_ps; x!=pk->p_rpr; ) {
  372.         x = next[x];
  373.         if (pk->p_os[x]&B_SENT) {
  374.             i++;
  375.             pk->p_os[x] = B_NULL;
  376.             pk->p_state &= ~WAITO;
  377.             pk->p_xcount--;
  378.             FREEPACK(pk->p_ob[x], pk->p_bits);
  379.             pk->p_ps = x;
  380.             WAKEUP(&pk->p_ps);
  381.         }
  382.     }
  383.     return(i);
  384. }
  385.  
  386.  
  387.  
  388. pkoutput(pk)
  389. register struct pack *pk;
  390. {
  391. register x,rx;
  392. int s;
  393. char bstate;
  394. int i;
  395. SDEF;
  396. int flag;
  397.  
  398.     flag = 0;
  399.     ISYSTEM;
  400.     LOCK;
  401.     if (pk->p_obusy++ || OBUSY) {
  402.         pk->p_obusy--;
  403.         UNLOCK;
  404.         return;
  405.     }
  406.     UNLOCK;
  407.  
  408.  
  409.     /*
  410.      * find seq number and buffer state
  411.      * of next output packet
  412.      */
  413.     if (pk->p_state&RXMIT)  {
  414.         pk->p_nxtps = next[pk->p_rpr];
  415.         flag++;
  416.     }
  417.     x = pk->p_nxtps;
  418.     bstate = pk->p_os[x];
  419.  
  420.  
  421.     /*
  422.      * Send control packet if indicated
  423.      */
  424.     if (pk->p_msg) {
  425.         if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
  426.             x = pk->p_msg;
  427.             for(i=0; i<8; i++) 
  428.                 if (x&1)
  429.                     break; else
  430.                 x >>= 1;
  431.             x = i;
  432.             x <<= 3;
  433.             switch(i) {
  434.             case CLOSE:
  435.                 break;
  436.             case RJ:
  437.             case RR:
  438.                 x += pk->p_pr;
  439.                 break;
  440.             case SRJ:
  441.                 break;
  442.             case INITB:
  443.                 x += pksize(pk->p_rsize);
  444.                 break;
  445.             case INITC:
  446.                 x += pk->p_rwindow;
  447.                 break;
  448.             case INITA:
  449.                 x += pk->p_rwindow;
  450.                 break;
  451.             }
  452.  
  453.             pk->p_msg &= ~mask[i];
  454.             pkxstart(pk, x, -1);
  455.             goto out;
  456.         }
  457.     }
  458.  
  459.  
  460.     /*
  461.      * Don't send data packets if line is marked dead.
  462.      */
  463.     if (pk->p_state&DOWN) {
  464.         WAKEUP(&pk->p_ps);
  465.         goto out;
  466.     }
  467.     /*
  468.      * Start transmission (or retransmission) of data packets.
  469.      */
  470.     if (bstate & (B_READY|B_SENT)) {
  471.         char seq;
  472.  
  473.         bstate |= B_SENT;
  474.         seq = x;
  475.         pk->p_nxtps = next[x];
  476.  
  477.         x = 0200+pk->p_pr+(seq<<3);
  478.         if (bstate & B_SHORT)
  479.             x |= 0100;
  480.         pkxstart(pk, x, seq);
  481.         pk->p_os[seq] = bstate;
  482.         pk->p_state &= ~RXMIT;
  483.         pk->p_nout++;
  484.         goto out;
  485.     }
  486.     /*
  487.      * enable timeout if there's nothing to send
  488.      * and transmission buffers are languishing
  489.      */
  490.     if (pk->p_xcount) {
  491.         pk->p_timer = 2;
  492.         pk->p_state |= WAITO;
  493.     } else
  494.         pk->p_state &= ~WAITO;
  495.     WAKEUP(&pk->p_ps);
  496. out:
  497.     pk->p_obusy = 0;
  498. }
  499.  
  500.  
  501. /*
  502.  * shut down line by
  503.  *    ignoring new input
  504.  *    letting output drain
  505.  *    releasing space and turning off line discipline
  506.  */
  507. pkclose(S)
  508. SDEF;
  509. {
  510. register struct pack *pk;
  511. register i,s,rbits;
  512. char **bp;
  513. int rcheck;
  514. char *p;
  515.  
  516.  
  517.     pk = PADDR;
  518.     pk->p_state |= DRAINO;
  519.  
  520.  
  521.     /*
  522.      * try to flush output
  523.      */
  524.     i = 0;
  525.     LOCK;
  526.     pk->p_timer = 2;
  527.     while (pk->p_xcount && pk->p_state&LIVE) {
  528.         if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
  529.             break;
  530.         pkoutput(pk);
  531.         SLEEP(&pk->p_ps,PKOPRI);
  532.     }
  533.     pk->p_timer = 0;
  534.     pk->p_state |= DOWN;
  535.     UNLOCK;
  536.  
  537.  
  538.     /*
  539.      * try to exchange CLOSE messages
  540.      */
  541.     i = 0;
  542.     while ((pk->p_state&RCLOSE)==0 && i<2) {
  543.         pk->p_msg = M_CLOSE;
  544.         pk->p_timer = 2;
  545.         pkoutput(pk);
  546.         SLEEP(&pk->p_ps, PKOPRI);
  547.         i++;
  548.     }
  549.  
  550.  
  551.     for(i=0;i<NPLINES;i++)
  552.         if (pklines[i]==pk)  {
  553.             pklines[i] = NULL;
  554.         }
  555.     TURNOFF;
  556.  
  557.  
  558.     /*
  559.      * free space
  560.      */
  561.     rbits = DTOM(pk->p_rsize);
  562.     rcheck = 0;
  563.     for (i=0;i<8;i++) {
  564.         if (pk->p_os[i]!=B_NULL) {
  565.             FREEPACK(pk->p_ob[i],pk->p_bits);
  566.             pk->p_xcount--;
  567.         }
  568.         if (pk->p_is[i]!=B_NULL)  {
  569.             FREEPACK(pk->p_ib[i],rbits);
  570.             rcheck++;
  571.         }
  572.     }
  573.     LOCK;
  574.     while (pk->p_ipool != NULL) {
  575.         bp = pk->p_ipool;
  576.         pk->p_ipool = (char **)*bp;
  577.         rcheck++;
  578.         FREEPACK(bp, rbits);
  579.     }
  580.     UNLOCK;
  581.     if (rcheck  != pk->p_rwindow) {
  582.         fprintf(stderr, "r short %d want %d\n",rcheck,pk->p_rwindow);
  583.         fprintf(stderr, "rcount = %d\n",pk->p_rcount);
  584.         fprintf(stderr, "xcount = %d\n",pk->p_xcount);
  585.     }
  586.     FREEPACK((caddr_t)pk, npbits);
  587. }
  588.  
  589.  
  590.  
  591. pkreset(pk)
  592. register struct pack *pk;
  593. {
  594.  
  595.     pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
  596.     pk->p_nxtps = 1;
  597. }
  598.  
  599. chksum(s,n)
  600. register char *s;
  601. register n;
  602. {
  603.     register short sum;
  604.     register unsigned t;
  605.     register x;
  606.  
  607.     sum = -1;
  608.     x = 0;
  609.  
  610.     do {
  611.         if (sum<0) {
  612.             sum <<= 1;
  613.             sum++;
  614.         } else
  615.             sum <<= 1;
  616.         t = sum;
  617.         sum += (unsigned)*s++;
  618.         x += sum^n;
  619.         if ((unsigned)sum <= t) {
  620.             sum ^= x;
  621.         }
  622.     } while (--n > 0);
  623.  
  624.     return(sum);
  625. }
  626.  
  627. pkline(pk)
  628. register struct pack *pk;
  629. {
  630. register i;
  631.     for(i=0;i<NPLINES;i++) {
  632.         if (pklines[i]==pk)
  633.             return(i);
  634.     }
  635.     return(-i);
  636. }
  637.  
  638. pkzero(s,n)
  639. register char *s;
  640. register n;
  641. {
  642.     while (n--)
  643.         *s++ = 0;
  644. }
  645.  
  646. pksize(n)
  647. register n;
  648. {
  649. register k;
  650.  
  651.     n >>= 5;
  652.     for(k=0; n >>= 1; k++);
  653.     return(k);
  654. }
  655.