2 #include <lwip/sockets.h>
7 #define HTTP_VERSION "1.0"
12 #define MAXPENDING 5 // Max connection requests
20 struct responce_header
{
25 struct responce_header headers
[] = {
26 { 200, "HTTP/" HTTP_VERSION
" 200 OK\r\n"
27 "Server: jhttpd/" VERSION
"\r\n"},
31 struct error_messages
{
36 struct error_messages errors
[] = {
49 req_free(struct http_request
*req
)
56 send_header(struct http_request
*req
, int code
)
58 struct responce_header
*h
= headers
;
59 while (h
->code
!= 0 && h
->header
!= 0) {
68 int len
= strlen(h
->header
);
69 if (write(req
->sock
, h
->header
, len
) != len
) {
70 die("Failed to send bytes to client");
77 send_data(struct http_request
*req
, int fd
)
79 // LAB 6: Your code here.
80 panic("send_data not implemented");
84 send_size(struct http_request
*req
, off_t size
)
89 r
= snprintf(buf
, 64, "Content-Length: %ld\r\n", (long)size
);
91 panic("buffer too small!");
93 if (write(req
->sock
, buf
, r
) != r
)
100 mime_type(const char *file
)
102 //TODO: for now only a single mime type
107 send_content_type(struct http_request
*req
)
113 type
= mime_type(req
->url
);
117 r
= snprintf(buf
, 128, "Content-Type: %s\r\n", type
);
119 panic("buffer too small!");
121 if (write(req
->sock
, buf
, r
) != r
)
128 send_header_fin(struct http_request
*req
)
130 const char *fin
= "\r\n";
131 int fin_len
= strlen(fin
);
133 if (write(req
->sock
, fin
, fin_len
) != fin_len
)
139 // given a request, this function creates a struct http_request
141 http_request_parse(struct http_request
*req
, char *request
)
145 int url_len
, version_len
;
150 if (strncmp(request
, "GET ", 4) != 0)
158 while (*request
&& *request
!= ' ')
160 url_len
= request
- url
;
162 req
->url
= malloc(url_len
+ 1);
163 memmove(req
->url
, url
, url_len
);
164 req
->url
[url_len
] = '\0';
170 while (*request
&& *request
!= '\n')
172 version_len
= request
- version
;
174 req
->version
= malloc(version_len
+ 1);
175 memmove(req
->version
, version
, version_len
);
176 req
->version
[version_len
] = '\0';
184 send_error(struct http_request
*req
, int code
)
189 struct error_messages
*e
= errors
;
190 while (e
->code
!= 0 && e
->msg
!= 0) {
199 r
= snprintf(buf
, 512, "HTTP/" HTTP_VERSION
" %d %s\r\n"
200 "Server: jhttpd/" VERSION
"\r\n"
202 "Content-type: text/html\r\n"
204 "<html><body><p>%d - %s</p></body></html>\r\n",
205 e
->code
, e
->msg
, e
->code
, e
->msg
);
207 if (write(req
->sock
, buf
, r
) != r
)
214 send_file(struct http_request
*req
)
217 off_t file_size
= -1;
220 // open the requested url for reading
221 // if the file does not exist, send a 404 error using send_error
222 // if the file is a directory, send a 404 error using send_error
223 // set file_size to the size of the file
225 // LAB 6: Your code here.
226 panic("send_file not implemented");
228 if ((r
= send_header(req
, 200)) < 0)
231 if ((r
= send_size(req
, file_size
)) < 0)
234 if ((r
= send_content_type(req
)) < 0)
237 if ((r
= send_header_fin(req
)) < 0)
240 r
= send_data(req
, fd
);
248 handle_client(int sock
)
250 struct http_request con_d
;
252 char buffer
[BUFFSIZE
];
254 struct http_request
*req
= &con_d
;
259 if ((received
= read(sock
, buffer
, BUFFSIZE
)) < 0)
260 panic("failed to read");
262 memset(req
, 0, sizeof(req
));
266 r
= http_request_parse(req
, buffer
);
268 send_error(req
, 400);
270 panic("parse failed");
284 umain(int argc
, char **argv
)
286 int serversock
, clientsock
;
287 struct sockaddr_in server
, client
;
289 binaryname
= "jhttpd";
291 // Create the TCP socket
292 if ((serversock
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
293 die("Failed to create socket");
295 // Construct the server sockaddr_in structure
296 memset(&server
, 0, sizeof(server
)); // Clear struct
297 server
.sin_family
= AF_INET
; // Internet/IP
298 server
.sin_addr
.s_addr
= htonl(INADDR_ANY
); // IP address
299 server
.sin_port
= htons(PORT
); // server port
301 // Bind the server socket
302 if (bind(serversock
, (struct sockaddr
*) &server
,
305 die("Failed to bind the server socket");
308 // Listen on the server socket
309 if (listen(serversock
, MAXPENDING
) < 0)
310 die("Failed to listen on server socket");
312 cprintf("Waiting for http connections...\n");
315 unsigned int clientlen
= sizeof(client
);
316 // Wait for client connection
317 if ((clientsock
= accept(serversock
,
318 (struct sockaddr
*) &client
,
321 die("Failed to accept client connection");
323 handle_client(clientsock
);