2004 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

c8/ws.c

Go to the documentation of this file.
00001 /*
00002     More-complete Web Server
00003     AUP2, Sec. 8.04.4 (not in book)
00004 
00005     Copyright 2003 by Marc J. Rochkind. All rights reserved.
00006     May be copied only for purposes and under conditions described
00007     on the Web page www.basepath.com/aup/copyright.htm.
00008 
00009     The Example Files are provided "as is," without any warranty;
00010     without even the implied warranty of merchantability or fitness
00011     for a particular purpose. The author and his publisher are not
00012     responsible for any damages, direct or incidental, resulting
00013     from the use or non-use of these Example Files.
00014 
00015     The Example Files may contain defects, and some contain deliberate
00016     coding mistakes that were included for educational reasons.
00017     You are responsible for determining if and how the Example Files
00018     are to be used.
00019 
00020 */
00021 #include "defs.h"
00022 #include "ssi.h"
00023 
00024 /* rfc2616 */
00025 
00026 /* use basename? *********************************************************/
00027 
00028 #define WEB_ROOT        "/aup/webroot/"
00029 #define NOTFOUND_PAGE   "/aup/notfound.htm"
00030 
00031 #define HEADER_OK\
00032     "HTTP/1.1 200 OK\r\n"\
00033     "Server: AUP-ws\r\n"\
00034     "Content-Length: %ld\r\n"
00035 
00036 #define CONTENT_TEXT\
00037     "Content-Type: text/html\r\n\r\n"
00038 
00039 #define CONTENT_JPEG\
00040     "Content-Type: image/jpeg\r\n\r\n"
00041 
00042 #define HEADER_NOTFOUND\
00043     "HTTP/1.1 404 Not Found\r\n"\
00044     "Server: AUP-ws\r\n"\
00045     "Transfer-Encoding: chunked\r\n"\
00046     "Content-Type: text/html\r\n\r\n"
00047 
00048 #define HTML_NOTFOUND\
00049     "<!DOCTYPE html PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"\
00050     "<html><head><title>Error 404</title>\n"\
00051     "</head><body>\n"\
00052     "<h2>AUP-ws server can't find page %s</h2>"\
00053     "</body></html>\r\n"
00054 
00055 
00056 static void send_header_OK(SSI *ssip, off_t len, const char *path, int fd)
00057 {
00058     char buf[1000], *dot;
00059 
00060     snprintf(buf, sizeof(buf), HEADER_OK, (long)len);
00061     ec_neg1(  writeall(fd, buf, strlen(buf)) )
00062     /* Following is extremely oversimplified */
00063     dot = strrchr(path, '.');
00064     if (dot != NULL && (strcasecmp(dot, ".jpg") == 0 ||
00065       strcasecmp(dot, ".jpeg") == 0))
00066         ec_neg1(  writeall(fd, CONTENT_JPEG, strlen(CONTENT_JPEG)) )
00067     else {
00068         time_t tm;
00069         char buf[100];
00070 
00071         ec_neg1(  writeall(fd, CONTENT_TEXT, strlen(CONTENT_TEXT)) )
00072         (void)time(&tm);
00073         strcpy(buf, ctime(&tm));
00074         ec_neg1( writeall(fd, buf, strlen(buf)) )
00075     }
00076     return;
00077 
00078 EC_CLEANUP_BGN
00079     EC_FLUSH("Error sending response (nonfatal)")
00080 EC_CLEANUP_END
00081 }
00082 
00083 static void send_header_notfound(SSI *ssip, const char *path, int fd)
00084 {
00085     char buf[2000], buf_html[1000];
00086 
00087     /* Bug: Should remove meta-characters from path. */
00088     snprintf(buf_html, sizeof(buf_html), HTML_NOTFOUND, path);
00089     snprintf(buf, sizeof(buf), "%s%x\r\n%s\r\n0\r\n\r\n",
00090       HEADER_NOTFOUND, strlen(buf_html), buf_html);
00091     ec_neg1(  writeall(fd, buf, strlen(buf)) )
00092     return;
00093 
00094 EC_CLEANUP_BGN
00095     EC_FLUSH("Error sending response (nonfatal)")
00096 EC_CLEANUP_END
00097 }
00098 
00099 static bool handle_request(SSI *ssip, const char *s, int fd)
00100 {
00101     char *p, buf[1000], path[FILENAME_MAX];// wrong macro
00102     FILE *in;
00103     struct stat statbuf;
00104     ssize_t nread, nsent, nsenttotal = 0;
00105 
00106     if (strncasecmp(s, "GET ", 4) == 0) {
00107         s += 4;
00108         p = strchr(s, ' ');
00109         if (p != NULL)
00110             *p = '\0';
00111         strcpy(path, WEB_ROOT);
00112         strncat(path, s, sizeof(path));
00113         if (stat(path, &statbuf) == 0 &&
00114           (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
00115             if (path[strlen(path) - 1] != '/')
00116                 strncat(path, "/", sizeof(path));
00117             strncat(path, "index.html", sizeof(path));
00118         }
00119         if (stat(path, &statbuf) == -1 ||
00120           (in = fopen(path, "rb")) == NULL) {
00121             send_header_notfound(ssip, s, fd);
00122             return false;
00123         }
00124         send_header_OK(ssip, statbuf.st_size, path, fd);
00125 // use sendfile or whatever the fast thingy is
00126         while ((nread = fread(buf, 1, sizeof(buf), in)) > 0) {
00127             ec_neg1(  nsent = writeall(fd, buf, nread) )
00128             nsenttotal += nsent;
00129         }
00130         if (statbuf.st_size != nsenttotal)
00131             printf("Sizes different stat = %ld; sent = %d\n",
00132               (long)statbuf.st_size, nsenttotal);
00133         (void)fclose(in);
00134     }
00135     else
00136         printf("Unknown request: %.25s\n", s);
00137     return true;
00138 
00139 EC_CLEANUP_BGN
00140     EC_FLUSH("Error sending response (nonfatal)")
00141     return false;
00142 EC_CLEANUP_END
00143 }
00144 
00145 int main(int argc, char *argv[])
00146 {
00147     SSI *ssip = NULL;
00148     char msg[1600];
00149     ssize_t nrcv;
00150     int i, fd, c;
00151     char hostbuf[100] = "//", *host = NULL;
00152 
00153     while ((c = getopt(argc, argv, ":h:")) != -1)
00154         switch(c) {
00155         case 'h':
00156             host = optarg;
00157             break;
00158         case ':':
00159             fprintf(stderr, "Option -%c requires an operand\n", optopt);
00160             /* fall through */
00161         default:
00162             fprintf(stderr, "Usage: ws [-h host]\n");
00163             exit(EXIT_FAILURE);
00164         }
00165     if (host == NULL) {
00166         ec_neg1( gethostname(&hostbuf[2], sizeof(hostbuf) - 2) ) /* leave // there */
00167         host = hostbuf;
00168     }
00169     if (strchr(host, ':') == NULL)
00170         strcat(host, ":8000");
00171     printf("Connecting to host \"%s\"\n", host);
00172     ec_null(  ssip = ssi_open(host, true) )
00173     printf("\t...connected\n");
00174     while (true) {
00175         ec_neg1( fd = ssi_wait_server(ssip) )
00176         nrcv = read(fd, msg, sizeof(msg));
00177         switch (nrcv) {
00178         case 0:
00179             continue;
00180         case -1:
00181             if (errno == ECONNRESET)
00182                 fprintf(stderr, "ECONNRESET\n");
00183             syserr_print("smi_receive_skt_string got error (nonfatal)\n");
00184             continue;
00185         default:
00186             msg[nrcv] = '\0';
00187             printf("Got %d bytes:\n", nrcv);
00188             for (i = 0; i < nrcv; i++) {
00189                 if (isgraph((int)msg[i]) || isspace((int)msg[i]))
00190                     printf("%c", msg[i]);
00191                 else
00192                     printf("'\\%o'", msg[i]);
00193             }
00194             (void)handle_request(ssip, msg, fd);
00195         }
00196     }
00197     ec_false( ssi_close(ssip) )
00198     printf("Done.\n");
00199     exit(EXIT_SUCCESS);
00200 
00201 EC_CLEANUP_BGN
00202     return EXIT_FAILURE;
00203 EC_CLEANUP_END
00204 }

Generated on Fri Apr 23 10:57:02 2004 for AUP2 Example Source by doxygen 1.3.1