diff --git a/ethernet/c/Makefile b/ethernet/c/Makefile index af43d7af..4985aa11 100644 --- a/ethernet/c/Makefile +++ b/ethernet/c/Makefile @@ -2,7 +2,9 @@ CC = gcc CFLAGS = -Wall -O2 LFLAGS =-lpcap -all: testarp +all: testarp webserver + +### testarp: testarp.o $(CC) $(LFLAGS) -o testarp testarp.o @@ -10,5 +12,15 @@ testarp: testarp.o testarp.o: testarp.c $(CC) $(CFLAGS) -c testarp.c +### + +webserver: webserver.o + $(CC) $(LFLAGS) -o webserver webserver.o + +webserver.o: webserver.c + $(CC) $(CFLAGS) -c webserver.c + +### + clean: - rm -f *~ *.o testarp + rm -f *~ *.o testarp webserver diff --git a/ethernet/c/about.html b/ethernet/c/about.html new file mode 100644 index 00000000..a035a6a5 --- /dev/null +++ b/ethernet/c/about.html @@ -0,0 +1,14 @@ + +About the VMW-web server + + + +

About the VMW-web server

+ +I made it myself. + +
+ +Back + + diff --git a/ethernet/c/index.html b/ethernet/c/index.html new file mode 100644 index 00000000..da0a4dfb --- /dev/null +++ b/ethernet/c/index.html @@ -0,0 +1,23 @@ + +Sample web Page + + + +
+ +

Sample Web Page

+ +Just testing out a barebones webserver for ECE435.

+ +More info

+ +Invalid Link

+ +Teapot Link

+ +
+ +Back to My Web Page + + + diff --git a/ethernet/c/vmw_logo.png b/ethernet/c/vmw_logo.png new file mode 100644 index 00000000..8a21707e Binary files /dev/null and b/ethernet/c/vmw_logo.png differ diff --git a/ethernet/c/webserver.c b/ethernet/c/webserver.c new file mode 100644 index 00000000..d12757b4 --- /dev/null +++ b/ethernet/c/webserver.c @@ -0,0 +1,357 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BUFFER_SIZE 256 + +/* assume the max command we get is this big */ +#define RECEIVE_BUFFER_SIZE 4096 + + +/* Default port to listen on */ +#define DEFAULT_PORT 80 + + +#define MIME_HTML 0 +#define MIME_TXT 1 +#define MIME_PNG 2 +#define MIME_JPG 3 +#define MIME_MAX 4 + + + +struct mime_type { + char extension[5]; + char string[32]; +}; + +struct mime_type mime[MIME_MAX] = { + {"html", "text/html"}, + {"txt", "text/plain"}, + {"png", "image/png"}, + {"jpg", "image/jpeg"}, +}; + +static int detect_mime(char *filename) { + + int i,j; + + i=strlen(filename); + while(i>0) { + if (filename[i]=='.') break; + i--; + } + i++; + + for(j=0;j\r\n" + "418 I'm a teapot\r\n" + "\r\n" + "

I'm a Teapot

\r\n" + "

I'm a *little* teapot.
\r\n" + "

\r\n" + "\r\n"; + + sprintf(out_buffer, + "HTTP/1.1 418 I'm a teapot\r\n" + "Date: %s\r\n" + "Server: VMW-web\r\n" + "Content-Length: %d\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "\r\n" + "%s", + time_string,(int)strlen(message418),message418); + out_size=strlen(out_buffer); + + } else if (result<0) { + char message404[]= + "\r\n" + "400 Bad Request\r\n" + "\r\n" + "

Bad Request

\r\n" + "

Your browser sent a request that this server could not understand.
\r\n" + "

