Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Given the tiny webserver C code. Modify the tiny webserver to do the following: a-Let it recognize and play mp3 audio files. b-save any mp3

Given the tiny webserver C code.

Modify the tiny webserver to do the following:

a-Let it recognize and play mp3 audio files.

b-save any mp3 file on the tiny directory and the html file "mp3.html" that will play the audio file

c- Extend tiny to support the HTTP HEAD method. HEAD is like mini version of GET method.

d-Include a CGI program called "hw5cgi" that should accept 5 integer numbers as arguments formatted as "?x1=val1&x2=val2&x3=val3&x4=val4&x5=val5". The CGI program should display the variable names and their values follwed by the minimum value, maximum value, and average value shown as:

x1=val1

x2=val2

x3=val3

x4=val4

x5=val5

minimum = val

maximum = val

average = val

Note that the variable names could take any value not necessarily start with "x" as shown in the example above

e- write a html file named "hw5.html" that will use forms to take five integer numbers from the user and then submit the numbers to the CGI program and show the result

f- test HTTP HEAD using telnet and include the result in your report

g- show screen shots of the browser using the html files in the report

//tiny webserver source code that you will modify:

/* $begin tinymain */

/*

* tiny.c - A simple, iterative HTTP/1.0 Web server that uses the

* GET method to serve static and dynamic content.

*/

#include "csapp.h"

void doit(int fd);

void read_requesthdrs(rio_t *rp);

int parse_uri(char *uri, char *filename, char *cgiargs);

void serve_static(int fd, char *filename, int filesize);

void get_filetype(char *filename, char *filetype);

void serve_dynamic(int fd, char *filename, char *cgiargs);

void clienterror(int fd, char *cause, char *errnum,

char *shortmsg, char *longmsg);

int main(int argc, char **argv)

{

int listenfd, connfd;

char hostname[MAXLINE], port[MAXLINE];

socklen_t clientlen;

struct sockaddr_storage clientaddr;

/* Check command line args */

if (argc != 2) {

fprintf(stderr, "usage: %s ", argv[0]);

exit(1);

}

listenfd = Open_listenfd(argv[1]);

while (1) {

clientlen = sizeof(clientaddr);

connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); //line:netp:tiny:accept

Getnameinfo((SA *) &clientaddr, clientlen, hostname, MAXLINE,

port, MAXLINE, 0);

printf("Accepted connection from (%s, %s) ", hostname, port);

doit(connfd); //line:netp:tiny:doit

Close(connfd); //line:netp:tiny:close

}

}

/* $end tinymain */

/*

* doit - handle one HTTP request/response transaction

*/

/* $begin doit */

void doit(int fd)

{

int is_static;

struct stat sbuf;

char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];

char filename[MAXLINE], cgiargs[MAXLINE];

rio_t rio;

/* Read request line and headers */

Rio_readinitb(&rio, fd);

if (!Rio_readlineb(&rio, buf, MAXLINE)) //line:netp:doit:readrequest

return;

printf("%s", buf);

sscanf(buf, "%s %s %s", method, uri, version); //line:netp:doit:parserequest

if (strcasecmp(method, "GET")) { //line:netp:doit:beginrequesterr

clienterror(fd, method, "501", "Not Implemented",

"Tiny does not implement this method");

return;

} //line:netp:doit:endrequesterr

read_requesthdrs(&rio); //line:netp:doit:readrequesthdrs

/* Parse URI from GET request */

is_static = parse_uri(uri, filename, cgiargs); //line:netp:doit:staticcheck

if (stat(filename, &sbuf) < 0) { //line:netp:doit:beginnotfound

clienterror(fd, filename, "404", "Not found",

"Tiny couldn't find this file");

return;

} //line:netp:doit:endnotfound

if (is_static) { /* Serve static content */

if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { //line:netp:doit:readable

clienterror(fd, filename, "403", "Forbidden",

"Tiny couldn't read the file");

return;

}

serve_static(fd, filename, sbuf.st_size); //line:netp:doit:servestatic

}

else { /* Serve dynamic content */

if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { //line:netp:doit:executable

clienterror(fd, filename, "403", "Forbidden",

"Tiny couldn't run the CGI program");

return;

}

serve_dynamic(fd, filename, cgiargs); //line:netp:doit:servedynamic

}

}

/* $end doit */

/*

* read_requesthdrs - read HTTP request headers

*/

/* $begin read_requesthdrs */

void read_requesthdrs(rio_t *rp)

{

char buf[MAXLINE];

Rio_readlineb(rp, buf, MAXLINE);

printf("%s", buf);

while(strcmp(buf, " ")) { //line:netp:readhdrs:checkterm

Rio_readlineb(rp, buf, MAXLINE);

printf("%s", buf);

}

return;

}

/* $end read_requesthdrs */

/*

* parse_uri - parse URI into filename and CGI args

* return 0 if dynamic content, 1 if static

*/

/* $begin parse_uri */

int parse_uri(char *uri, char *filename, char *cgiargs)

