X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fwebserver.c;h=1c308dc0c3db2ea5c030ce4c549be44e6caade29;hb=b9af9a3fafd99a3fb81cb09f01390531ffe6f29d;hp=7cc4f3f9674aea93b1913efb630dcb22592d89de;hpb=d7122d9b8ae8863ca4412deb95b619585f28eda6;p=citadel.git diff --git a/webcit/webserver.c b/webcit/webserver.c index 7cc4f3f96..1c308dc0c 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -35,7 +35,6 @@ #include #include #include - #include "webcit.h" #include "webserver.h" @@ -45,6 +44,7 @@ int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp); int verbosity = 9; /* Logging level */ int msock; /* master listening socket */ +int is_https = 0; /* Nonzero if I am an HTTPS service */ extern void *context_loop(int); extern void *housekeeping_loop(void); extern pthread_mutex_t SessionListMutex; @@ -54,10 +54,8 @@ extern pthread_key_t MyConKey; char *server_cookie = NULL; -char *defaulthost = DEFAULT_HOST; -char *defaultport = DEFAULT_PORT; - -pthread_mutex_t AcceptQueue; +char *ctdlhost = DEFAULT_HOST; +char *ctdlport = DEFAULT_PORT; /* * This is a generic function to set up a master socket for listening on @@ -114,6 +112,13 @@ int client_read_to(int sock, char *buf, int bytes, int timeout) struct timeval tv; int retval; + +#ifdef HAVE_OPENSSL + if (is_https) { + return(client_read_ssl(buf, bytes, timeout)); + } +#endif + len = 0; while (len < bytes) { FD_ZERO(&rfds); @@ -126,7 +131,9 @@ int client_read_to(int sock, char *buf, int bytes, int timeout) if (FD_ISSET(sock, &rfds) == 0) { return (0); } + rlen = read(sock, &buf[len], bytes - len); + if (rlen < 1) { lprintf(2, "client_read() failed: %s\n", strerror(errno)); @@ -137,6 +144,18 @@ int client_read_to(int sock, char *buf, int bytes, int timeout) return (1); } + +ssize_t client_write(const void *buf, size_t count) { +#ifdef HAVE_OPENSSL + if (is_https) { + client_write_ssl((char *)buf, count); + return(count); + } +#endif + return(write(WC->http_sock, buf, count)); +} + + /* * Read data from the client socket with default timeout. * (This is implemented in terms of client_read_to() and could be @@ -230,7 +249,11 @@ int main(int argc, char **argv) char tracefile[PATH_MAX]; /* Parse command line */ +#ifdef HAVE_OPENSSL + while ((a = getopt(argc, argv, "hp:t:cs")) != EOF) +#else while ((a = getopt(argc, argv, "hp:t:c")) != EOF) +#endif switch (a) { case 'p': port = atoi(optarg); @@ -257,21 +280,27 @@ int main(int argc, char **argv) } } break; + case 's': + is_https = 1; + break; default: fprintf(stderr, "usage: webserver [-p localport] " "[-t tracefile] [-c] " +#ifdef HAVE_OPENSSL + "[-s] " +#endif "[remotehost [remoteport]]\n"); return 1; } if (optind < argc) { - defaulthost = argv[optind]; + ctdlhost = argv[optind]; if (++optind < argc) - defaultport = argv[optind]; + ctdlport = argv[optind]; } /* Tell 'em who's in da house */ lprintf(1, SERVER "\n" -"Copyright (C) 1996-2002 by the Citadel/UX development team.\n" +"Copyright (C) 1996-2004 by the Citadel/UX development team.\n" "This software is distributed under the terms of the GNU General Public\n" "License. If you paid for this software, someone is ripping you off.\n\n"); @@ -287,6 +316,18 @@ int main(int argc, char **argv) lprintf(1, "Can't create TSD key: %s\n", strerror(errno)); } + /* + * Set up a place to put thread-specific SSL data. + * We don't stick this in the wcsession struct because SSL starts + * up before the session is bound, and it gets torn down between + * transactions. + */ +#ifdef HAVE_OPENSSL + if (pthread_key_create(&ThreadSSL, NULL) != 0) { + lprintf(1, "Can't create TSD key: %s\n", strerror(errno)); + } +#endif + /* * Bind the server to our favorite port. * There is no need to check for errors, because ig_tcp_server() @@ -298,7 +339,6 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); pthread_mutex_init(&SessionListMutex, NULL); - pthread_mutex_init(&AcceptQueue, NULL); /* * Start up the housekeeping thread @@ -309,13 +349,22 @@ int main(int argc, char **argv) (void *(*)(void *)) housekeeping_loop, NULL); + /* + * If this is an HTTPS server, fire up SSL + */ +#ifdef HAVE_OPENSSL + if (is_https) { + init_ssl(); + } +#endif + /* Start a few initial worker threads */ - for (i=0; i<(INITIAL_WORKER_THREADS); ++i) { + for (i=0; i<(MIN_WORKER_THREADS); ++i) { spawn_another_worker_thread(); } - /* now the original thread can go away. */ - pthread_exit(NULL); + /* now the original thread becomes another worker */ + worker_entry(); return 0; } @@ -325,25 +374,14 @@ int main(int argc, char **argv) */ void worker_entry(void) { int ssock; - struct sockaddr_in fsin; - int alen; int i = 0; int time_to_die = 0; - time_t start_time, stop_time; + int fail_this_transaction = 0; do { /* Only one thread can accept at a time */ - start_time = time(NULL); - pthread_mutex_lock(&AcceptQueue); - ssock = accept(msock, (struct sockaddr *) &fsin, &alen); - pthread_mutex_unlock(&AcceptQueue); - stop_time = time(NULL); - - /* Augment the thread pool if we're not blocking at all */ - if ( (stop_time - start_time) == 0L) { - spawn_another_worker_thread(); - } - + fail_this_transaction = 0; + ssock = accept(msock, NULL, 0); if (ssock < 0) { lprintf(2, "accept() failed: %s\n", strerror(errno)); } else { @@ -352,8 +390,19 @@ void worker_entry(void) { setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + /* If we are an HTTPS server, go crypto now. */ +#ifdef HAVE_OPENSSL + if (is_https) { + if (starttls(ssock) != 0) { + fail_this_transaction = 1; + } + } +#endif + /* Perform an HTTP transaction... */ - context_loop(ssock); + if (fail_this_transaction == 0) { + context_loop(ssock); + } /* ...and close the socket. */ lingering_close(ssock); @@ -379,7 +428,7 @@ int lprintf(int loglevel, const char *format, ...) struct tm *tim; gettimeofday(&tv, NULL); - tim = localtime(&(tv.tv_sec)); + tim = localtime((time_t *)&(tv.tv_sec)); if (WC && WC->wc_session) { fprintf(stderr, @@ -387,14 +436,16 @@ int lprintf(int loglevel, const char *format, ...) tim->tm_year + 1900, tim->tm_mon + 1, tim->tm_mday, tim->tm_hour, tim->tm_min, tim->tm_sec, (long)tv.tv_usec / 1000, - pthread_self(), WC->wc_session, buf); + (long)pthread_self(), + WC->wc_session, buf); } else { fprintf(stderr, "%04d/%02d/%02d %2d:%02d:%02d.%03ld [%ld] %s", tim->tm_year + 1900, tim->tm_mon + 1, tim->tm_mday, tim->tm_hour, tim->tm_min, tim->tm_sec, (long)tv.tv_usec / 1000, - pthread_self(), buf); + (long)pthread_self(), + buf); } fflush(stderr); }