\r\n" + "\r\n"; + + sprintf(out_buffer, + "HTTP/1.1 400 Bad Request\r\n" + "Date: %s\r\n" + "Server: VMW-web\r\n" + "Content-Length: %d\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "\r\n" + "%s", + time_string,(int)strlen(message404),message404); + out_size=strlen(out_buffer); + } + + else { + char mod_string[1000]; + tm = *gmtime(&stat_buf.st_mtime); + int in_fd,out_offset; + char file_buffer[256]; + + strftime(mod_string, sizeof(mod_string), + "%a, %d %b %Y %H:%M:%S %Z", &tm); + + sprintf(out_buffer, + "HTTP/1.1 200 OK\r\n" + "Date: %s\r\n" + "Server: VMW-web\r\n" + "Last-Modified: %s\r\n" + "Content-Length: %ld\r\n" + "Content-Type: %s\r\n" + "\r\n", + time_string, + mod_string, + stat_buf.st_size, + mime[mime_type].string); + + out_offset=strlen(out_buffer); + + in_fd=open(filename,O_RDONLY); + if (in_fd<0) { + fprintf(stderr,"Could not open %s\n",filename); + } else { + while(1) { + result=read(in_fd,&file_buffer,256); + if (result<=0) break; + + memcpy(out_buffer+out_offset, + file_buffer,result); + out_offset+=result; + } + + close(in_fd); + } + out_size=out_offset; + } + + + /* Send a response */ + + printf("Sending:\n"); + printf("%s\n",out_buffer); + + n = write(fd,out_buffer,out_size); + if (n<0) { + fprintf(stderr,"Error writing. %s\n", + strerror(errno)); + } + return 0; +} + + +int main(int argc, char **argv) { + + int socket_fd,new_socket_fd; + struct sockaddr_in server_addr, client_addr; + struct addrinfo hints,*server_info; + int port=DEFAULT_PORT; + int n; + socklen_t client_len; + char buffer[BUFFER_SIZE]; + char in[RECEIVE_BUFFER_SIZE]; + int i,result,in_ptr=0; + char port_string[BUFFER_SIZE]; + + if (argc>1) { + port=atoi(argv[1]); + } + sprintf(port_string,"%d",port); + + + printf("Starting server on port %d\n",port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + /* Null means localhost */ + /* How can we get IP of default interface? */ + result=getaddrinfo(NULL,port_string,&hints,&server_info); + if (result<0) { + fprintf(stderr,"Error getaddrinfo!\n"); + return -1; + } + + /* Open a socket to listen on */ + /* AF_INET means an IPv4 connection */ + /* SOCK_STREAM means reliable two-way connection (TCP) */ + socket_fd = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); + if (socket_fd<0) { + fprintf(stderr,"Error opening socket! %s\n", + strerror(errno)); + return -1; + } + + /* Set up the server address to listen on */ + memset(&server_addr,0,sizeof(struct sockaddr_in)); + server_addr.sin_family=AF_INET; + /* Convert the port we want to network byte order */ + server_addr.sin_port=htons(port); + + + /* Bind to the port */ + if (bind(socket_fd, server_info->ai_addr,server_info->ai_addrlen)) { + fprintf(stderr,"Error binding! %s\n", strerror(errno)); + return -1; + } + + /* Tell the server we want to listen on the port */ + /* Second argument is backlog, how many pending connections can */ + /* build up */ + listen(socket_fd,5); + +listen_connection: + + /* Call accept to create a new file descriptor for an incoming */ + /* connection. It takes the oldest one off the queue */ + /* We're blocking so it waits here until a connection happens */ + client_len=sizeof(client_addr); + new_socket_fd = accept(socket_fd, + (struct sockaddr *)&client_addr,&client_len); + if (new_socket_fd<0) { + fprintf(stderr,"Error accepting! %s\n",strerror(errno)); + } + + + in_ptr=0; + + while(1) { + + /* Someone connected! Let's try to read BUFFER_SIZE-1 bytes */ + memset(buffer,0,BUFFER_SIZE); + n = read(new_socket_fd,buffer,(BUFFER_SIZE-1)); + if (n==0) { + fprintf(stderr,"Connection to client lost\n\n"); + break; + } + else if (n<0) { + fprintf(stderr,"Error reading from socket %s\n", + strerror(errno)); + } + + if (in_ptr+n>RECEIVE_BUFFER_SIZE) { + fprintf(stderr,"Overflow receive buffer!\n"); + break; + } + + memcpy(&in[in_ptr],buffer,n); + in_ptr+=n; + in[in_ptr]=0; + + /* See if last chars were CRLFCRLF (empty line) */ + /* Which indicates done talking */ + if ((in[in_ptr-1]=='\n') && (in[in_ptr-3]=='\n')) { + break; + } + } + + + /* Print the message we received */ + + char filename[BUFSIZ]; + + printf("Request from webserver:\n"); + i=0; + int found_filename=0,file_ptr=0; + while(iBUFSIZ) break; + } + filename[file_ptr]=0; + } + + + } + } + } + } + + printf("%c",in[i]); + i++; + } + + if (!strcmp(filename,"/")) { + printf("Mapping / to index.html\n"); + strcpy(filename,"/index.html"); + } + + printf("Sending back file: %s\n",filename); + + /* Skip leading / */ + serve_file(new_socket_fd,filename+1); + + printf("Exiting server\n\n"); + + /* Try to avoid TIME_WAIT */ +// sleep(1); + + /* Close the sockets */ + close(new_socket_fd); + + goto listen_connection; + + close(socket_fd); + + return 0; +} + +