代写代考 #include

#include
#include
#include
#include

Copyright By PowCoder代写 加微信 powcoder

#include
#include
#include #include
#include
#include
#include
#include
#include
#include
#include
#include

#include “libhttp.h”
#include “util.h”
#include “async.h”

* Global configuration variables.

int num_threads;
int server_port;
char *server_files_directory;
char *server_proxy_hostname;
int server_proxy_port;

* Reads an HTTP request from stream (fd), and writes an HTTP response
* containing:
* 1) If user requested an existing file, respond with the file
* 2) If user requested a directory and index.html exists in the directory,
* send the index.html file.
* 3) If user requested a directory and index.html doesn’t exist, send a list
* of files in the directory with links to each.
* 4) Send a 404 Not Found response.

void handle_files_request(int fd) {
struct http_request *request = http_request_parse(fd);

if(request == NULL) goto EXIT;

char *full_path = join_path(server_files_directory, request->path, NULL);
/* printf(“%s\n %s\n %s\n”, server_files_directory, request->path, full_path); */

struct stat sb;
stat(full_path, &sb);
if (S_ISDIR(sb.st_mode)) {

DIR *dirp;
struct dirent *dp;
dirp = opendir(full_path);
while((dp = readdir(dirp))!=NULL) {
if(strcmp(dp->d_name, “index.html”)==0) {
char *filename = join_path(full_path, “/index.html”, NULL);
reply_with_file(fd, filename, 200);
free(filename);
free(full_path);
closedir(dirp);
goto EXIT;
closedir(dirp);

char *template = “

%s

“;
size_t template_len = strlen(template), parent_path_len = strlen(request->path);
char *temp = NULL, *saved, *send_buffer = (char *)malloc(1);
send_buffer[0] = ‘\0’;
dirp = opendir(full_path);
char *display_name, *url;
while((dp = readdir(dirp))!=NULL) {
if(!strcmp(dp->d_name, “.”)) continue;
else if(!strcmp(dp->d_name, “..”)) {
display_name = “Parent Directory”;
url = get_parent_name(request->path);
display_name = dp->d_name;
url = join_path(request->path, dp->d_name, NULL);
temp = (char *) malloc(template_len + parent_path_len + 2*dp->d_reclen);
sprintf(temp, template, url, display_name);
saved = send_buffer;
send_buffer = join_string(send_buffer, temp, NULL);
free(saved);
free(temp);
free(url);
saved = send_buffer;
size_t content_len;
send_buffer = join_string(send_buffer, “

“, &content_len);
free(saved);

http_start_response(fd, 200);
http_send_header(fd, “Content-Type”, “text/html”);
dprintf(fd, “Content-Length: %lu\r\n”, content_len);
http_end_headers(fd);

http_send_string(fd, send_buffer);
closedir(dirp);
free(send_buffer);
if (access(full_path, F_OK) == -1) {
reply_with_file(fd, “./404.html”, 404);
goto EXIT;

reply_with_file(fd, full_path, 200);
EXIT: close(fd);

void file_request_handler(int req_fd) {
printf(“Process %d, thread %lu will handle request.\n”, getpid(), pthread_self());
handle_files_request(req_fd);

* Opens a connection to the proxy target (hostname=server_proxy_hostname and
* port=server_proxy_port) and relays traffic to/from the stream fd and the
* proxy target. HTTP requests from the client (fd) should be sent to the
* proxy target, and HTTP responses from the proxy target should be sent to
* the client (fd).
* +——–+ +————+ +————–+
* | client | <-> | httpserver | <-> | proxy target |
* +——–+ +————+ +————–+
/* create a socket connected to remote server */
int connect_to_host(char *hostname, int port) {
int fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror(“Failed to create a new socket”);
exit(errno);

/* get ip address of hostname */
struct hostent* ent = gethostbyname(hostname);
if(ent == NULL || ent->h_addr_list == NULL) {
perror(“Failed to get host ip”);
exit(errno);
struct in_addr** addr = (struct in_addr**)ent->h_addr_list;

struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr= *addr[0];
server_addr.sin_port = htons(port);

if((connect(fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)))!=0) {
perror(“Failed to connect server”);
exit(errno);

return fd;

struct fd_pair {
int *read_fd;
int *write_fd;
char* type;
unsigned long id;

void* relay_message(void* endpoints) {
struct fd_pair* pair = (struct fd_pair*)endpoints;

char buffer[4096];
int read_ret, write_ret;
// printf(“%s thread %lu start to work\n”, pair->type, pair->id);
while((read_ret=read(*pair->read_fd, buffer, sizeof(buffer)-1))>0) {
write_ret = http_send_data(*pair->write_fd, buffer, read_ret);
if(write_ret<0) break; printf("%s thread %lu exited\n", pair->type, pair->id);
return NULL;

static unsigned long id;
pthread_mutex_t id_mutex = PTHREAD_MUTEX_INITIALIZER;

void proxy_request_handler(int req_fd) {
unsigned long local_id;

int target_fd = connect_to_host(server_proxy_hostname, server_proxy_port);

pthread_mutex_lock(&id_mutex);
local_id = id++;
pthread_mutex_unlock(&id_mutex);

printf(“Thread %lu will handle proxy request %lu.\n”, pthread_self(), local_id);

struct fd_pair pairs[2];
pairs[0].read_fd = &req_fd;
pairs[0].write_fd = &target_fd;
pairs[0].type = “request”;
pairs[0].id = local_id;

pairs[1].read_fd = &target_fd;
pairs[1].write_fd = &req_fd;
pairs[1].type = “response”;
pairs[1].id = local_id;

pthread_t threads[2];
pthread_create(threads, NULL, relay_message, pairs);
pthread_create(threads+1, NULL, relay_message, pairs+1);
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);

close(req_fd);
close(target_fd);
printf(“Socket closed, proxy request %lu finished.\n\n”, local_id);

/* create a server socket so that we can accept client connections */
int create_server_socket(int port) {
struct sockaddr_in server_address;
int socket_number = socket(PF_INET, SOCK_STREAM, 0);
if (socket_number == -1) {
perror(“Failed to create a new socket”);
exit(errno);

int socket_option = 1;
if (setsockopt(socket_number, SOL_SOCKET, SO_REUSEADDR, &socket_option,
sizeof(socket_option)) == -1) {
perror(“Failed to set socket options”);
exit(errno);

memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(port);

if (bind(socket_number, (struct sockaddr *) &server_address,
sizeof(server_address)) == -1) {
perror(“Failed to bind on socket”);
exit(errno);
return socket_number;

* Opens a TCP stream socket on all interfaces with port number PORTNO. Saves
* the fd number of the server socket in *socket_number. For each accepted
* connection, calls request_handler with the accepted fd number.
void serve_forever(int *socket_number, void (*request_handler)(int)) {
struct sockaddr_in client_address;
size_t client_address_length = sizeof(client_address);
int client_socket_number;

*socket_number = create_server_socket(server_port);
if (listen(*socket_number, 1024) == -1) {
perror(“Failed to listen on socket”);
exit(errno);

printf(“Listening on port %d…\n”, server_port);

while (1) {
client_socket_number = accept(*socket_number,
(struct sockaddr *) &client_address,
(socklen_t *) &client_address_length);
if (client_socket_number < 0) { perror("Error accepting socket"); printf("Accepted connection from %s on port %d\n", inet_ntoa(client_address.sin_addr), client_address.sin_port); async_run(request_handler,client_socket_number); shutdown(*socket_number, SHUT_RDWR); close(*socket_number); int server_fd; void signal_callback_handler(int signum) { printf("Caught signal %d: %s\n", signum, strsignal(signum)); printf("Closing socket %d\n", server_fd); if (close(server_fd) < 0) perror("Failed to close server_fd (ignoring)\n"); char *USAGE = "Usage: ./httpserver --files files/ --port 8000 [--num-threads 5]\n" " ./httpserver --proxy inst.eecs.berkeley.edu:80 --port 8000 [--num-threads 5]\n"; void exit_with_usage() { fprintf(stderr, "%s", USAGE); exit(EXIT_SUCCESS); int main(int argc, char **argv) { signal(SIGINT, signal_callback_handler); signal(SIGPIPE, SIG_IGN); /* Default settings */ server_port = 8000; num_threads = 10; void (*request_handler)(int) = NULL; for (i = 1; i < argc; i++) { if (strcmp("--files", argv[i]) == 0) { server_files_directory = argv[++i]; if (!server_files_directory) { fprintf(stderr, "Expected argument after --files\n"); exit_with_usage(); } else if (strcmp("--proxy", argv[i]) == 0) { char *proxy_target = argv[++i]; if (!proxy_target) { fprintf(stderr, "Expected argument after --proxy\n"); exit_with_usage(); char *colon_pointer = strchr(proxy_target, ':'); if (colon_pointer != NULL) { *colon_pointer = '\0'; server_proxy_hostname = proxy_target; server_proxy_port = atoi(colon_pointer + 1); server_proxy_hostname = proxy_target; server_proxy_port = 80; } else if (strcmp("--port", argv[i]) == 0) { char *server_port_string = argv[++i]; if (!server_port_string) { fprintf(stderr, "Expected argument after --port\n"); exit_with_usage(); server_port = atoi(server_port_string); } else if (strcmp("--num-threads", argv[i]) == 0) { char *num_threads_str = argv[++i]; if (!num_threads_str || (num_threads = atoi(num_threads_str)) < 1) { fprintf(stderr, "Expected positive integer after --num-threads\n"); exit_with_usage(); } else if (strcmp("--help", argv[i]) == 0) { exit_with_usage(); fprintf(stderr, "Unrecognized option: %s\n", argv[i]); exit_with_usage(); if (server_files_directory == NULL && server_proxy_hostname == NULL) { fprintf(stderr, "Please specify either \"--files [DIRECTORY]\" or \n" " \"--proxy [HOSTNAME:PORT]\"\n"); exit_with_usage(); } else if(server_files_directory != NULL){ request_handler = file_request_handler; } else if(server_proxy_hostname != NULL) { request_handler = proxy_request_handler; async_init(num_threads); serve_forever(&server_fd, request_handler); return EXIT_SUCCESS; 程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com