📄 webmaster.c
字号:
/* $Id: webmaster.c 81998 2008-06-17 09:31:15Z sma $ */
/**************************************************************************
* *
* Copyright (C) 1995 Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs were *
* developed by SGI for public use. If any changes are made to this code*
* please try to get the changes back to the author. Feel free to make *
* modifications and changes to the code and release it. *
* *
**************************************************************************/
/* FUZZ: disable check_for_math_include */
/* FUZZ: disable check_for_improper_main_declaration */
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifndef WIN32
#include <unistd.h>
#endif /* WIN32 */
#include <math.h>
#ifndef WIN32
#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#else
#define FD_SETSIZE 1024 /* max size for select() - keep before <winsock.h>
* and same size as MAXCLIENTS */
#include <windows.h>
#include <winsock.h>
#include <io.h>
#include <process.h>
#endif /* WIN32 */
#include "sysdep.h"
#include "bench.h"
/* command line options/data */
int savefile = 0;
int debug = 0;
int norexec = 0;
int haveproxyserver = 0;
char proxyserver[MAXHOSTNAMELEN];
char network_mask_str[30] = "255.255.255.0";
unsigned network_mask = 0;
int servaddrin_config = 0;
int dumpall = 0;
int testtime = 0;
int havewebserver = 0;
int numloops = 0;
NETPORT portnum = 0;
int redirect = 0;
int record_all_transactions = 0;
int uil_filelist_f = 0;
int verbose = 0;
char webserver[MAXHOSTNAMELEN];
char configfile[MAXPATHLEN];
char uil_filelist[NCCARGS];
char filelist[256][MAXPATHLEN];
fd_set zerofdset;
/* other key data */
long int number_of_pages = 0;
int totalnumclients = 0;
int num_rexecs = 0;
SOCKET socknum[MAXCLIENTS];
SOCKET sockIO[MAXTOTALPROCS];
SOCKET sockErr[MAXTOTALPROCS];
THREAD FILE *debugfile = stderr;
struct hostent *master_phe; /* IP addresses for webmaster */
struct timeval sumedh_start, sumedh_end;
void HostEntCpy(struct hostent *dest, struct hostent *src);
static void
usage(const char *progname)
{
fprintf(stderr, "Usage: %s [-a] [-d] -f config_file [-l numloops]\n",
progname);
fprintf(stderr, " [-p port_num] [-r] [-s] [-t run_time] \n");
fprintf(stderr, "\n");
fprintf(stderr, "-w webserver URL [URL ...]\n\n");
fprintf(stderr, "-a print timing information for all clients\n");
fprintf(stderr, "-d turn on debug statements\n");
fprintf(stderr, "-f config_file\tfile specifying clients\n");
fprintf(stderr, "-l number of iterations to retrieve uils\n");
fprintf(stderr, "-p port number of web server if not 80\n");
fprintf(stderr, "-r redirect stdout of clients to /tmp/webstone.xxx\n");
fprintf(stderr, "-s save client gets to /tmp/webstone.data.*\n");
fprintf(stderr, "-t run_time\tduration of test in minutes\n");
fprintf(stderr, "-w webserver\tname of webserver host to contact\n");
fprintf(stderr, "-u URL file\tfilelist of URLs\n");
fprintf(stderr, "-v verbose mode\n");
fprintf(stderr, "-P servername\tuse proxy server for transactions\n");
fprintf(stderr, "-W webserver addresses are in the config file\n");
fprintf(stderr, "-R record all transactions\n");
errexit("\n");
}
static SOCKET
passivesock(const NETPORT portnum, const char *protocol, const int qlen)
{
struct protoent *ppe; /* pointer to protocol info entry */
struct sockaddr_in sin; /* Internet endpoint address */
SOCKET s; /* socket descriptor */
int type; /* socket type */
D_PRINTF( "Beginning passivesock with errno %d\n",errno );
D_PRINTF( "Zeroing address structure\n" );
memset((char *)&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
/* NOT USED: Map service name to portnumber */
D_PRINTF( "Mapping portnum errno %d\n",errno );
sin.sin_port = htons(portnum);
/* Map protocol name to number */
D_PRINTF( "Mapping protocol name errno %d\n",errno );
if ((ppe = getprotobyname(protocol)) == 0)
{
errexit("Can't get \"%s\" protocol entry\n", protocol);
}
errno = 0;
/* use protocol to choose socket type */
D_PRINTF( "Changing socket type, errno %d\n",errno );
if (strcmp(protocol, "udp") == 0)
{
type = SOCK_DGRAM;
D_PRINTF( "Choosing SOCK_DGRAM\n" );
}
else
{
type = SOCK_STREAM;
D_PRINTF( "Choosing SOCK_STREAM, errno %d\n",errno );
}
/* allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (BADSOCKET(s))
{
D_PRINTF( "Socket PF_INET %d %d returned %d with %s\n",
type, ppe->p_proto, s, neterrstr() );
errexit("Can't create socket: %s\n", neterrstr());
}
D_PRINTF( "Socket %d created with errno %d\n",s,errno );
/* Bind the socket */
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
errexit("Can't bind to port %d: %s\n", portnum, neterrstr());
}
D_PRINTF( "Bind succeeded\n" );
/* If it's a stream, listen for connections */
/* NOTE: ON NT, the listen() backlog parm is silently limited to 5 conns */
if ((type == SOCK_STREAM) && BADSOCKET(listen(s, qlen)))
{
errexit("Can't listen on port %s: %s\n", portnum, neterrstr());
}
D_PRINTF( "Listen succeeded\n" );
/* all done, return socket descriptor */
return(s);
}
/* abort clients -- called by SIGINT handler */
static void abort_clients(void)
{
/* Not supposed to have fprintf in a signal handler, but... */
fprintf(stdout, "Webmaster received SIGINT. Terminating.\n");
/* exit will close all open connections */
exit(2);
}
/* signal handler for SIGINT */
static void sig_int(int sig) {
abort_clients();
}
#ifdef WIN32
/* echo stdout/stderr from clients */
void echo_client(void *stream)
{
SOCKET *sockarr;
FILE *outfile;
int which_stream = (int) stream;
char buf[BUFSIZ];
int i, len, rv;
fd_set readfds;
/* This code which handles the timeout may need
to be ifdef'ed for WIN32 */
struct timeval timeout;
timeout.tv_sec = (long)5;
timeout.tv_usec = (long)0;
if (which_stream) {
sockarr = sockIO;
outfile = stdout;
} else {
sockarr = sockErr;
outfile = stderr;
}
D_PRINTF( "echo_client running\n" );
signal( SIGINT, SIG_DFL); /* restore default behavior
for SIGINT */
while (1) {
FD_ZERO(&readfds);
for (i = 0; i < num_rexecs; i++)
if (sockarr[i] != BADSOCKET_VALUE)
FD_SET(sockarr[i], &readfds);
rv = select(num_rexecs, &readfds, 0, 0, &timeout);
if ( rv == 0)
continue;
if (rv < 0 && WSAGetLastError() == WSANOTINITIALISED)
return;
if (rv < 0)
errexit("Error in echo_client(): select() returns %d: %s\n", rv, neterrstr());
/* loop over the sockets that are ready with data */
for (i = 0; i < num_rexecs; i++) {
if (sockarr[i] != BADSOCKET_VALUE && FD_ISSET(sockarr[i], &readfds)) {
len = NETREAD(sockarr[i], buf, sizeof(buf));
if (len <= 0) {
/* mark connection closed */
sockarr[i] = BADSOCKET_VALUE;
if (len < 0 && WSAGetLastError() == WSANOTINITIALISED)
return;
if (len < 0)
fprintf(stderr, "Error in echo_client() after NETREAD(): %s\n", neterrstr());
continue;
}
/* copy to stdout or stderr */
fwrite(buf, sizeof(char), len, outfile);
}
}
}
D_PRINTF( "Exiting echo_client\n" );
}
#else
static int
echo_client(char *hostname, const int fd)
{
/*
* WRITE TEXT FROM FILE DESCRIPTOR INTO STDOUT
*/
char buf[BUFSIZ];
int cc;
D_PRINTF( "echo_client running\n" );
while (getppid() != 1)
{
cc = NETREAD(fd, buf, sizeof(buf));
if (cc > 0)
{
write(STDOUT_FILENO, buf, cc);
}
}
D_PRINTF( "Exiting echo_client\n" );
NETCLOSE(fd);
}
#endif /* WIN32 */
/* Picks the appropriate webmaster IP address based on the address of the client.
* This is significant only for hosts with multiple interfaces
*
* return value is a string with the IP address or hostname (or NULL)
*/
char *pick_webmaster_IP_address(char *client_hostname, struct hostent *master_phe,
unsigned netmask) {
static char buf[20];
unsigned char addr[4];
int client_addr;
int i;
if (client_hostname[0] >= '0' && client_hostname[0] <= '9') {
/* we have an IP address */
client_addr = inet_addr(client_hostname);
if (client_addr == INADDR_NONE)
return 0;
} else {
/* we have a hostname, use the webserver hostname */
return master_phe->h_name;
}
for (i = 0; master_phe->h_addr_list[i] != 0; i++) {
if ((*(int *)(master_phe->h_addr_list[i]) & netmask) ==
(client_addr & netmask))
goto gotit;
}
i = 0; /* give up */
gotit:
memcpy((char *)addr, master_phe->h_addr_list[i], sizeof(addr)); /* Internet specific */
sprintf(buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
return buf;
}
/*
Command line parsing
*/
void ParseCmdLine(int argc, char **argv )
{
char getoptch;
int currarg;
extern char *optarg;
extern int optind;
/*
* PARSE THE COMMAND LINE OPTIONS
*/
while((getoptch = getopt(argc,argv,"P:f:t:l:p:u:R:w:n:M:adrsvWX")) != (const char)EOF)
{
switch(getoptch)
{
case 'M':
strcpy(network_mask_str, optarg);
break;
case 'P':
haveproxyserver = 1;
strcpy(proxyserver, optarg);
break;
case 'R':
record_all_transactions = 1;
break;
case 'X':
norexec = 1;
break;
case 'W':
servaddrin_config = 1;
break;
case 'a':
dumpall = 1;
break;
case 'd':
debug = 1;
break;
case 'f':
strcpy(configfile, optarg);
break;
case 'l':
numloops = atoi(optarg);
break;
case 'p':
portnum = atoi(optarg);
break;
case 'r':
redirect = 1;
break;
case 's':
savefile = 1;
break;
case 't':
testtime = atoi(optarg);
break;
case 'u':
uil_filelist_f = 1;
strcpy(uil_filelist, optarg);
break;
case 'v':
verbose = 1;
break;
case 'w':
havewebserver = 1;
strcpy(webserver, optarg);
break;
default:
usage(argv[0]);
} /* end switch */
} /* end while */
if (numloops && testtime)
errexit("Can't have both -l and -t\n");
if(!havewebserver && !servaddrin_config)
{
/*
* THE SERVERS NAME MUST BE SPECIFIED
*/
fprintf(stderr,"No WWW Server specified\n");
usage(argv[0]);
}
if (havewebserver && servaddrin_config)
{
/*
* CAN'T HAVE BOTH -w and -W
*/
fprintf(stderr, "Can't have both -w and -W options\n");
usage(argv[0]);
}
network_mask = inet_addr(network_mask_str);
if (network_mask == INADDR_NONE) {
fprintf(stderr, "Invalid network mask (-M %s)\n", network_mask_str);
usage(argv[0]);
}
if(strlen(configfile) == 0)
{
/*
* THE MASTER MUST HAVE A CONFIGURATION FILE TO READ.
*/
fprintf(stderr,"No Configuration file specified\n");
usage(argv[0]);
}
/* IF WE DO NOT HAVE A FILE LIST THEN THERE ARE UIL'S AT THE END OF THE
* COMMAND LINE SO GRAB THEM.
*/
if (uil_filelist_f == 0)
{
currarg = optind;
number_of_pages = 0;
while(currarg != argc)
{
/*
* GET THE UILS TO RETRIEVE.
*/
sscanf(argv[currarg],"%s",filelist[number_of_pages]);
number_of_pages++;
currarg++;
}
}
else
{
/* have filelist; take a stab at the number of valid URLs */
D_PRINTF( "About to parse filelist %s\n", uil_filelist );
number_of_pages = count_file_list(uil_filelist);
}
if (number_of_pages == 0)
{
/*
* AT LEAST ONE FILE MUST BE SPECIFIED
*/
fprintf(stderr,"No URL resources specified\n");
usage(argv[0]);
}
}
/*
This function sets up the socket we will use to synchronize with the
clients.
Returns the socket number if successful, doesn't return if it fails
*/
SOCKET SetupSyncSocket( serveraddr )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -