Changes in uspace/app/websrv/websrv.c [9c3bba0:f4a2d624] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/websrv/websrv.c
r9c3bba0 rf4a2d624 1 1 /* 2 * Copyright (c) 201 1Jiri Svoboda2 * Copyright (c) 2010 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** 33 * @file Skeletalweb server.33 * @file (Less-than-skeleton) web server. 34 34 */ 35 35 36 #include <bool.h>37 #include <errno.h>38 36 #include <stdio.h> 39 #include <sys/types.h>40 #include <sys/stat.h>41 #include <stdlib.h>42 #include <fcntl.h>43 37 44 38 #include <net/in.h> … … 50 44 #define PORT_NUMBER 8080 51 45 52 #define WEB_ROOT "/data/web"53 54 46 /** Buffer for receiving the request. */ 55 47 #define BUFFER_SIZE 1024 56 static char rbuf[BUFFER_SIZE]; 57 static size_t rbuf_out, rbuf_in; 58 59 static char lbuf[BUFFER_SIZE + 1]; 60 static size_t lbuf_used; 61 62 static char fbuf[BUFFER_SIZE]; 48 static char buf[BUFFER_SIZE]; 63 49 64 50 /** Response to send to client. */ 65 static const char * ok_msg =51 static const char *response_msg = 66 52 "HTTP/1.0 200 OK\r\n" 67 "\r\n"; 68 69 /** Receive one character (with buffering) */ 70 static int recv_char(int fd, char *c) 71 { 72 ssize_t rc; 73 74 if (rbuf_out == rbuf_in) { 75 rbuf_out = 0; 76 rbuf_in = 0; 77 78 rc = recv(fd, rbuf, BUFFER_SIZE, 0); 79 if (rc <= 0) { 80 printf("recv() failed (%zd)\n", rc); 81 return rc; 82 } 83 84 rbuf_in = rc; 85 } 86 87 *c = rbuf[rbuf_out++]; 88 return EOK; 89 } 90 91 /** Receive one line with length limit. */ 92 static int recv_line(int fd) 93 { 94 char c, prev; 95 int rc; 96 char *bp; 97 98 bp = lbuf; c = '\0'; 99 while (bp < lbuf + BUFFER_SIZE) { 100 prev = c; 101 rc = recv_char(fd, &c); 102 if (rc != EOK) 103 return rc; 104 105 *bp++ = c; 106 if (prev == '\r' && c == '\n') 107 break; 108 } 109 110 lbuf_used = bp - lbuf; 111 *bp = '\0'; 112 113 if (bp == lbuf + BUFFER_SIZE) 114 return ELIMIT; 115 116 return EOK; 117 } 118 119 static bool uri_is_valid(char *uri) 120 { 121 char *cp; 122 char c; 123 124 if (uri[0] != '/') 125 return false; 126 if (uri[1] == '.') 127 return false; 128 129 cp = uri + 1; 130 while (*cp != '\0') { 131 c = *cp++; 132 if (c == '/') 133 return false; 134 } 135 136 return true; 137 } 138 139 static int send_response(int conn_sd, const char *msg) 140 { 141 size_t response_size; 142 ssize_t rc; 143 144 response_size = str_size(msg); 145 146 /* Send a canned response. */ 147 printf("Send response...\n"); 148 rc = send(conn_sd, (void *) msg, response_size, 0); 149 if (rc < 0) { 150 printf("send() failed.\n"); 151 return rc; 152 } 153 154 return EOK; 155 } 156 157 static int uri_get(const char *uri, int conn_sd) 158 { 159 int rc; 160 char *fname; 161 int fd; 162 ssize_t nr; 163 164 if (str_cmp(uri, "/") == 0) 165 uri = "/index.htm"; 166 167 rc = asprintf(&fname, "%s%s", WEB_ROOT, uri); 168 if (rc < 0) 169 return ENOMEM; 170 171 fd = open(fname, O_RDONLY); 172 if (fd < 0) { 173 printf("File '%s' not found.\n", fname); 174 free(fname); 175 return ENOENT; 176 } 177 178 free(fname); 179 180 rc = send_response(conn_sd, ok_msg); 181 if (rc != EOK) 182 return rc; 183 184 while (true) { 185 nr = read(fd, fbuf, BUFFER_SIZE); 186 if (nr == 0) 187 break; 188 189 if (nr < 0) { 190 close(fd); 191 return EIO; 192 } 193 194 rc = send(conn_sd, fbuf, nr, 0); 195 if (rc < 0) { 196 printf("send() failed\n"); 197 close(fd); 198 return rc; 199 } 200 } 201 202 close(fd); 203 204 return EOK; 205 } 206 207 static int req_process(int conn_sd) 208 { 209 int rc; 210 char *uri, *end_uri; 211 212 rc = recv_line(conn_sd); 213 if (rc != EOK) { 214 printf("recv_line() failed\n"); 215 return rc; 216 } 217 218 printf("%s", lbuf); 219 220 if (str_lcmp(lbuf, "GET ", 4) != 0) { 221 printf("Invalid HTTP method.\n"); 222 return EINVAL; 223 } 224 225 uri = lbuf + 4; 226 end_uri = str_chr(uri, ' '); 227 if (end_uri == NULL) { 228 end_uri = lbuf + lbuf_used - 2; 229 assert(*end_uri == '\r'); 230 } 231 232 *end_uri = '\0'; 233 printf("Requested URI '%s'.\n", uri); 234 235 if (!uri_is_valid(uri)) { 236 printf("Invalid request URI.\n"); 237 return EINVAL; 238 } 239 240 return uri_get(uri, conn_sd); 241 } 53 "\r\n" 54 "<h1>Hello from HelenOS!</h1>\r\n"; 242 55 243 56 int main(int argc, char *argv[]) … … 251 64 int rc; 252 65 66 size_t response_size; 253 67 254 68 addr.sin_family = AF_INET; … … 281 95 } 282 96 97 response_size = str_size(response_msg); 98 283 99 printf("Listening for connections at port number %u.\n", PORT_NUMBER); 284 100 while (true) { … … 289 105 if (conn_sd < 0) { 290 106 printf("accept() failed.\n"); 291 continue;107 return 1; 292 108 } 293 109 … … 295 111 296 112 printf("Wait for client request\n"); 297 rbuf_out = rbuf_in = 0;298 113 299 rc = req_process(conn_sd); 300 if (rc != EOK) 301 printf("Error processing request.\n"); 114 /* Really we should wait for a blank line. */ 115 rc = recv(conn_sd, buf, BUFFER_SIZE, 0); 116 if (rc < 0) { 117 printf("recv() failed\n"); 118 return 1; 119 } 120 121 /* Send a canned response. */ 122 printf("Send response...\n"); 123 rc = send(conn_sd, (void *) response_msg, response_size, 0); 124 if (rc < 0) { 125 printf("send() failed.\n"); 126 return 1; 127 } 302 128 303 129 rc = closesocket(conn_sd);
Note:
See TracChangeset
for help on using the changeset viewer.