updates for summer 2020

this update adds the unit tests as part of the student distribution
This commit is contained in:
Godmar Back 2020-08-03 23:33:16 -04:00
parent b0f08b3e8a
commit 7cbe3af927
14 changed files with 2256 additions and 14 deletions

View File

@ -14,12 +14,12 @@ git clone https://github.com/akheron/jansson.git
(cd jansson;
autoreconf -fi;
./configure --prefix=${BASE}/deps;
make install
make -j 40 install
)
git clone https://git@github.com/benmcollins/libjwt.git
(cd libjwt;
autoreconf -fi;
env PKG_CONFIG_PATH=../deps/lib/pkgconfig:${PKG_CONFIG_PATH} ./configure --prefix=${BASE}/deps;
make install
make -j 40 install
)

View File

@ -2,7 +2,7 @@ DEP_BASE_DIR=../deps
DEP_INCLUDE_DIR=$(DEP_BASE_DIR)/include
DEP_LIB_DIR=$(abspath $(DEP_BASE_DIR)/lib)
CFLAGS=-g -O2 -pthread -std=gnu11 -Wall -Werror -Wmissing-prototypes -I$(DEP_INCLUDE_DIR)
CFLAGS=-g -O2 -pthread -Wall -Werror -Wmissing-prototypes -I$(DEP_INCLUDE_DIR)
# include lib directory into runtime path to facilitate dynamic linking
LDFLAGS=-pthread -Wl,-rpath -Wl,$(DEP_LIB_DIR)

View File

@ -24,15 +24,13 @@
#include "hexdump.h"
#include "socket.h"
#include "bufio.h"
#include "main.h"
// Need macros here because of the sizeof
#define CRLF "\r\n"
#define STARTS_WITH(field_name, header) \
(!strncasecmp(field_name, header, sizeof(header) - 1))
char * server_root; // root from which static files are served
/* Parse HTTP request line, setting req_method, req_path, and req_version. */
static bool
http_parse_request(struct http_transaction *ta)
@ -227,6 +225,7 @@ send_error(struct http_transaction * ta, enum http_response_status status, const
ta->resp_body.len += len > MAX_ERROR_LEN ? MAX_ERROR_LEN - 1 : len;
va_end(ap);
ta->resp_status = status;
http_add_header(&ta->resp_headers, "Content-Type", "text/plain");
return send_response(ta);
}

View File

@ -8,21 +8,31 @@
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "buffer.h"
#include "hexdump.h"
#include "http.h"
#include "socket.h"
#include "bufio.h"
#include "globals.h"
#include "main.h"
/* Implement HTML5 fallback.
* This means that if a non-API path refers to a file and that
* file is not found or is a directory, return /index.html
* instead. Otherwise, return the file.
* If HTML5 fallback is implemented and activated, the server should
* treat requests to non-API paths specially.
* If the requested file is not found, the server will serve /index.html
* instead; that is, it should treat the request as if it
* had been for /index.html instead.
*/
bool html5_fallback = false;
// silent_mode. During benchmarking, this will be true
bool silent_mode = false;
int token_expiration_time = 24 * 60 * 60; // default token expiration time is 1 day
// default token expiration time is 1 day
int token_expiration_time = 24 * 60 * 60;
// root from which static files are served
char * server_root;
/*
* A non-concurrent, iterative server that serves one client at a time.
@ -31,7 +41,7 @@ int token_expiration_time = 24 * 60 * 60; // default token expiration time is
static void
server_loop(char *port_string)
{
int accepting_socket = socket_open_bind_listen(port_string, 1024);
int accepting_socket = socket_open_bind_listen(port_string, 10000);
while (accepting_socket != -1) {
fprintf(stderr, "Waiting for client...\n");
int client_socket = socket_accept_client(accepting_socket);
@ -48,7 +58,7 @@ server_loop(char *port_string)
static void
usage(char * av0)
{
fprintf(stderr, "Usage: %s [-p port] [-R rootdir] [-h] [-e seconds]\n"
fprintf(stderr, "Usage: %s -p port [-R rootdir] [-h] [-e seconds]\n"
" -p port port number to bind to\n"
" -R rootdir root directory from which to serve files\n"
" -e seconds expiration time for tokens in seconds\n"
@ -91,6 +101,15 @@ main(int ac, char *av[])
}
}
if (port_string == NULL)
usage(av[0]);
/* We ignore SIGPIPE to prevent the process from terminating when it tries
* to send data to a connection that the client already closed.
* This may happen, in particular, in bufio_sendfile.
*/
signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Using port %s\n", port_string);
server_loop(port_string);
exit(EXIT_SUCCESS);

