home *** CD-ROM | disk | FTP | other *** search
/ Toolkit for DOOM / DOOMTOOL.ISO / net_doom / ihhd.zip / tcpdialer.c < prev   
C/C++ Source or Header  |  1994-02-20  |  8KB  |  422 lines

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <sys/time.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <errno.h>
  7. #include <netdb.h>
  8. #include <stdio.h>
  9. #include <sgtty.h>
  10. #include <signal.h>
  11. #include <time.h>
  12.  
  13. /*
  14.  * tcpdialer - talk to a switch and remote dialer.
  15.  *
  16.  * usage: tcpdialer [ -e escape_char ] [ -l logfile ] [ -s ] [ -rp port ] [ -lp port ] [ -m max_tries ] -call host | -answer
  17.  * 
  18.  * ARGUMENTS
  19.  * -e escape_char Change escape character, enter as numeric value of the
  20.  *            character, use '\01' to set it to CNTRL-A
  21.  * -l logfile    Log data transfer to logfile.out and logfile.in.
  22.  * -s        Generate I/O stats when done.
  23.  * -lp port    Local port number to use.
  24.  * -rp port    Port number to use when on remote host.
  25.  * -m max_tries    Maximum number of connection attempts.
  26.  * -call host    Remote host to call.
  27.  * -answer    Answer any callers.
  28.  *
  29.  * Terminate using by typing ^C^C^C (three control-Cs).
  30.  */
  31.  
  32. static char* sccsid = "@(#)tcpdialer.c    1.7    10/29/93";
  33.  
  34. #define MOUTHPIECE    0
  35. #define MAXPKTSIZE    1024
  36. #define ON        1
  37. #define OFF        0
  38. #define CTRLC        '\003'
  39.  
  40. FILE* outputlogf = NULL;
  41. FILE* inputlogf = NULL;
  42. struct sockaddr_in datagram;
  43. struct sgttyb saved_tty;
  44. time_t start_time = 0;
  45. char* program;
  46. char* remotehost = NULL;
  47. char* logfile = NULL;
  48. char packet[MAXPKTSIZE];
  49. char escape_char = CTRLC;
  50. short remoteport = 6123;
  51. short localport = 6123;
  52. short statistics = 0;
  53. short answermode = 0;
  54. short max_tries = 30;
  55. int pktcount = 0;
  56. int minpktsize = MAXPKTSIZE + 1;
  57. int maxpktsize = 0;
  58. int totalsize = 0;
  59. int sock;
  60.  
  61. void terminate();
  62. void sig_child_handler();
  63.  
  64. main(argc, argv)
  65.     int     argc;
  66.     char**    argv;
  67. {
  68.  
  69.     program = *argv;
  70.  
  71.     for (argc--, argv++; argc; argc--, argv++) {
  72.         if (!strcmp(*argv, "-rp")) {
  73.             remoteport = atoi(*(argv+1));
  74.             argc--;
  75.             argv++;
  76.         }
  77.         else if (!strcmp(*argv, "-lp")) {
  78.             localport = atoi(*(argv+1));
  79.             argc--;
  80.             argv++;
  81.         }
  82.         else if (!strcmp(*argv, "-e")) {
  83.             argv++;
  84.             argc--;
  85.             escape_char = atoi(*argv) && 0xff;
  86.             fprintf(stderr, "escape char set to %d\n",escape_char);
  87.         }
  88.         else if (!strcmp(*argv, "-l")) {
  89.             logfile = *(argv+1);
  90.             argv++;
  91.             argc--;
  92.         }
  93.         else if (!strcmp(*argv, "-s")) {
  94.             statistics = 1;
  95.         }
  96.         else if (!strcmp(*argv, "-m")) {
  97.             max_tries = atoi(*(argv+1));
  98.             argc--;
  99.             argv++;
  100.         }
  101.         else if (!strcmp(*argv, "-call")) {
  102.             remotehost = *++argv;
  103.             argc--;
  104.         }
  105.         else if (!strcmp(*argv, "-answer")) {
  106.             answermode = 1;
  107.         }
  108.         else {
  109.             fprintf(stderr, "usage: dialer [ -e escape_char ] [ -l logfile ] [ -s ] [ -rp port ] [ -lp port ] [ -m max_tries ] -call host | -answer \n");
  110.             exit(1);
  111.         }
  112.     }
  113.  
  114.     /* verify proper mode */
  115.     if ( remotehost && answermode ) {
  116.         fprintf(stderr, "usage: dialer [ -s ] [ -rp port ] [ -lp port ] [ -m max_tries ] -call host | -answer \n");
  117.         exit(1);
  118.     }
  119.     if ( !remotehost && !answermode ) {
  120.         fprintf(stderr, "usage: dialer [ -s ] [ -rp port ] [ -lp port ] [ -m max_tries ] -call host | -answer \n");
  121.         exit(1);
  122.     }
  123.  
  124.     init_socket();
  125.  
  126.     save_tty_settings();
  127.     raw();
  128.     echo(OFF);
  129.  
  130.     /* the following never return */
  131.     if (make_handset() == MOUTHPIECE) {
  132.         signal(SIGTERM, terminate);
  133.         do_mouthpiece();
  134.     }
  135.     else {
  136.         /* when mouthpiece dies, we should too */
  137.         signal(SIGCHLD, sig_child_handler);
  138.  
  139.         do_earpiece();
  140.     }
  141.  
  142.     exit(0);
  143. }
  144.  
  145. /* this socket will be used for both sending and receiving */
  146. init_socket() {
  147.  
  148.     void open_sock();
  149.     struct sockaddr_in name;
  150.     struct sockaddr_in saddr;
  151.     struct hostent* hp;
  152.     int msgsock;
  153.     int errcode;
  154.     int tries = 0;
  155.     int len;
  156.  
  157.     open_sock();
  158.  
  159.     /* bind it */
  160.     if (answermode) {
  161.         name.sin_family = AF_INET;
  162.         name.sin_addr.s_addr = INADDR_ANY;
  163.         name.sin_port = htons(localport);
  164.         if (bind(sock, (struct sockaddr*)&name, sizeof name) < 0) {
  165.             perror("binding datagram socket");
  166.             exit(2);
  167.         }
  168.  
  169.         printf("Waiting for call...");
  170.         fflush(stdout);
  171.         listen(sock, 2);
  172.         msgsock = accept(sock, (struct sockaddr*)0, (int*)0);
  173.         if (msgsock == -1) {
  174.             perror("accepting connection from remote host");
  175.             exit(2);
  176.         }
  177.         len = sizeof(saddr);
  178.         if (getpeername(msgsock, &saddr, &len) == 0) {
  179.             printf("\007answered call from %s\n",inet_ntoa(saddr.sin_addr));
  180.         }
  181.         else {
  182.             printf("\007answered call\n");
  183.         }
  184.         close(sock);
  185.         sock = msgsock;
  186.     }
  187.     else {
  188.         name.sin_family = AF_INET;
  189.         hp = gethostbyname(remotehost);
  190.         if (hp == 0) {
  191.             fprintf(stderr, "%s: unknown host\n", remotehost);
  192.             exit(2);
  193.         }
  194.         bcopy((char*)hp->h_addr, (char*)&name.sin_addr,hp->h_length);
  195.         name.sin_port = htons(remoteport);
  196.  
  197.         /* try to make the connection */
  198.         while (1) {
  199.             printf("Ringing %s...", remotehost);
  200.             fflush(stdout);
  201.             errcode = connect(sock, (struct sockaddr*)&name,
  202.                       sizeof name);
  203.             if (errcode == -1) {
  204.                 if (errno == ECONNREFUSED || errno == EINTR) {
  205.                     sleep(5);
  206.                     if (++tries < max_tries) {
  207.                         printf("\n");
  208.                         close(sock);
  209.                         open_sock();
  210.                         continue;
  211.                     }
  212.                     else {
  213.                         /* too many retries */
  214.                         perror("connect");
  215.                         exit(2);
  216.                     }
  217.                 }
  218.                 else {
  219.                     /* error during connect */
  220.                     perror("connect");
  221.                     exit(2);
  222.                 }
  223.             }
  224.             else {
  225.                 printf("\007connected\n");
  226.                 break;
  227.             }
  228.         }
  229.     }
  230. }
  231.  
  232. void open_sock() {
  233.  
  234.     int on = 1;
  235.  
  236.     sock = socket(AF_INET, SOCK_STREAM, 0);
  237.     if (sock < 0) {
  238.         perror("opening datagram socket");
  239.         exit(2);
  240.     }
  241.  
  242. #ifdef SO_KEEPALIVE
  243.     /* use keepalives to force us to die when the remote dies */
  244.     if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) {
  245.           perror("cannot set sock option");
  246.     }
  247. #endif
  248. }
  249.  
  250. /* create a reader process */
  251. make_handset() {
  252.  
  253.     /*
  254.      * The reader process reads the tty and sends the data
  255.      * to the remote host.
  256.      */
  257.  
  258.     int pid = fork();
  259.     if (pid < 0) {
  260.         perror("forking reader process");
  261.         exit(3);
  262.     }
  263.  
  264.     return pid;
  265. }
  266.  
  267. do_mouthpiece() {
  268.  
  269.     struct timeval tv;
  270.     int bytecount;
  271.     int endsequence = 0;
  272.     char logname[1024];
  273.  
  274.     /* logfile prep */
  275.     if (logfile) {
  276.         strcpy(logname, logfile);
  277.         strcat(logname, ".out");
  278.         outputlogf = fopen(logname, "w");
  279.     }
  280.  
  281.     /* record starting time */
  282.     time(&start_time);
  283.  
  284.     while (1) {
  285.         /* keep delay between read/write to a minimum! */
  286.         bytecount = read(0, packet, 1024);
  287.         if (bytecount) {
  288.             if (write(sock, packet, bytecount) < 0)
  289.                 perror("sending datagram message");
  290.     
  291.             /* log data */
  292.             if (outputlogf) {
  293.                 gettimeofday(&tv, NULL);
  294.                 fwrite(&tv, sizeof(tv), 1, outputlogf);
  295.                 fwrite(&bytecount, sizeof(bytecount), 1, outputlogf);
  296.                 fwrite(packet, sizeof(char), bytecount, outputlogf);
  297.             }
  298.  
  299.             if (bytecount == 1 && (packet[0]&0177) == escape_char) {
  300.                 if (++endsequence == 3)
  301.                     terminate();
  302.             }
  303.             else
  304.                 endsequence = 0;
  305.  
  306.             /* statistics generation */
  307.             pktcount++;
  308.             totalsize += bytecount;
  309.             if (bytecount < minpktsize) minpktsize = bytecount;
  310.             else if (bytecount > maxpktsize) maxpktsize = bytecount;
  311.         }
  312.     }
  313. }
  314.  
  315. do_earpiece() {
  316.  
  317.     struct timeval tv;
  318.     int bytecount;
  319.     char logname[1024];
  320.  
  321.     /* logfile prep */
  322.     if (logfile) {
  323.         strcpy(logname, logfile);
  324.         strcat(logname, ".in");
  325.         inputlogf = fopen(logname, "w");
  326.     }
  327.  
  328.     while (1) {
  329.         bytecount = read(sock, packet, 1024);
  330.         if (bytecount > 0) {
  331.             write(1, packet, bytecount);
  332.  
  333.             /* log data */
  334.             if (inputlogf) {
  335.                 gettimeofday(&tv, NULL);
  336.                 fwrite(&tv, sizeof(tv), 1, inputlogf);
  337.                 fwrite(&bytecount, sizeof(bytecount), 1, inputlogf);
  338.                 fwrite(packet, sizeof(char), bytecount, inputlogf);
  339.             }
  340.         }
  341.     }
  342. }
  343.  
  344. /* save the original tty settings */
  345. save_tty_settings() {
  346.     gtty(0, &saved_tty);
  347. }
  348.  
  349. /* restore the original tty settings */
  350. restore_tty_settings() {
  351.     stty(0, &saved_tty);
  352. }
  353.  
  354. /* place the terminal in raw mode */
  355. raw() {
  356.     struct sgttyb tty;
  357.  
  358.     gtty(0, &tty);
  359.     tty.sg_flags |= RAW;
  360.     stty(0, &tty);
  361. }
  362.  
  363. /* place the terminal in cooked mode */
  364. cooked() {
  365.     struct sgttyb tty;
  366.  
  367.     gtty(0, &tty);
  368.     tty.sg_flags &= ~RAW;
  369.     stty(0, &tty);
  370. }
  371.  
  372. echo(on) 
  373.     int on;
  374. {
  375.  
  376.     struct sgttyb tty;
  377.  
  378.     gtty(0, &tty);
  379.     if (on) {
  380.         tty.sg_flags |= ECHO;
  381.     }
  382.     else
  383.         tty.sg_flags &= ~ECHO;
  384.  
  385.     stty(0, &tty);
  386. }
  387.  
  388. void sig_child_handler() {
  389.  
  390.     restore_tty_settings();
  391.  
  392.     if (outputlogf)
  393.         fclose(outputlogf);
  394.     if (inputlogf)
  395.         fclose(inputlogf);
  396.  
  397.     exit(0);
  398. }
  399.  
  400. void terminate() {
  401.  
  402.     time_t time_diff = time(0) - start_time;
  403.  
  404.     if (outputlogf)
  405.         fclose(outputlogf);
  406.     if (inputlogf)
  407.         fclose(inputlogf);
  408.  
  409.     /* report statistics */
  410.     if (statistics) {
  411.         printf("%d packets, %d bytes, %d/%d/%d min/avg/max pkt size\r\n",
  412.             pktcount, totalsize, minpktsize, totalsize/pktcount, 
  413.             maxpktsize);
  414.         if (time_diff)
  415.             printf("%d seconds, %g pkt/s, %d b/s\r\n",
  416.                 time_diff, (float)pktcount / (float)time_diff, 
  417.                 totalsize/time_diff);
  418.     }
  419.  
  420.     exit(0);
  421. }
  422.