/*
File: proxy.c
Description: a general-purpose proxy optimized for a large number
of concurrent connections.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/event.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include "config.h"
#include "proxy_protos.h"
extern char *optarg;
extern int optind;
static int sig;
/* usage() */
static void usage ( void );
/* signal handler */
static void sighandler ( int signum );
/* main program */
int
main ( int argc, char **argv )
{
struct kevent ke;
struct mdata *md;
void (*ef)(struct kevent *, struct mdata * );
char ch;
unsigned short sp = 0;
unsigned short lp = 0;
char lh[MAXPATHLEN];
char rh[MAXPATHLEN];
char lf[MAXPATHLEN];
struct timespec ts;
int verbose = 0;
/* get options */
memset(lh,0,sizeof(lh));
memset(rh,0,sizeof(rh));
memset(lf,0,sizeof(lf));
while ( (ch = getopt(argc,argv,"a:b:h:p:l:v")) != -1 ) {
switch (ch) {
case 'a':
strncpy(lh,optarg,MAXPATHLEN-1);
break;
case 'b':
lp = (unsigned short)strtoul(optarg,NULL,10);
break;
case 'h':
strncpy(rh,optarg,MAXPATHLEN-1);
break;
case 'p':
sp = (unsigned short)strtoul(optarg,NULL,10);
break;
case 'l':
strncpy(lf,optarg,MAXPATHLEN-1);
break;
case 'v':
verbose = 1;
break;
}
}
argc -= optind;
argv += optind;
/* usage() */
if ( !sp || !lh[0] || !lp || !rh[0] ) {
usage();
exit(1);
}
fprintf(stderr,"Local host: %s\n", lh);
fprintf(stderr,"Local port: %u\n", lp);
fprintf(stderr,"Server host: %s\n", rh);
fprintf(stderr,"Server port: %u\n", sp);
/* set up signal handlers */
signal ( SIGINT, sighandler );
signal ( SIGTERM, sighandler );
signal ( SIGKILL, sighandler );
if ( fork() ) exit(0);
/* allocate the main data structure */
if ( !(md = init_mdata(lh,lp,rh,sp,lf,verbose)) ) {
perror("init_mdata");
exit(2);
}
/* set up the event queue, bind to the local port, and listen */
if ( !pay_attention(md) ) {
perror("pay_attention");
deinit_mdata(md);
exit(3);
}
/* enter the main event loop until a signal is received */
log_msg(md, "Entering event loop now");
/* 100 microsecond timeout */
ts.tv_sec = 0;
ts.tv_nsec = 100000;
while ( !sig ) {
while ( kevent(md->kq,NULL,0,&ke,1,&ts) > 0 ) {
md->events++;
ef = ke.udata;
ef(&ke,md);
}
md->iterations++;
}
/* print some info from this session */
print_stats(md);
/* free allocated memory */
deinit_mdata(md);
return 0;
}
static void
usage ( void )
{
fprintf(stderr,"Usage: %s -a <local host> -b <local port> -h <server host> -p <server port> [-l <logfile>] [-v]\n",
PACKAGE);
}
/*
signal handler, used for SIGINT, SIGTERM, SIGKILL
*/
static void
sighandler ( int signum )
{
sig = signum;
}
syntax highlighted by Code2HTML, v. 0.9.1