home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / simirid.zip / simirid.c < prev    next >
C/C++ Source or Header  |  2010-02-09  |  9KB  |  361 lines

  1. // simirid.c -- simulate iridium delays between two serial ports
  2.  
  3. # include <stdio.h>
  4. # include <stdlib.h>
  5. # include <unistd.h>
  6. # include <string.h>
  7.  
  8. # include <sys/time.h>  // for timeval
  9. # include <time.h>      // for timeval, gettimeofday
  10. # include <ctype.h>     // for isprint()
  11. # include <sys/stat.h>  // to check if pid is running
  12. # include <termio.h>    // for settty() gettty() args
  13. # include <fcntl.h>     // for open() args
  14. # include <sys/types.h>
  15.  
  16. double now(void)
  17. {
  18.     struct timeval tv;
  19.     struct timezone tz;
  20.  
  21.     static time_t s0 = 0;
  22.  
  23.     gettimeofday(&tv,&tz);
  24.  
  25.     if(s0 == 0)
  26.         s0 = tv.tv_sec;
  27.  
  28.     return (double)(tv.tv_sec - s0) + (double)(tv.tv_usec) * 1.0e-6;
  29. }
  30.  
  31. void sleep_us(long us)
  32. {
  33.     struct timeval timeout;
  34.     if(us <= 0)
  35.         return;
  36.     timeout.tv_sec  = us/1000000L;
  37.     timeout.tv_usec = us%1000000L;
  38.     select(1, NULL, NULL, NULL, &timeout);
  39.     return;
  40. }
  41.  
  42. int opentty(char *tty, long baud)
  43. {
  44.     static struct termios settty;
  45.     int ret;
  46.     int baudflag;
  47.     int fdtty;
  48.     char ttydev[100];
  49.  
  50.     // open first with no delay in order to change the bits to ignore
  51.     // handshaking lines, then open again for real.
  52.  
  53.     sprintf(ttydev,"/dev/%s",tty);
  54.  
  55.     if((fdtty=open(ttydev,O_RDWR | O_NDELAY))<0){
  56.         perror("first serial port open failed");
  57.         fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
  58.         return -1;
  59.     }
  60.  
  61.     if     (baud == 110) baudflag = B110;
  62.     else if(baud == 300) baudflag = B300;
  63.     else if(baud == 600) baudflag = B600;
  64.     else if(baud == 1200) baudflag = B1200;
  65.     else if(baud == 2400) baudflag = B2400;
  66.     else if(baud == 4800) baudflag = B4800;
  67.     else if(baud == 9600) baudflag = B9600;
  68.     else if(baud == 19200) baudflag = B19200;
  69.     else if(baud == 38400) baudflag = B38400;
  70.     else if(baud == 57600) baudflag = B57600;
  71.     else if(baud == 115200) baudflag = B115200;
  72.     else if(baud == 230400) baudflag = B230400;
  73.     else if(baud == 460800) baudflag = B460800;
  74.     else{
  75.         fprintf(stderr,"opentty(): bad baudrate=%ld\n",baud);
  76.         return -2;
  77.     }
  78.  
  79. # if 0
  80.     if((tcgetattr(fdtty, &settty)) < 0){
  81.         perror("tcgetattr() serial port failed");
  82.         fprintf(stderr,"ttydev=\"%s\" fdtty=%d\n",ttydev,fdtty);
  83.         return -6;
  84.     }
  85. # endif
  86.  
  87.     settty.c_iflag = 0;
  88.     settty.c_oflag = 0;
  89.     settty.c_cflag = 0;
  90.     settty.c_lflag = 0;
  91.     cfmakeraw(&settty);
  92.     settty.c_cflag |= CLOCAL;        // ignore modem control lines
  93.     settty.c_cflag &= ~CRTSCTS;   // no flow control
  94.     settty.c_cflag |= CREAD;        // added June 21, 2002 per new tty driver
  95.     cfsetispeed(&settty,baudflag);
  96.     cfsetospeed(&settty,baudflag);
  97.  
  98.     ret=tcsetattr(fdtty,TCSANOW,&settty);
  99.     if(ret<0){
  100.         perror("tcsetattr() serial port failed");
  101.         fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
  102.         return -3;
  103.     }
  104.  
  105. # if 0
  106.     if(close(fdtty) < 0){
  107.         perror("error: close() serial port open failed");
  108.         fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
  109.         return -4;
  110.     }
  111.  
  112.     if((fdtty=open(ttydev,O_RDWR)) < 0){
  113.         perror("second serial port open failed");
  114.         fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
  115.         return -5;
  116.     }
  117. # endif
  118.  
  119.     return fdtty;
  120. }
  121.  
  122. int main(int argc, char** argv)
  123. {
  124.     # define MBUF 10000
  125.     char buf1[MBUF], buf2[MBUF];
  126.     double time1[MBUF],time2[MBUF];
  127.     int head1=0, tail1=0;
  128.     int head2=0, tail2=0;
  129.     unsigned char kar, kar1, kar2;
  130.     int seq1,seq2;
  131.     int n1 = 0, n2 = 0;
  132.  
  133.     char *ttydev1; // leafname of tty device
  134.     char *ttydev2; // leafname of tty device
  135.     long baud;     // baudrate in both directions
  136.     double delay_min;  // minimum seconds of one-way path delay
  137.     double delay_max;  // maximum seconds of one-way path delay
  138.     double delay;
  139.     long usbc;     // microseconds between characters
  140.  
  141.     char tmp[100];
  142.     pid_t pid;
  143.     FILE *fplock2;
  144.     FILE *fplock1;
  145.     char lockfile1[100];
  146.     char lockfile2[100];
  147.     int fdtty1;
  148.     int fdtty2;
  149.     int selret;
  150.     double error_rate;
  151.     long error_thresh;
  152.  
  153.     if(argc != 8){
  154.         fprintf(stderr,"usage: simirid tty1 tty2 baud delay_min delay_max "
  155.             "usbc error_rate\n");
  156.         exit(1);
  157.     }
  158.  
  159.     ttydev1 = *++argv;
  160.     ttydev2 = *++argv;
  161.     baud    = atol(*++argv);
  162.     delay_min   = atof(*++argv);
  163.     delay_max   = atof(*++argv);
  164.     usbc    = atol(*++argv);
  165.     error_rate  = atof(*++argv);
  166.  
  167.     error_thresh = (double)RAND_MAX * error_rate;
  168.  
  169.     sprintf(lockfile1,"/var/lock/LCK..%s",ttydev1);
  170.     if((fplock1 = fopen(lockfile1,"r"))!=NULL){
  171.         struct stat statbuf;
  172. //        fprintf(stderr,"lock file found: %s\n",lockfile1);
  173.         fscanf(fplock1,"%10d\n",&pid);
  174.         fclose(fplock1);
  175.         sprintf(tmp,"/proc/%d",pid);
  176. //        fprintf(stderr,"checking process %s\n",tmp);
  177.         if(stat(tmp,&statbuf) == -1){
  178. //            fprintf(stderr,"it is not running\n");
  179.             if(unlink(lockfile1) == -1){
  180.                 perror("cannot remove lockfile1");
  181.                 fprintf(stderr,"lockfile1=%s\n",lockfile1);
  182.                 exit(1);
  183.             }
  184.             fprintf(stderr,"removed stale lockfile1=%s\n",lockfile1);
  185.         }
  186.         else{
  187.             fprintf(stderr,"lockfile1=%s indicates processs %d is using %s\n",
  188.                     lockfile1,pid,ttydev1);
  189.             fprintf(stderr,"exiting\n");
  190.             exit(1);
  191.         }
  192.     }
  193.  
  194.     sprintf(lockfile2,"/var/lock/LCK..%s",ttydev2);
  195.     if((fplock2 = fopen(lockfile2,"r"))!=NULL){
  196.         struct stat statbuf;
  197. //        fprintf(stderr,"lock file found: %s\n",lockfile2);
  198.         fscanf(fplock2,"%10d\n",&pid);
  199.         fclose(fplock2);
  200.         sprintf(tmp,"/proc/%d",pid);
  201. //        fprintf(stderr,"checking process %s\n",tmp);
  202.         if(stat(tmp,&statbuf) == -1){
  203. //            fprintf(stderr,"it is not running\n");
  204.             if(unlink(lockfile2) == -1){
  205.                 perror("cannot remove lockfile2 2");
  206.                 fprintf(stderr,"lockfile2 %s\n",lockfile2);
  207.                 exit(1);
  208.             }
  209.             fprintf(stderr,"removed stale lockfile2 %s\n",lockfile2);
  210.         }
  211.         else{
  212.             fprintf(stderr,"lockfile2 %s indicates processs %d is using %s\n",
  213.                     lockfile2,pid,ttydev2);
  214.             fprintf(stderr,"exiting\n");
  215.             exit(1);
  216.         }
  217.     }
  218.  
  219.     if((fdtty1 = opentty(ttydev1, baud)) < 0){
  220.         fprintf(stderr,"opentty failed ");
  221.         fprintf(stderr,"ttydev1=%s fdtty1=%d\n",ttydev1,fdtty1);
  222.         unlink(lockfile1);
  223.         exit(1);
  224.     }
  225.  
  226.     if((fdtty2 = opentty(ttydev2, baud)) < 0){
  227.         fprintf(stderr,"opentty failed ");
  228.         fprintf(stderr,"ttydev2=%s fdtty2=%d\n",ttydev2,fdtty2);
  229.         unlink(lockfile1);
  230.         unlink(lockfile2);
  231.         exit(1);
  232.     }
  233.  
  234.     while(1){
  235.         int nfds;
  236.         fd_set readfds;
  237.         struct timeval timeout;
  238.  
  239.         if(fdtty1 > fdtty2) nfds = fdtty1 + 1;
  240.         else                nfds = fdtty2 + 1;
  241.  
  242.         FD_ZERO(&readfds);
  243.         FD_SET(fdtty1,&readfds);
  244.         FD_SET(fdtty2,&readfds);
  245.  
  246.         timeout.tv_sec  = 0;
  247.         timeout.tv_usec = 1000L;   // 1 ms timeout
  248.  
  249.         selret = select(nfds, &readfds, NULL, NULL, &timeout);
  250.  
  251.         if(selret < 0){
  252.             perror("select failed");
  253.             fprintf(stderr,"  selret=%d\n",selret);
  254.             goto cleanupandexit;
  255.         }
  256.  
  257.         if(selret > 0){  // something's available
  258.  
  259.             // this sleep_us simulates slow bit rate over RF link
  260.             // by causing time1 and time2 to be increased in order
  261.             // to delay output
  262.             sleep_us(usbc);
  263.  
  264.             if(FD_ISSET(fdtty1,&readfds)){
  265.                 if(read(fdtty1, (char*)(&kar), 1) != 1){
  266.                     perror("read fdtty1 failed");
  267.                     goto cleanupandexit;
  268.                 }
  269.                 if(0 && kar == 0xFF){
  270.                     perror("fdtty1 read 0xFF character -- cannot use with telnet\n");
  271.                     goto cleanupandexit;
  272.                 }
  273.                 if((long)(rand()) < error_thresh)
  274.                     kar = rand() & 0xFF;
  275.                 buf1[head1] = kar;
  276.                 delay = delay_min +
  277.                     (delay_max - delay_min) * (double)rand() / (double)(RAND_MAX);
  278.                 time1[head1] = now() + delay;
  279.                 head1++; if(head1 >= MBUF) head1=0;
  280.             }
  281.  
  282.             if(FD_ISSET(fdtty2,&readfds)){
  283.                 if(read(fdtty2, (char*)(&kar), 1) != 1){
  284.                     perror("read fdtty2 failed");
  285.                     goto cleanupandexit;
  286.                 }
  287.                 if(0 && kar == 0xFF){
  288.                     perror("fdtty1 read 0xFF character -- cannot use with telnet\n");
  289.                     goto cleanupandexit;
  290.                 }
  291.                 if((long)(rand()) < error_thresh)
  292.                     kar = rand() & 0xFF;
  293.                 buf2[head2] = kar;
  294.                 delay = delay_min +
  295.                     (delay_max - delay_min) * (double)rand() / (double)(RAND_MAX);
  296.                 time2[head2] = now() + delay;
  297.                 head2++; if(head2 >= MBUF) head2=0;
  298.             }
  299.         }
  300.  
  301.         // the following is executed every input character or select timeout
  302.  
  303.         if(head1 != tail1 && now() > time1[tail1]){
  304.             kar = buf1[tail1];
  305.             tail1++; if(tail1 >= MBUF) tail1=0;
  306.  
  307.             n1++;
  308.             if(n1 == 2) seq1=kar-32;
  309.             if(n1 == 3){
  310.                 if(kar!='Y' && kar!='N') fprintf(stderr,"\n");
  311.                 fprintf(stderr,"h1: %2d-%c ",seq1,kar);
  312.                 kar1=kar;
  313.             }
  314.             if(kar == 0x01) n1=0;
  315.             if(kar == 0x0d){
  316. //                fprintf(stderr,"h1: %2d-%c ",seq1,kar1);
  317.                 fprintf(stderr,"n1: %4d ",n1);
  318.             }
  319.  
  320.             if(write(fdtty2,&kar,1) != 1){
  321.                 perror("write fdtty2 failed");
  322.                 goto cleanupandexit;
  323.             }
  324.         }
  325.  
  326.         if(head2 != tail2 && now() > time2[tail2]){
  327.             kar = buf2[tail2];
  328.             tail2++; if(tail2 >= MBUF) tail2=0;
  329.  
  330.             n2++;
  331.             if(n2 == 2) seq2=kar-32;
  332.             if(n2 == 3){
  333.                 if(kar!='Y' && kar!='N') fprintf(stderr,"\n");
  334.                 fprintf(stderr,"h2: %2d-%c ",seq2,kar);
  335.                 kar2=kar;
  336.             }
  337.             if(kar == 0x01) n2=0;
  338.             if(kar == 0x0d){
  339. //                fprintf(stderr,"h2: %2d-%c ",seq2,kar2);
  340.                 fprintf(stderr,"n2: %4d ",n2);
  341.             }
  342.  
  343.             if(write(fdtty1,&kar,1) != 1){
  344.                 perror("write fdtty1 failed");
  345.                 goto cleanupandexit;
  346.             }
  347.         }
  348.     }
  349.     
  350.     unlink(lockfile1);
  351.     unlink(lockfile2);
  352.     fprintf(stderr,"simirid normal exit\n");
  353.     exit(0);
  354.  
  355. cleanupandexit:
  356.     unlink(lockfile1);
  357.     unlink(lockfile2);
  358.     fprintf(stderr,"simirid cleanup and exit\n");
  359.     exit(1);
  360. }
  361.