| @@ -4,21 +4,146 @@ · 3 unmodified lines |
| 4 | #include <fns.h> | 4 | #include <fns.h> |
| 5 | #include <dat.h> | 5 | #include <dat.h> |
| 6 | | 6 | |
| | 7 | int |
| | 8 | parse(char *buf, Request *req) |
| | 9 | { |
| | 10 | static int first_header = 1; // interesting |
| | 11 | char *endptr; |
| | 12 | int len; |
| | 13 | |
| | 14 | if (first_header) { |
| | 15 | if (!strncmp(buf, "GET ", 4)) { |
| | 16 | req->method = GET; |
| | 17 | buf += 4; |
| | 18 | } else { |
| | 19 | req->method = UNSUPPORTED; |
| | 20 | req->status = 501; |
| | 21 | } |
| | 22 | |
| | 23 | while (*buf && isspace(*buf)) |
| | 24 | buf++; |
| | 25 | |
| | 26 | endptr = strchr(buf, ' '); |
| | 27 | if (endptr == 0) |
| | 28 | len = strlen(buf); |
| | 29 | else |
| | 30 | len = endptr - buf; |
| | 31 | if (!len) { |
| | 32 | req->status = 400; |
| | 33 | return -1; |
| | 34 | } |
| | 35 | |
| | 36 | req->resource = calloc(len+1, sizeof(char)); |
| | 37 | strncpy(req->resource, buf, len); |
| | 38 | |
| | 39 | if (strstr(buf, "HTTP/")) |
| | 40 | req->type = FULL; |
| | 41 | else |
| | 42 | req->type = SIMPLE; |
| | 43 | |
| | 44 | first_header = 0; |
| | 45 | return 0; |
| | 46 | } |
| | 47 | return 0; |
| | 48 | } |
| | 49 | |
| | 50 | void |
| | 51 | reqinit(Request *req) |
| | 52 | { |
| | 53 | req->status = 200; |
| | 54 | } |
| | 55 | |
| | 56 | int |
| | 57 | openresource(Request *req) |
| | 58 | { |
| | 59 | cleanURL(req->resource); |
| | 60 | strcat(root, req->resource); |
| | 61 | return open(root, OREAD); |
| | 62 | } |
| | 63 | |
| | 64 | void |
| | 65 | outputheaders(int fd, Request *req) |
| | 66 | { |
| | 67 | char buf[100]; |
| | 68 | sprint(buf, "HTTP/1.0 %d OK\r\r", req->status); |
| | 69 | writeline(fd, buf, strlen(buf)); |
| | 70 | |
| | 71 | writeline(fd, "Server: httpbench\r\n", strlen("Server: httpbench\r\n")); |
| | 72 | writeline(fd, "Content-Type: text/html\r\n", 25); |
| | 73 | writeline(fd, "\r\n", 2); |
| | 74 | } |
| | 75 | |
| | 76 | int |
| | 77 | sendresource(int conn, int resource) |
| | 78 | { |
| | 79 | char c; |
| | 80 | int i; |
| | 81 | |
| | 82 | while ( (i = read(resource, &c, 1)) ) { |
| | 83 | if ( i < 0 ) |
| | 84 | exits("Error reading from file."); |
| | 85 | if ( write(conn, &c, 1) < 1 ) |
| | 86 | exits("Error sending file."); |
| | 87 | } |
| | 88 | |
| | 89 | return 0; |
| | 90 | } |
| | 91 | |
| | 92 | int |
| | 93 | senderror(int conn, Request* reqinfo) |
| | 94 | { |
| | 95 | |
| | 96 | char buffer[100]; |
| | 97 | |
| | 98 | sprint(buffer, "<HTML>\n<HEAD>\n<TITLE>Server Error %d</TITLE>\n" |
| | 99 | "</HEAD>\n\n", reqinfo->status); |
| | 100 | writeline(conn, buffer, strlen(buffer)); |
| | 101 | |
| | 102 | sprint(buffer, "<BODY>\n<H1>Server Error %d</H1>\n", reqinfo->status); |
| | 103 | writeline(conn, buffer, strlen(buffer)); |
| | 104 | |
| | 105 | sprint(buffer, "<P>The request could not be completed.</P>\n" |
| | 106 | "</BODY>\n</HTML>\n"); |
| | 107 | writeline(conn, buffer, strlen(buffer)); |
| | 108 | |
| | 109 | return 0; |
| | 110 | |
| | 111 | } |
| | 112 | |
| 7 | void | 113 | void |
| 8 | handler(int fd) | 114 | handler(int fd) |
| 9 | { | 115 | { |
| 10 | char buffer[MaxLineLen] = {0}; | 116 | char buffer[MaxLineLen] = {0}; |
| | 117 | Request req; |
| | 118 | int rfd; // resource fd |
| 11 | | 119 | |
| 12 | print("new connection\n"); | 120 | reqinit(&req); |
| 13 | | 121 | |
| 14 | alarm(TIMEOUT); | 122 | alarm(TIMEOUT); |
| 15 | do { | 123 | do { |
| 16 | Readline(fd, buffer, MaxLineLen - 1); | 124 | readline(fd, buffer, MaxLineLen - 1); |
| 17 | Trim(buffer); | 125 | trim(buffer); |
| 18 | print("read: %s\n", buffer); | 126 | if (buffer[0] == '\0') |
| 19 | } while (1); | 127 | break; |
| | 128 | if (parse(buffer, &req)) |
| | 129 | break; |
| | 130 | } while (req.type != SIMPLE); |
| 20 | alarm(0); | 131 | alarm(0); |
| 21 | print("done\n"); | 132 | |
| | 133 | rfd = openresource(&req); // make sure the resource exists |
| | 134 | if (rfd < 0) |
| | 135 | req.status = 404; |
| | 136 | |
| | 137 | if (req.type == FULL) |
| | 138 | outputheaders(fd, &req); |
| | 139 | |
| | 140 | if (req.status == 200) { |
| | 141 | if (sendresource(fd, rfd)) |
| | 142 | exits("something bad happened while sending the resource\n"); |
| | 143 | } else { |
| | 144 | senderror(fd, &req); |
| | 145 | } |
| | 146 | exits(0); |
| 22 | } | 147 | } |
| 23 | | 148 | |
| 24 | // This started life as a straight rip-off from dial(2) | 149 | // This started life as a straight rip-off from dial(2) |
| @@ -27,8 +152,6 @@ main() · 2 unmodified lines |
| 27 | { | 152 | { |
| 28 | int dfd, acfd, lcfd; | 153 | int dfd, acfd, lcfd; |
| 29 | char adir[40], ldir[40]; | 154 | char adir[40], ldir[40]; |
| 30 | int n; | | |
| 31 | char buf[256]; | | |
| 32 | | 155 | |
| 33 | acfd = announce("tcp!*!8080", adir); | 156 | acfd = announce("tcp!*!8080", adir); |
| 34 | if (acfd < 0) | 157 | if (acfd < 0) |
| @@ -50,10 +173,7 @@ main() · 15 unmodified lines |
| 50 | exits("accept failed"); | 173 | exits("accept failed"); |
| 51 | | 174 | |
| 52 | handler(dfd); | 175 | handler(dfd); |
| 53 | /* echo until EOF */ | 176 | exits(0); // should never get here |
| 54 | //while((n = read(dfd, buf, sizeof(buf))) > 0) | | |
| 55 | // write(dfd, buf, n); | | |
| 56 | exits(0); | | |
| 57 | default: | 177 | default: |
| 58 | close(lcfd); | 178 | close(lcfd); |
| 59 | break; | 179 | break; |