[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;
}
}
}
}