home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / pcmail / part03 / kphys.c < prev    next >
C/C++ Source or Header  |  1989-02-03  |  8KB  |  214 lines

  1. /*++
  2. /* NAME
  3. /*      kphys 3
  4. /* SUMMARY
  5. /*      k protocol packet exchange
  6. /* PACKAGE
  7. /*      uucp across the TUEnet
  8. /* SYNOPSIS
  9. /*      #include "kp.h"
  10. /*
  11. /*      kspack(fd,type,num,size,data) 
  12. /*      int fd, num, size;
  13. /*      char type, data[MAXPACKSIZ];
  14. /*
  15. /*      krpack(fd,num,size,data)
  16. /*      int fd, *num, *size;
  17. /*      char data[MAXPACKSIZ];
  18. /* DESCRIPTION
  19. /*      The functions in this file take care of data framing and verification. 
  20. /*
  21. /*      Kspack() sends a packet of the specified type and number,
  22. /*      and with len data bytes.
  23. /*
  24. /*      Krpack() tries to receive a packet and returns: the packet type plus
  25. /*      size and data, or TIME (no packet) or FAIL (bad checksum).
  26. /*
  27. /*      The data format has been derived from kermit implementations:
  28. /*
  29. /* .nf
  30. /* .in +5
  31. /*      SOH     packet header, ASCII control-P
  32. /*      len     (size of data, low 6 bits) + 32
  33. /*      len     (size of data, high 6 bits) + 32
  34. /*      num     (packet number mod 64) + 32
  35. /*      type    packet type
  36. /*      check   one-byte type-1 kermit checksum
  37. /*
  38. /*      The header is followed by checksummed data if len >0:
  39. /*
  40. /* .nf
  41. /* .in +5
  42. /*      data    len data bytes
  43. /*      check1  (upper 2 bits of type-3 kermit 16-bit checksum) + 32
  44. /*      check2  (middle 6 bits of type-3 kermit 16-bit checksum) + 32
  45. /*      check3  (lower 6 bits of type-3 kermit 16-bit checksum) + 32
  46. /*
  47. /*      Every packet is followed by an ASCII carriage return, which is
  48. /*      ignored upon reception of a packet. It prevents timeout errors
  49. /*      when one byte gets lost (the most common case).
  50. /* BUGS
  51. /*      It is yet another convention for data framing.
  52. /* AUTHOR(S)
  53. /*      Wietse Venema
  54. /*      Eindhoven University of Technology
  55. /*      Department of Mathematics and Computer Science
  56. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  57. /* CREATION DATE
  58. /*      Mon Feb  3 13:38:14 MET 1986
  59. /* LAST MODIFICATION
  60. /*    Mon Apr  4 23:43:13 MET 1988
  61. /* VERSION/RELEASE
  62. /*    1.5
  63. /*--*/
  64.  
  65. #include <signal.h>
  66. #include <setjmp.h>
  67. #include "kp.h"
  68.  
  69. #define READS(fd,ch)    {if (read(fd,&ch,1) < 0) clkint(); if ((ch &= 0177) == SOH) goto SYNC;}
  70.  
  71. jmp_buf env;                /* Environment ptr for timeout longjump */
  72.  
  73. clkint()                                /* Timer interrupt handler */
  74. {
  75.     longjmp(env,TRUE);                  /* Tell krpack to give up */
  76. }
  77.  
  78. kspack(fd,type,num,len,data)
  79. int fd;
  80. char type, *data;
  81. int num, len;
  82. {
  83.     char chksum, header[6], chk[3];     /* Checksums, header */
  84.  
  85.     DEBUG(7,"xmt: type %c\n",type);
  86.     if (len > 0)
  87.     DEBUG(7,"xmt: data %d\n",len);
  88.  
  89.     header[0] = SOH;                    /* Packet marker (SOH) */
  90.     header[1] = tosix(len);             /* Send the character count */
  91.     chksum    = header[1];              /* Initialize the checksum */
  92.     header[2] = tosix(len>>OUT);        /* Send the character count */
  93.     chksum   += header[2];              /* Update checksum */
  94.     header[3] = tochar(num);            /* Packet number */
  95.     chksum   += header[3];              /* Update checksum */
  96.     header[4] = type;                   /* Packet type */
  97.     chksum   += header[4];              /* Update checksum */
  98.     chksum    = (((chksum&0300) >> 6)+chksum)&077; /* Compute header checksum */
  99.     header[5] = tochar(chksum);         /* Put it in the packet */
  100.     write(fd,header,6);                /* Send the header */
  101.  
  102.     if (len > 0) {                      /* Make data packet */
  103.     write(fd,data,len);           /* Send data */
  104.     chk3(data,len,chk);           /* Compute 16-bit checksum */
  105.     write(fd,chk,3);              /* Send checksum */
  106.     }
  107.     write(fd,"\r",1);                   /* Extra-packet line terminator */
  108. }
  109.  
  110. krpack(fd,num,len,data)
  111. int fd;
  112. int *num;                               /* Packet number */
  113. int *len;                               /* Packet length */
  114. char *data;                             /* Packet data */
  115. {
  116.     int i;                              /* Data character number, loop exit */
  117.     char t,                             /* Current input character */
  118.     type,                           /* Packet type */
  119.     rchk[3],                        /* Data checksum from host */
  120.     cchk[3],                        /* Data checksum computed here */
  121.     cchksum,                        /* Our (computed) checksum */
  122.     rchksum;                        /* Header checksum from other host */
  123.  
  124.     if (setjmp(env)) {
  125.     DEBUG(7,"rcv: timed out\n","");
  126.     return TIME;                    /* Timed out */
  127.     }
  128.     signal(SIGALRM,clkint);             /* Setup the timeout */
  129.     alarm(TIMEOUT);
  130.  
  131.     for (;;)                            /* Wait for packet header */
  132.     READS(fd,t);
  133. SYNC:                                   /* Got SOH */
  134.     alarm(TIMEOUT);
  135.     DEBUG(7,"rcv: found sync\n","");
  136.     READS(fd,t);                        /* Get character */
  137.     cchksum = t;                        /* Start the checksum */
  138.     *len = unchar(t);                   /* Character count, low six bits */
  139.  
  140.     READS(fd,t);                        /* Get character */
  141.     cchksum += t;                       /* Update checksum */
  142.     *len += (unchar(t)<<OUT);           /* Character count, high six bits */
  143.  
  144.     READS(fd,t);                        /* Get character */
  145.     cchksum += t;                       /* Update checksum */
  146.     *num = unchar(t);                   /* Packet number */
  147.  
  148.     READS(fd,t);                        /* Get character */
  149.     cchksum += t;                       /* Update checksum */
  150.     type = t;                           /* Packet type */
  151.  
  152.     READS(fd,t);                        /* Get header checksum */
  153.     rchksum = unchar(t);                /* Convert to numeric */
  154.     /* Fold in bits 7,8 to compute */
  155.     cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* header checksum */
  156.  
  157.     if (cchksum != rchksum) {
  158.     DEBUG(7,"rcv: bad header\n","");
  159.     alarm(0);                       /* Disable the timer interrupt */
  160.     return FAIL;
  161.     } 
  162.     DEBUG(7,"rcv: type %c\n",type);
  163.  
  164.     if ((*len > 0) && (data != NULLP))
  165.     {
  166.     for (i=0; i<*len; i++)          /* The data itself, if any */
  167.     {                               /* Loop for character count */
  168.         READS(fd,t);                /* Get character */
  169.         data[i] = t;                /* Keep data */
  170.     }
  171.  
  172.     for (i=0; i<3; i++)             /* 16-bit CRC checksum */
  173.     {
  174.         READS(fd,t);                /* Get character */
  175.         rchk[i] = t;                /* Keep data */
  176.     }
  177.  
  178.     chk3(data,*len,cchk);           /* Compute CRC */
  179.     if (strncmp(rchk,cchk,3)) {     /* Check with received CRC */
  180.         DEBUG(7,"rcv: bad data\n","");
  181.         alarm(0);                   /* Disable the timer interrupt */
  182.         return FAIL;
  183.     }
  184.     DEBUG(7,"rcv: data %d\n",*len);
  185.     }
  186.     alarm(0);                /* Disable the timer interrupt */
  187.     return(type);                       /* All OK, return packet type */
  188. }
  189.  
  190. /*  C H K 3  --  Compute a type-3 Kermit block check.  */
  191. /*
  192. Calculate the 16-bit CRC of a string using a byte-oriented
  193. tableless algorithm invented by Andy Lowry (Columbia University).  The
  194. magic number 010201 is derived from the CRC-CCITT polynomial x^16+x^12+x^5+1.
  195. */
  196. static chk3(s,len,chk) 
  197. char *s, *chk; 
  198. int len; 
  199. {
  200.     unsigned int c, q;
  201.     long crc = 0;
  202.  
  203.     while (len--) {
  204.     c = *s++;
  205.     q = (crc ^ c) & 017;            /* Low-order nibble */
  206.     crc = (crc >> 4) ^ (q * 010201);
  207.     q = (crc ^ (c >> 4)) & 017;     /* High order nibble */
  208.     crc = (crc >> 4) ^ (q * 010201);
  209.     }
  210.     *chk++ = tochar(((unsigned)(crc & 0170000)) >> 12);
  211.     *chk++ = tochar((crc & 07700) >> 6);
  212.     *chk++ = tochar(crc & 077);
  213. }
  214.