/* -----------------------------------------------------------------------------
* web.c
*
* This file implements the web-server.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Sotiria Lampoudi (slampoud@cs.uchicago.edu)
* Mike Sliczniak (mzsliczn@midway.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
static char cvsroot[] = "$Header: /home/pastacvs/cvs-rep/vermicelli/tot/src/SWILL-0.1/Source/SWILL/web.c,v 1.4 2005/01/28 12:24:34 dillema Exp $";
#include "swillint.h"
/*
#define __USE_MPI
#undef __USE_MPI
*/
#ifdef __USE_MPI
#include <mpi.h>
#endif
/* Server info */
int SwillInit = 0;
static int SwillSocket = -1;
static int SwillPort = 0;
static String *SwillTitle = 0;
static String *SwillDocroot = 0;
int SwillTimeout = SWILL_TIMEOUT;
static FILE *SwillFile = 0;
#ifdef __USE_MPI
static int _swill_mpi_rank, _swill_mpi_numprocs;
#endif
/* Global variables containing information about the current request */
static Hash *http_out_headers = 0;
static String *http_uri = 0;
static String *http_response = 0;
static Hash *current_request = 0;
/* -----------------------------------------------------------------------------
* Utility functions for setting/getting headers and form vars
* ----------------------------------------------------------------------------- */
void swill_setheader(const char *header, const char *value) {
Setattr(http_out_headers,header,value);
}
void swill_setresponse(const char *value) {
if (http_response) Delete(http_response);
http_response = NewString(value);
}
char *swill_getheader(const char *header) {
Hash *headers;
char temp[1024];
char *c;
strcpy(temp,header);
c = temp;
while (*c) {
*c = tolower(*c);
c++;
}
headers = Getattr(current_request,"headers");
if (headers) {
return GetChar(headers,temp);
} else {
return 0;
}
}
char *swill_getvar(const char *name) {
Hash *query = Getattr(current_request,"query");
if (query) {
return GetChar(query,name);
}
return 0;
}
int swill_getint(const char *name) {
Hash *query = Getattr(current_request,"query");
if (query) {
return GetInt(query,name);
}
return 0;
}
double swill_getdouble(const char *name) {
Hash *query = Getattr(current_request,"query");
if (query) {
return GetDouble(query,name);
}
return 0;
}
/* -----------------------------------------------------------------------------
* swill_init()
* ----------------------------------------------------------------------------- */
int
swill_init(int port) {
struct sockaddr_storage servaddr;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
int flag = 1;
char hname[256];
assert(!SwillInit);
if (!SwillFile) {
SwillFile = tmpfile();
assert(SwillFile);
}
SwillSocket = -1;
SwillPort = 0;
#ifdef __USE_MPI
/*MPI_Init(&argc, &argv); */
/* we don't call MPI_Init(), we expect that the host code has done it for us.
* --TL
*/
MPI_Comm_size(MPI_COMM_WORLD,&_swill_mpi_numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&_swill_mpi_rank);
#endif
signal(SIGPIPE, SIG_IGN);
DohEncoding("url",swill_url_encoder);
DohEncoding("pre",swill_pre_encoder);
#ifdef __USE_MPI
if(_swill_mpi_rank == 0) {
#endif
/* Open up the server socket */
#ifdef USE_INET6
SwillSocket = socket(AF_INET6, SOCK_STREAM, 0);
#else
SwillSocket = socket(AF_INET, SOCK_STREAM, 0);
#endif
if (SwillSocket < 0) {
printf("swill_init: Can't create socket!\n");
/* Maybe some kind of MPI reduce here */
SwillInit = SwillPort = 0;
goto init_ret;
/*return 0; */
}
/* Re-use the address if possible */
if (setsockopt(SwillSocket,SOL_SOCKET, SO_REUSEADDR,(char *)&flag,sizeof(int)) < 0) {
perror("setsockopt");
}
/* Set the server address */
bzero(&servaddr, sizeof(servaddr));
#ifdef USE_INET6
sin6 = (struct sockaddr_in6 *) &servaddr;
sin6->sin6_len = sizeof (struct sockaddr_in6);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
sin6->sin6_addr = in6addr_any;
#else
sin = (struct sockaddr_in *) &servaddr;
sin->sin_len = sizeof (struct sockaddr_in);
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = htonl(INADDR_ANY);
#endif
/* Bind the socket to the port */
if (bind(SwillSocket,
(struct sockaddr *) &servaddr,
servaddr.ss_len) < 0) {
printf("swill_init: Can't bind to port %d!\n", port);
perror("bind");
/* Maybe some kind of MPI reduce here */
SwillInit = SwillPort = 0;
goto init_ret;
/* return 0; */
}
/* Allow, at most, 5 outstanding network connections */
listen(SwillSocket, 5);
/* Get port assigned to the socket */
{
struct sockaddr_in socketname;
int inlen = sizeof(socketname);
if (getsockname(SwillSocket, (struct sockaddr *) &socketname, &inlen) >= 0) {
SwillPort = ntohs(socketname.sin_port);
}
}
#ifdef __USE_MPI
} else {
/* Need to place some initialization code here */
}
#endif
SwillTitle = NewString("SWILL");
SwillDocroot = 0;
SwillInit = 1;
swill_security_init();
swill_handle("info",SH(SwillListHandlers),0);
init_ret:
#ifdef __USE_MPI
MPI_Bcast(&SwillInit, 1,MPI_INT, 0, MPI_COMM_WORLD);
#endif
return SwillPort;
}
/* -----------------------------------------------------------------------------
* swill_close()
*
* Close the server
* ----------------------------------------------------------------------------- */
void
swill_close() {
if (!SwillInit) return;
if (SwillSocket > 0) {
close(SwillSocket);
}
fclose(SwillFile);
SwillFile = 0;
SwillSocket = 0;
Delete(SwillTitle);
Delete(SwillDocroot);
SwillTitle = 0;
SwillDocroot = 0;
SwillInit = 0;
swill_handler_reset();
swill_security_reset();
}
/* -----------------------------------------------------------------------------
* swill_title()
*
* Set or return the server title.
* ----------------------------------------------------------------------------- */
char *
swill_title(const char *title) {
if (!SwillInit) return 0;
if (title)
SwillTitle = NewString(title);
return Char(SwillTitle);
}
/* -----------------------------------------------------------------------------
* swill_directory()
*
* Set the document root for serving arbitrary files.
* ----------------------------------------------------------------------------- */
char *
swill_directory(const char *pathname) {
if (!SwillInit) return 0;
if (pathname) {
if (SwillDocroot) Delete(SwillDocroot);
if (strlen(pathname)) {
SwillDocroot = NewString(pathname);
} else {
SwillDocroot = 0;
}
}
return SwillDocroot ? Char(SwillDocroot) : 0;
}
/* -----------------------------------------------------------------------------
* swill_timeout()
*
* Send the timeout value.
* ----------------------------------------------------------------------------- */
void
swill_timeout(int timeout) {
SwillTimeout = timeout;
}
/* -----------------------------------------------------------------------------
* check_filename()
*
* Checks a filename to see if it is legal or not. Does not allow any
* path component to start with a '.'
* ----------------------------------------------------------------------------- */
static int
check_filename(String *fn) {
int ch;
int state = 0;
Seek(fn,0,SEEK_SET);
while (1) {
ch = Getc(fn);
if (ch == EOF) return 1;
if ((ch == '.') && (state)) return 0;
if (ch == '.') state++;
else state = 0;
}
}
/* -----------------------------------------------------------------------------
* swill_nbwrite()
*
* Non-blocking write to a socket
* ----------------------------------------------------------------------------- */
static int
swill_nbwrite(int fd, char *buffer, int len) {
fd_set wset;
struct timeval tv;
int nsent = 0;
int retval;
int n;
FD_ZERO(&wset);
while (nsent < len) {
FD_SET(fd,&wset);
tv.tv_sec = SwillTimeout;
tv.tv_usec = 0;
retval = select(fd+1,0,&wset,0,&tv);
if (retval <= 0) {
/* Timeout. We're history. */
swill_logprintf(" Warning: write timeout!\n");
return nsent;
}
n = write(fd,buffer+nsent,len-nsent);
if (n < 0) {
if (errno != EWOULDBLOCK) {
return nsent;
}
continue;
}
nsent += n;
}
return nsent;
}
static int
swill_nbcopydata(FILE *in, int fd) {
char buffer[16384];
int nread;
int total = 0;
while (1) {
nread = Read(in,buffer,16384);
if (nread < 0) {
if (errno != EINTR) {
return total;
}
continue;
}
if (nread == 0) break;
if (swill_nbwrite(fd,buffer,nread) != nread) {
return total;
}
total += nread;
}
}
/* -----------------------------------------------------------------------------
* swill_dump_page()
*
* Dumps the raw page to the socket.
* ----------------------------------------------------------------------------- */
static int
swill_dump_page(File *webpage, int fd) {
String *tmp;
String *key;
int nbytes;
int val;
Seek(webpage, 0, SEEK_END);
nbytes = Tell(webpage);
Seek(webpage,0, SEEK_SET);
/* Put the socket in non-blocking I/O mode */
val = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, val | O_NONBLOCK);
tmp = NewStringf("HTTP/1.0 %s\n", http_response);
if (swill_nbwrite(fd, Char(tmp), Len(tmp)) != Len(tmp)) {
goto send_error;
}
key = Firstkey(http_out_headers);
while (key) {
Clear(tmp);
Printf(tmp,"%s: %s\n", key, Getattr(http_out_headers,key));
if (swill_nbwrite(fd, Char(tmp), Len(tmp)) != Len(tmp)) {
goto send_error;
}
key = Nextkey(http_out_headers);
}
Clear(tmp);
if (nbytes) {
Printf(tmp,"Content-Length: %d\n", nbytes);
}
Printf(tmp,"Server: SWILL/%d.%d\n", SWILL_MAJOR_VERSION, SWILL_MINOR_VERSION);
Printf(tmp,"Connection: close\n");
Printf(tmp,"\n");
if (swill_nbwrite(fd, Char(tmp), Len(tmp)) != Len(tmp)) {
goto send_error;
}
swill_nbcopydata(webpage,fd);
/* Restore flags */
fcntl(fd, F_SETFL, val);
if (tmp) Delete(tmp);
return nbytes;
send_error:
if (tmp) Delete(tmp);
fcntl(fd, F_SETFL,val);
return 0;
}
/* -----------------------------------------------------------------------------
* swill_serve_file()
*
* Serves a local file. Returns -1 if unsuccessful.
* uri is the input URL, out is the output stream, and clientfd is the
* integer fd of the socket.
* ----------------------------------------------------------------------------- */
static int
swill_serve_file(String *uri, File *out, int clientfd) {
String *filename, *of;
char *cfilename;
FILE *f;
int fileok = 0;
struct stat info;
filename = NewString("");
Printf(filename,"%s/%s",SwillDocroot,uri);
if (SwillDocroot) {
if (Strncmp(filename,SwillDocroot,Len(SwillDocroot)) == 0) {
String *tfilename = NewString(Char(filename)+Len(SwillDocroot));
fileok = check_filename(tfilename);
Delete(tfilename);
}
} else {
fileok = check_filename(filename);
}
if (fileok) {
/* Get some statistics about the file */
filetry:
cfilename = (char *) Data(filename);
if (lstat(cfilename,&info) < 0) {
SwillFileNotFound(out,0);
Delete(filename);
return -1;
}
if (S_ISDIR(info.st_mode)) {
/* Hmmm. Appears to be a directory. If the directory does not have a trailing "/"
We need to redirect the browser */
if (cfilename[strlen(cfilename)-1] != '/') {
swill_setresponse("301 Moved Permanently");
of = NewString("");
Printf(of,"http://%s/%s/", swill_getheader("host"), uri);
swill_setheader("location",(char *) of);
swill_setheader("Content-Type","text/html");
Printf(out,"<h1>Moved permanently</h1>\n");
Delete(filename);
return -1;
}
Printf(filename,"%s",SWILL_DEFAULT);
goto filetry;
}
f = fopen((char *)Data(filename),"r");
if (!f) {
SwillFileNotFound(out,0);
Delete(filename);
return -1;
}
swill_setheader("Content-Type", swill_guess_mimetype(Char(filename)));
SetInt(http_out_headers,"Content-Length",info.st_size);
/* Dump web-page so far */
swill_dump_page(out,clientfd);
{
int val = fcntl(clientfd, F_GETFL,0);
fcntl(clientfd, F_SETFL, val | O_NONBLOCK);
swill_nbcopydata(f,clientfd);
fcntl(clientfd, F_SETFL, val);
}
fclose(f);
Delete(filename);
return 0;
} else {
SwillFileNotFound(out,0);
Delete(filename);
return -1;
}
}
/* -----------------------------------------------------------------------------
* swill_serve_one()
*
* This function handles a raw http-request on a single processor. This is the
* entry point to the server on a multiprocessor application. Tasks performed
* at this stage include:
*
* - Serving of simple files or directories
* - User authentication
* - Error messages for invalid web pages.
* - Redirection.
*
* If the request was an error or applicable to a single processor, NULL is
* returned.
*
* Otherwise, an output object is returned and some global variables are set.
* The caller can use this to figure out how to call the handling function.
*
* P.S. This function is a big mess...
* ----------------------------------------------------------------------------- */
static FILE *
swill_serve_one(struct sockaddr *clientaddr, int clientfd)
{
Hash *handler;
SwillHandler whandle;
FILE *out = 0;
String *excess;
String *requeststring;
Hash *request;
String *method;
String *peerip;
char addr[INET6_ADDRSTRLEN];
/* Compute the peer IP address */
if (clientaddr->sa_family == AF_INET) {
struct sockaddr_in *sin_p = (struct sockaddr_in *) clientaddr;
peerip = NewString(inet_ntop(sin_p->sin_family, (void *) &sin_p->sin_addr,
addr,sizeof(addr)));
}
#ifdef USE_INET6
if (clientaddr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6_p = (struct sockaddr_in6 *) clientaddr;
peerip = NewString(inet_ntop(sin6_p->sin6_family, (void *) &sin6_p->sin6_addr,
addr,sizeof(addr)));
}
#endif
/* Implement IP filtering here */
if (!swill_check_ip(peerip)) {
Delete(peerip);
return 0;
}
swill_logprintf("%-64s ", peerip);
/* Read the raw HTTP request */
if (!swill_read_rawrequest(clientfd, &requeststring, &excess)) {
/* Bad request. Too big, malformed, etc. */
Delete(peerip);
swill_logprintf("Bad request\n");
return 0;
}
/* Try to parse into a request */
request = swill_parse_request_headers(requeststring);
if (!request) {
Delete(peerip);
Delete(excess);
Delete(requeststring);
swill_logprintf("Malformed request\n");
return 0;
}
/* If we made it this far, the initial HTTP request looks valid */
Delete(requeststring);
method = Getattr(request,"method");
/* If a logfile is available, print some information about the request */
{
time_t t;
struct tm *tms;
char ts[256];
t = time(NULL);
tms = localtime(&t);
strftime(ts,64,"[%d %b %y %H:%M:%S]", tms);
swill_logprintf("%s %s %s\n", ts, method, Getattr(request,"uri"));
}
Setattr(request,"peername", peerip);
Delete(peerip);
/* Handle query string data here */
if (Strcmp(method,"POST") == 0) {
int length;
String *posts;
Hash *headers;
requeststring = Getattr(request,"request");
headers = Getattr(request,"headers");
Seek(requeststring, 0, SEEK_END);
Append(requeststring,excess); /* Add excess data */
length = GetInt(headers,"content-length");
if (length > 0) {
posts = swill_read_post(clientfd,length,excess);
if (posts) {
if (Len(posts) > Len(excess)) {
Append(requeststring, Char(posts) + Len(excess));
}
Delete(posts);
} else {
Delete(excess);
Delete(request);
return 0;
}
}
}
Delete(excess);
if (!swill_parse_request_data(request)) {
Delete(request);
return 0;
}
/* Request has been parsed and all form variables are set */
/* Set global variables */
http_uri = Getattr(request,"uri");
current_request = request;
/* Create output headers */
http_out_headers = NewHash();
/* Setattr(http_out_headers,"Cache-Control","no-cache"); */
Setattr(http_out_headers,"Expires","Sat, 1 Jan 2000 00:00:00 GMT");
Setattr(http_out_headers,"Pragma","nocache");
swill_setresponse("200 OK");
/* Create an output object */
out = SwillFile;
ftruncate(fileno(out),0);
fseek(out,0, SEEK_SET);
/* Check for user authorization here */
if (!swill_checkuser()) {
SwillAuthenticate(out,0);
Setattr(http_out_headers,"WWW-Authenticate","Basic");
goto handled_request;
}
/* Check if method is valid */
if (!(Strcmp(method,"GET") == 0) && !(Strcmp(method,"POST") == 0)) {
SwillUnsupported(out,0);
goto handled_request;
}
/* See if there is a handler function registered for this URI */
handler = swill_handler_lookup(http_uri);
if (handler) {
/* A user handler was registered. If it is the special "info" handler or a file, we just run it here.
Otherwise, we will return to the caller */
/* Set default mime-type of return page */
swill_setheader("Content-Type", GetChar(handler,"mimetype"));
whandle = (SwillHandler) Data(Getattr(handler,"handler"));
if (whandle) {
/* Only serve the handler if its the special info page */
if (Cmp(http_uri,"info") == 0) {
(*whandle)(out,Data(Getattr(handler,"clientdata")));
goto handled_request;
}
/* We actually got a valid request for something that we will
return to the user. In this case, we simply return the output object */
return out;
} else {
/* No callback function. A simple file */
FILE *f;
char *filename;
filename = Data(Getattr(handler,"filename"));
f = fopen(filename,"r");
if (!f) {
SwillFileNotFound(out,0);
goto handled_request;
} else {
/* Find out the length */
struct stat info;
fstat(fileno(f),&info);
SetInt(http_out_headers,"Content-Length",info.st_size);
swill_dump_page(out,clientfd);
{
int val = fcntl(clientfd, F_GETFL,0);
fcntl(clientfd, F_SETFL, val | O_NONBLOCK);
swill_nbcopydata(f,clientfd);
fcntl(clientfd, F_SETFL, val);
}
fclose(f);
out = 0;
goto handled_request;
}
}
}
/* No handler registered. Maybe we can pull something out of a directory of files */
/* See if a document root has been set */
if (!SwillDocroot) {
SwillFileNotFound(out,0);
goto handled_request;
}
if (swill_serve_file(http_uri,out,clientfd) >= 0) {
out = 0;
}
/* This code is called when the request has been handled by this function */
handled_request:
if (out) {
/* Dump the web-page out. We handled it on a single processor */
fflush(out);
swill_dump_page(out,clientfd);
}
/* Cleanup */
Delete(current_request);
Delete(http_out_headers);
return 0;
}
/* -----------------------------------------------------------------------------
* swill_serve()
* ----------------------------------------------------------------------------- */
#ifndef __USE_MPI
int
swill_serve() {
struct sockaddr_storage clientaddr;
int clientfd, len = sizeof(clientaddr);
int oldstdout;
FILE *out = 0;
if (!SwillInit) {
return 0;
}
/* Wait for a connection */
/* This is where that DoS prevention code should go !! */
clientfd = accept(SwillSocket, (struct sockaddr *) &clientaddr, &len);
if (clientfd < 0) return 0;
/* Go process request */
out = swill_serve_one((struct sockaddr *)&clientaddr,clientfd);
if (!out) {
/* swill_serve_one() took care of everything. Goodbye */
close(clientfd);
return 1;
} else {
SwillHandler whandle;
Hash *handler;
File *of;
handler = swill_handler_lookup(http_uri);
assert(handler); /* we're hosed if this is broken */
whandle = (SwillHandler) Data(Getattr(handler,"handler"));
assert(whandle);
/* Note : the stdout flag is set to capture stdout */
if (Getattr(handler,"stdout")) {
/* This is a very sneaky horrible trick. We swap in a new file descriptor for stdout. */
fflush(stdout);
oldstdout = dup(1); /* Duplicate the file descriptor for stdout */
/* Now dup2 the output stream onto stdout */
dup2(fileno(out),1);
}
/* Call the handler */
(*whandle)(out,Data(Getattr(handler,"clientdata")));
if (Getattr(handler,"stdout")) {
/* Restore the old stdout file descriptor */
fflush(stdout);
dup2(oldstdout,1);
close(oldstdout);
}
fflush(out);
/* Dump the web-page here */
swill_dump_page(out,clientfd);
/* Delete the other fields */
Delete(current_request);
Delete(http_out_headers);
}
close(clientfd);
return 1;
}
#elif defined __USE_MPI
/* MPI version */
int
swill_serve() {
struct sockaddr_in clientaddr;
int clientfd, len = sizeof(clientaddr);
int oldstdout;
FILE *out = 0;
String *request = 0;
int request_len = 0;
char *tmp_request = 0;
if (!SwillInit) {
return 0;
}
if ( _swill_mpi_rank == 0){
/* Wait for a connection */
/* This is where that DoS prevention code should go !! */
clientfd = accept(SwillSocket, (struct sockaddr *) &clientaddr, &len);
if (clientfd < 0){
request = 0;
goto bcast_serve;
}
out = swill_serve_one((struct sockaddr *)&clientaddr,clientfd);
if (!out) {
close(clientfd);
request = 0;
goto bcast_serve;
} else {
/* Need to regenerate a request to send to other nodes */
request = Getattr(current_request,"request");
request_len = Len(request);
tmp_request = Char(request);
}
} /* whether NULL or not, we have a request string. --TL */
bcast_serve:
MPI_Bcast(&request_len, 1, MPI_INT, 0, MPI_COMM_WORLD);
if( request_len){
if(_swill_mpi_rank){
tmp_request = (char *)malloc(sizeof(char) * request_len+1);
}
MPI_Bcast(tmp_request, request_len+1, MPI_CHAR, 0, MPI_COMM_WORLD);
if(_swill_mpi_rank){
request = NewString(tmp_request);
}
free(tmp_request);
/* now build up the information you need to execute this;
* this obviates the need for setting the parameters accessible to node0,
* since it is easier for everyone to recompute them. --TL
*/
/* This function builds the needed data structures from
the received request string */
if(_swill_mpi_rank){
current_request = swill_parse_request(request);
}
http_out_headers = NewHash();
http_uri = Getattr(current_request,"uri");
/* We need to call the handler here */
{
FILE *out;
String *tmp_merged_out;
SwillHandler whandle;
Hash *handler;
int out_size = 0;
int tmp_out_size = 0;
char *tmp_out = 0;
String *tmp_out_string = 0;
int i = 0;
MPI_Status status;
String *outs;
handler = swill_handler_lookup(http_uri);
assert(handler); /* we're hosed if this is broken */
whandle = (SwillHandler) Data(Getattr(handler,"handler"));
assert(whandle);
/* Create an output object */
out = SwillFile;
ftruncate(fileno(out),0);
fseek(out,0, SEEK_SET);
swill_setheader("Content-Type", GetChar(handler,"mimetype"));
swill_setresponse("200 OK");
/* Note : the stdout flag is set to capture stdout */
if (Getattr(handler,"stdout")) {
/* This is a very sneaky horrible trick. We swap in a new file descriptor for stdout. */
fflush(stdout);
oldstdout = dup(1); /* Duplicate the file descriptor for stdout */
/* Now dup2 the output stream onto stdout */
dup2(fileno(out),1);
}
(*whandle)(out,Data(Getattr(handler,"clientdata")));
if (Getattr(handler,"stdout")) {
/* Restore the old stdout file descriptor */
fflush(stdout);
dup2(oldstdout,1);
close(oldstdout);
}
fflush(out);
out_size = Tell(out);
/* do fd initialization */
if( _swill_mpi_rank == 0){
tmp_out_string = NewString("");
/* first dump master */
Seek(out, 0, SEEK_SET);
Copyto(out, tmp_out_string);
}
for(i = 1; i < _swill_mpi_numprocs; i ++){
if( _swill_mpi_rank == i ){
MPI_Send(&out_size, 1, MPI_INT, 0, i , MPI_COMM_WORLD);
outs = NewString("");
Seek(out, 0, SEEK_SET);
Copyto(out, outs);
MPI_Send(Char(outs), out_size, MPI_CHAR, 0, i + 1024, MPI_COMM_WORLD);
Delete(outs);
} else if(_swill_mpi_rank == 0){
MPI_Recv(&tmp_out_size, 1, MPI_INT, i, i, MPI_COMM_WORLD, &status);
tmp_out = (char*) malloc(sizeof(char)*tmp_out_size);
MPI_Recv(tmp_out, tmp_out_size, MPI_CHAR, i, i + 1024,
MPI_COMM_WORLD, &status);
Write(tmp_out_string, tmp_out, tmp_out_size);
}
}
if( _swill_mpi_rank == 0){
swill_dump_page(tmp_out_string, clientfd);
Delete(tmp_out_string);
close(clientfd);
}
}
if(!_swill_mpi_rank == 0)
Delete(request);
Delete(current_request);
http_out_headers = 0;
return 0;
}
else {
/* probably just served a file
* could also be one of a number of problems,
* what the heck! return 0
*/
return 0;
}
/* everyone return 0? --TL */
return 0;
}
#endif
/* -----------------------------------------------------------------------------
* swill_poll()
*
* See if there are any pending connections and handle them if so. Otherwise
* return.
* ----------------------------------------------------------------------------- */
/* non MPI version */
#ifndef __USE_MPI
int swill_poll() {
fd_set rset;
struct timeval tv;
int ret;
if (!SwillInit) return 0;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(SwillSocket,&rset);
ret = select(SwillSocket+1,&rset,0,0,&tv);
if (ret <= 0) {
return 0;
}
if (FD_ISSET(SwillSocket,&rset)) {
return swill_serve();
} else {
return 0;
}
}
#endif
#ifdef __USE_MPI
/* MPI version of swill_poll() */
int swill_poll() {
int serve_flag;
fd_set rset;
struct timeval tv;
int ret;
/* we use swill_poll() to reach some agreement as to whether we need to do
* something. swill_serve() will actually do the work. --TL
*/
if (!SwillInit) return 0;
if(_swill_mpi_rank == 0 ){
/* master */
if (SwillSocket < 0) {
serve_flag = 0;
goto bcast_poll;
}
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(SwillSocket,&rset);
ret = select(SwillSocket+1,&rset,0,0,&tv);
if (ret <= 0) {
serve_flag = 0;
goto bcast_poll;
}
if (FD_ISSET(SwillSocket,&rset)) {
serve_flag = 1;
} else {
serve_flag = 0;
}
}
bcast_poll:
/* rank independent: broadcast decision and act on it. --TL */
MPI_Bcast(&serve_flag, 1, MPI_INT, 0, MPI_COMM_WORLD);
if( serve_flag ){
return swill_serve();
}
return 0;
}
#endif
void swill_netscape(const char *url) {
char buffer[2048];
sprintf(buffer,"netscape -remote 'openURL(http://localhost:%d/%s)'", SwillPort, url);
system(buffer);
}
syntax highlighted by Code2HTML, v. 0.9.1