[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How far is to far?




I've fixed the IP bouncer so it doesnt chew so much cpu any more,
backgrounds itself and detachs from the tty.  In testing last night,
it was using less %cpu than the telnet being used to connect to it on
the same machine (hope that bodes well! :).

Darren

-----------------------------------------------------------------------------
/* This file is telserv.c and is part of the Telnet Server package v. 1.0,
   written by "Hal-9000".  Much of this package was developed by Richard
   Stephens and my thanks go to "Xanadude" for providing me with that
   section.  Performance fix by Darren Reed.

   To compile, type "cc -O -s telserv.c -o telserv". */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#define	SERV_TCP_PORT	12345	/* port I'll listen for connections on */
#define	REM_HOST_ADDR	"127.0.0.1"	/* host I will bounce to */
#define	REM_TCP_PORT	19		/* port I will bounce to */

char sbuf[2048], cbuf[2048];

main()
{
  int sockfd, newsockfd, clilen, childpid, opt = 1;
  struct sockaddr_in  cli_addr, serv_addr;

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port        = htons(SERV_TCP_PORT);
  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) {
    perror("bind");
    exit(-1);
  }
  listen(sockfd, 5);
  setpgrp(getpid(), 0);
  close(0); close(1); close(2);
#ifdef TIOCNOTTY
  if ((newsockfd = open("/dev/tty", O_RDWR)) >= 0) {
    ioctl(newsockfd, TIOCNOTTY, (char *)0);
    close(newsockfd);
  }
#endif
  if (fork())
    exit(0);
  while (1) {
    clilen = sizeof(cli_addr);
    newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd == -1)
      exit(-1);
    setsockopt(newsockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    /*
    ** NB: FNDELAY and O_NDELAY aren't the same on all machines and on most
    ** we want FNDELAY.  The differences are subtle but differences all the
    ** same.
    */
#ifdef FNDELAY
    fcntl(newsockfd,F_SETFL,fcntl(newsockfd,F_GETFL,0)|FNDELAY);
#else
    fcntl(newsockfd,F_SETFL,O_NDELAY);
#endif
    childpid = fork();
    if (childpid == 0) {         /* child process */
      close(sockfd);             /* close original socket */
      telcli(newsockfd);         /* process the request */
      exit(0);
    }

    close(newsockfd);            /* parent process */
    wait(0);
    }
  }

telcli(clisockfd)
{
  int servsockfd;
  struct sockaddr_in  serv_addr;

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family       = AF_INET;
  serv_addr.sin_addr.s_addr  = inet_addr(REM_HOST_ADDR);
  serv_addr.sin_port         = htons(REM_TCP_PORT);
  servsockfd = socket(AF_INET, SOCK_STREAM, 0);
  connect(servsockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
#ifdef FNDELAY
  fcntl(servsockfd,F_SETFL,fcntl(clisockfd,F_GETFL,0)|FNDELAY);
#else
  fcntl(servsockfd,F_SETFL,O_NDELAY);
#endif
  communicate(servsockfd,clisockfd);
  close(servsockfd);
  exit(0);
}

communicate(sfd,cfd)  {
  char *chead, *ctail, *shead, *stail;
  int num, nfd, spos, cpos;
  extern int errno;
  fd_set rd, wr;

  chead = ctail = cbuf;
  cpos = 0;
  shead = stail = sbuf;
  spos = 0;

  while (1) {
    FD_ZERO(&rd);
    FD_ZERO(&wr);

    if (spos < sizeof(sbuf)-1)
      FD_SET(sfd, &rd);
    if (ctail > chead)
      FD_SET(sfd, &wr);
    if (cpos < sizeof(cbuf)-1)
      FD_SET(cfd, &rd);
    if (stail > shead)
      FD_SET(cfd, &wr);
    nfd = select(256, &rd, &wr, 0, 0);
    if (nfd <= 0)
      continue;

    if (FD_ISSET(sfd, &rd)) {
      num=read(sfd,stail,sizeof(sbuf)-spos);
      if ((num==-1) && (errno != EWOULDBLOCK)) return;
      if (num==0) return;
      if (num>0) {
        spos += num;
        stail += num;
	if (!--nfd)
	  continue;
      }
    }
    if (FD_ISSET(cfd, &rd)) {
      num=read(cfd,ctail,sizeof(cbuf)-cpos);
      if ((num==-1) && (errno != EWOULDBLOCK)) return;
	if (num==0) return;
	if (num>0) {
	  cpos += num;
	  ctail += num;
	  if (!--nfd)
	    continue;
      }
    }
    if (FD_ISSET(sfd, &wr)) {
      num=write(sfd,chead,ctail-chead);
      if ((num==-1) && (errno != EWOULDBLOCK)) return;
      if (num>0) {
        chead += num;
        if (chead == ctail) {
          chead = ctail = cbuf;
          cpos = 0;
        }
        if (!--nfd)
          continue;
      }
    }
    if (FD_ISSET(cfd, &wr)) {
      num=write(cfd,shead,stail-shead);
      if ((num==-1) && (errno != EWOULDBLOCK)) return;
      if (num>0) {
        shead += num;
        if (shead == stail) {
          shead = stail = sbuf;
          spos = 0;
        }
        if (!--nfd)
          continue;
      }
    }
  }
}