9
src/main.h Normal file
View File

@ -0,0 +1,9 @@
/*
* Declarations of various global variables.
*/
#include <stdbool.h>
extern char *server_root;
extern bool silent_mode;
extern int token_expiration_time;
extern bool html5_fallback;

View File

@ -18,11 +18,12 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include "socket.h"
#include "globals.h"
#include "main.h"
/*
* Find a suitable IPv4 address to bind to, create a socket, bind it,

4
tests/build.sh Executable file
View File

@ -0,0 +1,4 @@
# build the getaddrinfo preloaded library to test IPv4/IPv6 scenarios
gcc -fPIC -Wall -c getaddrinfo.c
gcc -shared -o getaddrinfo.so.1.0.1 getaddrinfo.o -ldl

102
tests/getaddrinfo.c Normal file
View File

@ -0,0 +1,102 @@
/*
* Intercept getaddrinfo to simulate IPv4-only, IPv6-only, and
* environment in which addresses are returned in a different order.
*
* Written for CS 3214 Virginia Tech, Spring 2018.
*
* Godmar Back <godmar@gmail.com>
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define __USE_GNU 1 /* for RTLD_NEXT */
#include <dlfcn.h>
static int (*real_getaddrinfo)(const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
static void (*real_freeaddrinfo)(struct addrinfo *res);
static void
init()
{
static int inited;
if (inited++ > 0) {
return;
}
real_getaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo");
if (!real_getaddrinfo) {
printf("error in dlsym getaddrinfo %s\n", dlerror());
exit(-1);
}
real_freeaddrinfo = dlsym(RTLD_NEXT, "freeaddrinfo");
if (!real_freeaddrinfo) {
printf("error in dlsym freeaddrinfo %s\n", dlerror());
exit(-1);
}
}
int getaddrinfo(
const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res)
{
init();
struct addrinfo * reallist;
int rc = real_getaddrinfo(node, service, hints, &reallist);
if (rc != 0)
return rc;
int skipipv4 = getenv("SKIPIPV4") != NULL;
int skipipv6 = getenv("SKIPIPV6") != NULL;
int reverse = getenv("REVERSEIPADDR") != NULL;
if (reverse) {
struct addrinfo * rp = reallist;
struct addrinfo * last = NULL;
while (rp != NULL) {
struct addrinfo * next = rp->ai_next;
rp->ai_next = last;
last = rp;
rp = next;
}
*res = last;
} else if (skipipv4 || skipipv6) {
struct addrinfo * rp, ** last = &reallist;
for (rp = reallist; rp != NULL; ) {
if ((skipipv4 && rp->ai_family == AF_INET) || (skipipv6 && rp->ai_family == AF_INET6)) {
// skip and free
(*last) = rp->ai_next;
struct addrinfo * old = rp;
rp = rp->ai_next;
old->ai_next = NULL;
real_freeaddrinfo(old);
} else {
// include
last = &rp->ai_next;
rp = rp->ai_next;
}
}
*res = reallist;
} else {
*res = reallist;
}
return rc;
}
void freeaddrinfo(struct addrinfo *res)
{
init();
real_freeaddrinfo(res);
}

2067
tests/server_unit_test_pserv.py Executable file

File diff suppressed because it is too large Load Diff

7
tests/test_root_data/css/jquery-ui.min.css vendored Executable file

File diff suppressed because one or more lines are too long

11
tests/test_root_data/index.html Executable file
View File

@ -0,0 +1,11 @@
<html>
<head>
<title>
CS3214 - Personal Server
</title>
</head>
<body>
<p>Congrats! Your server is up and running.</p>
<p>This is a main HTML file for CS3214 - Project 4 - Personal Server.</p>
</body>
</html>

3
tests/test_root_data/js/jquery.min.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>
CS3214 - Personal Server
</title>
</head>
<body>
<p>This is a secure file that must be served only if a valid auth token is present.</p>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>
CS3214 - Personal Server
</title>
</head>
<body>
<p>This is a public document that should be accessible irrespective of authentication.</p>
</body>
</html>