home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
ek
/
simirid
/
simirid.c
< prev
next >
Wrap
C/C++ Source or Header
|
2020-01-01
|
9KB
|
361 lines
// simirid.c -- simulate iridium delays between two serial ports
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <sys/time.h> // for timeval
# include <time.h> // for timeval, gettimeofday
# include <ctype.h> // for isprint()
# include <sys/stat.h> // to check if pid is running
# include <termio.h> // for settty() gettty() args
# include <fcntl.h> // for open() args
# include <sys/types.h>
double now(void)
{
struct timeval tv;
struct timezone tz;
static time_t s0 = 0;
gettimeofday(&tv,&tz);
if(s0 == 0)
s0 = tv.tv_sec;
return (double)(tv.tv_sec - s0) + (double)(tv.tv_usec) * 1.0e-6;
}
void sleep_us(long us)
{
struct timeval timeout;
if(us <= 0)
return;
timeout.tv_sec = us/1000000L;
timeout.tv_usec = us%1000000L;
select(1, NULL, NULL, NULL, &timeout);
return;
}
int opentty(char *tty, long baud)
{
static struct termios settty;
int ret;
int baudflag;
int fdtty;
char ttydev[100];
// open first with no delay in order to change the bits to ignore
// handshaking lines, then open again for real.
sprintf(ttydev,"/dev/%s",tty);
if((fdtty=open(ttydev,O_RDWR | O_NDELAY))<0){
perror("first serial port open failed");
fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
return -1;
}
if (baud == 110) baudflag = B110;
else if(baud == 300) baudflag = B300;
else if(baud == 600) baudflag = B600;
else if(baud == 1200) baudflag = B1200;
else if(baud == 2400) baudflag = B2400;
else if(baud == 4800) baudflag = B4800;
else if(baud == 9600) baudflag = B9600;
else if(baud == 19200) baudflag = B19200;
else if(baud == 38400) baudflag = B38400;
else if(baud == 57600) baudflag = B57600;
else if(baud == 115200) baudflag = B115200;
else if(baud == 230400) baudflag = B230400;
else if(baud == 460800) baudflag = B460800;
else{
fprintf(stderr,"opentty(): bad baudrate=%ld\n",baud);
return -2;
}
# if 0
if((tcgetattr(fdtty, &settty)) < 0){
perror("tcgetattr() serial port failed");
fprintf(stderr,"ttydev=\"%s\" fdtty=%d\n",ttydev,fdtty);
return -6;
}
# endif
settty.c_iflag = 0;
settty.c_oflag = 0;
settty.c_cflag = 0;
settty.c_lflag = 0;
cfmakeraw(&settty);
settty.c_cflag |= CLOCAL; // ignore modem control lines
settty.c_cflag &= ~CRTSCTS; // no flow control
settty.c_cflag |= CREAD; // added June 21, 2002 per new tty driver
cfsetispeed(&settty,baudflag);
cfsetospeed(&settty,baudflag);
ret=tcsetattr(fdtty,TCSANOW,&settty);
if(ret<0){
perror("tcsetattr() serial port failed");
fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
return -3;
}
# if 0
if(close(fdtty) < 0){
perror("error: close() serial port open failed");
fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
return -4;
}
if((fdtty=open(ttydev,O_RDWR)) < 0){
perror("second serial port open failed");
fprintf(stderr,"ttydev=\"%s\"\n",ttydev);
return -5;
}
# endif
return fdtty;
}
int main(int argc, char** argv)
{
# define MBUF 10000
char buf1[MBUF], buf2[MBUF];
double time1[MBUF],time2[MBUF];
int head1=0, tail1=0;
int head2=0, tail2=0;
unsigned char kar, kar1, kar2;
int seq1,seq2;
int n1 = 0, n2 = 0;
char *ttydev1; // leafname of tty device
char *ttydev2; // leafname of tty device
long baud; // baudrate in both directions
double delay_min; // minimum seconds of one-way path delay
double delay_max; // maximum seconds of one-way path delay
double delay;
long usbc; // microseconds between characters
char tmp[100];
pid_t pid;
FILE *fplock2;
FILE *fplock1;
char lockfile1[100];
char lockfile2[100];
int fdtty1;
int fdtty2;
int selret;
double error_rate;
long error_thresh;
if(argc != 8){
fprintf(stderr,"usage: simirid tty1 tty2 baud delay_min delay_max "
"usbc error_rate\n");
exit(1);
}
ttydev1 = *++argv;
ttydev2 = *++argv;
baud = atol(*++argv);
delay_min = atof(*++argv);
delay_max = atof(*++argv);
usbc = atol(*++argv);
error_rate = atof(*++argv);
error_thresh = (double)RAND_MAX * error_rate;
sprintf(lockfile1,"/var/lock/LCK..%s",ttydev1);
if((fplock1 = fopen(lockfile1,"r"))!=NULL){
struct stat statbuf;
// fprintf(stderr,"lock file found: %s\n",lockfile1);
fscanf(fplock1,"%10d\n",&pid);
fclose(fplock1);
sprintf(tmp,"/proc/%d",pid);
// fprintf(stderr,"checking process %s\n",tmp);
if(stat(tmp,&statbuf) == -1){
// fprintf(stderr,"it is not running\n");
if(unlink(lockfile1) == -1){
perror("cannot remove lockfile1");
fprintf(stderr,"lockfile1=%s\n",lockfile1);
exit(1);
}
fprintf(stderr,"removed stale lockfile1=%s\n",lockfile1);
}
else{
fprintf(stderr,"lockfile1=%s indicates processs %d is using %s\n",
lockfile1,pid,ttydev1);
fprintf(stderr,"exiting\n");
exit(1);
}
}
sprintf(lockfile2,"/var/lock/LCK..%s",ttydev2);
if((fplock2 = fopen(lockfile2,"r"))!=NULL){
struct stat statbuf;
// fprintf(stderr,"lock file found: %s\n",lockfile2);
fscanf(fplock2,"%10d\n",&pid);
fclose(fplock2);
sprintf(tmp,"/proc/%d",pid);
// fprintf(stderr,"checking process %s\n",tmp);
if(stat(tmp,&statbuf) == -1){
// fprintf(stderr,"it is not running\n");
if(unlink(lockfile2) == -1){
perror("cannot remove lockfile2 2");
fprintf(stderr,"lockfile2 %s\n",lockfile2);
exit(1);
}
fprintf(stderr,"removed stale lockfile2 %s\n",lockfile2);
}
else{
fprintf(stderr,"lockfile2 %s indicates processs %d is using %s\n",
lockfile2,pid,ttydev2);
fprintf(stderr,"exiting\n");
exit(1);
}
}
if((fdtty1 = opentty(ttydev1, baud)) < 0){
fprintf(stderr,"opentty failed ");
fprintf(stderr,"ttydev1=%s fdtty1=%d\n",ttydev1,fdtty1);
unlink(lockfile1);
exit(1);
}
if((fdtty2 = opentty(ttydev2, baud)) < 0){
fprintf(stderr,"opentty failed ");
fprintf(stderr,"ttydev2=%s fdtty2=%d\n",ttydev2,fdtty2);
unlink(lockfile1);
unlink(lockfile2);
exit(1);
}
while(1){
int nfds;
fd_set readfds;
struct timeval timeout;
if(fdtty1 > fdtty2) nfds = fdtty1 + 1;
else nfds = fdtty2 + 1;
FD_ZERO(&readfds);
FD_SET(fdtty1,&readfds);
FD_SET(fdtty2,&readfds);
timeout.tv_sec = 0;
timeout.tv_usec = 1000L; // 1 ms timeout
selret = select(nfds, &readfds, NULL, NULL, &timeout);
if(selret < 0){
perror("select failed");
fprintf(stderr," selret=%d\n",selret);
goto cleanupandexit;
}
if(selret > 0){ // something's available
// this sleep_us simulates slow bit rate over RF link
// by causing time1 and time2 to be increased in order
// to delay output
sleep_us(usbc);
if(FD_ISSET(fdtty1,&readfds)){
if(read(fdtty1, (char*)(&kar), 1) != 1){
perror("read fdtty1 failed");
goto cleanupandexit;
}
if(0 && kar == 0xFF){
perror("fdtty1 read 0xFF character -- cannot use with telnet\n");
goto cleanupandexit;
}
if((long)(rand()) < error_thresh)
kar = rand() & 0xFF;
buf1[head1] = kar;
delay = delay_min +
(delay_max - delay_min) * (double)rand() / (double)(RAND_MAX);
time1[head1] = now() + delay;
head1++; if(head1 >= MBUF) head1=0;
}
if(FD_ISSET(fdtty2,&readfds)){
if(read(fdtty2, (char*)(&kar), 1) != 1){
perror("read fdtty2 failed");
goto cleanupandexit;
}
if(0 && kar == 0xFF){
perror("fdtty1 read 0xFF character -- cannot use with telnet\n");
goto cleanupandexit;
}
if((long)(rand()) < error_thresh)
kar = rand() & 0xFF;
buf2[head2] = kar;
delay = delay_min +
(delay_max - delay_min) * (double)rand() / (double)(RAND_MAX);
time2[head2] = now() + delay;
head2++; if(head2 >= MBUF) head2=0;
}
}
// the following is executed every input character or select timeout
if(head1 != tail1 && now() > time1[tail1]){
kar = buf1[tail1];
tail1++; if(tail1 >= MBUF) tail1=0;
n1++;
if(n1 == 2) seq1=kar-32;
if(n1 == 3){
if(kar!='Y' && kar!='N') fprintf(stderr,"\n");
fprintf(stderr,"h1: %2d-%c ",seq1,kar);
kar1=kar;
}
if(kar == 0x01) n1=0;
if(kar == 0x0d){
// fprintf(stderr,"h1: %2d-%c ",seq1,kar1);
fprintf(stderr,"n1: %4d ",n1);
}
if(write(fdtty2,&kar,1) != 1){
perror("write fdtty2 failed");
goto cleanupandexit;
}
}
if(head2 != tail2 && now() > time2[tail2]){
kar = buf2[tail2];
tail2++; if(tail2 >= MBUF) tail2=0;
n2++;
if(n2 == 2) seq2=kar-32;
if(n2 == 3){
if(kar!='Y' && kar!='N') fprintf(stderr,"\n");
fprintf(stderr,"h2: %2d-%c ",seq2,kar);
kar2=kar;
}
if(kar == 0x01) n2=0;
if(kar == 0x0d){
// fprintf(stderr,"h2: %2d-%c ",seq2,kar2);
fprintf(stderr,"n2: %4d ",n2);
}
if(write(fdtty1,&kar,1) != 1){
perror("write fdtty1 failed");
goto cleanupandexit;
}
}
}
unlink(lockfile1);
unlink(lockfile2);
fprintf(stderr,"simirid normal exit\n");
exit(0);
cleanupandexit:
unlink(lockfile1);
unlink(lockfile2);
fprintf(stderr,"simirid cleanup and exit\n");
exit(1);
}