{

char *ptr;

if (!strstr(uri, "cgi-bin")) { /* Static content */ //line:netp:parseuri:isstatic

strcpy(cgiargs, ""); //line:netp:parseuri:clearcgi

strcpy(filename, "."); //line:netp:parseuri:beginconvert1

strcat(filename, uri); //line:netp:parseuri:endconvert1

if (uri[strlen(uri)-1] == '/') //line:netp:parseuri:slashcheck

strcat(filename, "home.html"); //line:netp:parseuri:appenddefault

return 1;

}

else { /* Dynamic content */ //line:netp:parseuri:isdynamic

ptr = index(uri, '?'); //line:netp:parseuri:beginextract

if (ptr) {

strcpy(cgiargs, ptr+1);

*ptr = '\0';

}

else

strcpy(cgiargs, ""); //line:netp:parseuri:endextract

strcpy(filename, "."); //line:netp:parseuri:beginconvert2

strcat(filename, uri); //line:netp:parseuri:endconvert2

return 0;

}

}

/* $end parse_uri */

/*

* serve_static - copy a file back to the client

*/

/* $begin serve_static */

void serve_static(int fd, char *filename, int filesize)

{

int srcfd;

char *srcp, filetype[MAXLINE], buf[MAXBUF];

/* Send response headers to client */

get_filetype(filename, filetype); //line:netp:servestatic:getfiletype

sprintf(buf, "HTTP/1.0 200 OK "); //line:netp:servestatic:beginserve

sprintf(buf, "%sServer: Tiny Web Server ", buf);

sprintf(buf, "%sConnection: close ", buf);

sprintf(buf, "%sContent-length: %d ", buf, filesize);

sprintf(buf, "%sContent-type: %s ", buf, filetype);

Rio_writen(fd, buf, strlen(buf)); //line:netp:servestatic:endserve

printf("Response headers: ");

printf("%s", buf);

/* Send response body to client */

srcfd = Open(filename, O_RDONLY, 0); //line:netp:servestatic:open

srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap

Close(srcfd); //line:netp:servestatic:close

Rio_writen(fd, srcp, filesize); //line:netp:servestatic:write

Munmap(srcp, filesize); //line:netp:servestatic:munmap

}

/*

* get_filetype - derive file type from file name

*/

void get_filetype(char *filename, char *filetype)

{

if (strstr(filename, ".html"))

strcpy(filetype, "text/html");

else if (strstr(filename, ".gif"))

strcpy(filetype, "image/gif");

else if (strstr(filename, ".png"))

strcpy(filetype, "image/png");

else if (strstr(filename, ".jpg"))

strcpy(filetype, "image/jpeg");

else

strcpy(filetype, "text/plain");

}

/* $end serve_static */

/*

* serve_dynamic - run a CGI program on behalf of the client

*/

/* $begin serve_dynamic */

void serve_dynamic(int fd, char *filename, char *cgiargs)

{

char buf[MAXLINE], *emptylist[] = { NULL };

/* Return first part of HTTP response */

sprintf(buf, "HTTP/1.0 200 OK ");

Rio_writen(fd, buf, strlen(buf));

sprintf(buf, "Server: Tiny Web Server ");

Rio_writen(fd, buf, strlen(buf));

if (Fork() == 0) { /* Child */ //line:netp:servedynamic:fork

/* Real server would set all CGI vars here */

setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv

Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ //line:netp:servedynamic:dup2

Execve(filename, emptylist, environ); /* Run CGI program */ //line:netp:servedynamic:execve

}

Wait(NULL); /* Parent waits for and reaps child */ //line:netp:servedynamic:wait

}

/* $end serve_dynamic */

/*

* clienterror - returns an error message to the client

*/

/* $begin clienterror */

void clienterror(int fd, char *cause, char *errnum,

char *shortmsg, char *longmsg)

{

char buf[MAXLINE], body[MAXBUF];

/* Build the HTTP response body */

sprintf(body, "Tiny Error");

sprintf(body, "%s ", body);

sprintf(body, "%s%s: %s ", body, errnum, shortmsg);

sprintf(body, "%s

%s: %s ", body, longmsg, cause);

sprintf(body, "%s


The Tiny Web server ", body);

/* Print the HTTP response */

sprintf(buf, "HTTP/1.0 %s %s ", errnum, shortmsg);

Rio_writen(fd, buf, strlen(buf));

sprintf(buf, "Content-type: text/html ");

Rio_writen(fd, buf, strlen(buf));

sprintf(buf, "Content-length: %d ", (int)strlen(body));

Rio_writen(fd, buf, strlen(buf));

Rio_writen(fd, body, strlen(body));

}

/* $end clienterror */

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Beginning C# 5.0 Databases

Authors: Vidya Vrat Agarwal

2nd Edition

1430242604, 978-1430242604

More Books

Students also viewed these Databases questions

Question

42 Pay programs (for example, incentive, variable, merit).

Answered: 1 week ago