Commit 6890940f authored by Matthew Burket's avatar Matthew Burket

Good part of the server done

parent e3b30759
Pipeline #337 passed with stage
in 15 seconds
coms352_project2_part2
\ No newline at end of file
......@@ -3,4 +3,4 @@ project(coms352_project2_part2 C)
set(CMAKE_C_STANDARD 11)
add_executable(coms352_project2_part2 main.c)
\ No newline at end of file
add_executable(coms352_project2_part2 main.c http.c http.h utils.c utils.h buffer.c buffer.h)
\ No newline at end of file
//
// Created by mburket on 4/7/18.
//
#include "buffer.h"
#include "string.h"
/// Initalize the buffer
///
/// \param arr pointer to the array struct
/// \param initSize inital size of the buffer
void initBuffer(GrowthBuffer *arr, size_t initSize) {
arr->array = (char *) malloc(sizeof(char) * initSize);
arr->total_size = initSize;
arr->used = 0;
for (int i = 0; i < initSize; i++) {
arr->array[i]= '\0';
}
}
/// Appends to the buffer
///
/// \param arr buffer to append to
/// \param value value to append
/// \param length length to append
/// \return 0 if sucesss
int appendBuffer(GrowthBuffer *arr, char *value, int length) {
int dLength = length + 1;
// Grow Array if not big enough
if (!hasSpaceBuffer(arr, dLength)) {
int growthFactor = arr->total_size;
if (growthFactor < dLength) {
growthFactor = dLength;
}
// Double the size
int arrNewSize = growthFactor * 2;
// realloc the array
char *newArr = realloc(arr->array, arrNewSize * sizeof(char));
for (int i = arr->total_size + 1; i < arrNewSize; i++) {
arr->array[i]= '\0';
}
// Set the new array
arr->array = newArr;
// Set the new total size
arr->total_size = arrNewSize;
}
// Position in the array
int buffPos;
// Count of the number bytes we have written
int copiedBytesCount = 0;
for (int i = 0; i < length; i++) {
// Don't write a null byte to the buffer
if (value[i] == '\0') {
break;
}
// The place to write the write to the buffer is arr->used + i
buffPos = arr->used + i;
// Set arr->array + buffPos to the value of given string at i
*(arr->array + buffPos) = value[i];
// Copied a byte, so increase counter
copiedBytesCount++;
}
// Update the used counter
arr->used += copiedBytesCount;
}
/// Free the memory used by the buffer
///
/// \param arr buffer to free
void freeBuffer(GrowthBuffer *arr) {
free(arr->array);
arr->array = NULL;
arr->used = arr->total_size = 0;
}
/// Checks if the array has space for the given length
///
/// \param arr
/// \param length
/// \return
int hasSpaceBuffer(GrowthBuffer *arr, int length) {
size_t unused = arr->total_size - arr->used;
return length <= unused;
}
\ No newline at end of file
//
// Created by mburket on 4/11/18.
//
#ifndef COMS352_PROJECT2_PART2_BUFFER_H
#define COMS352_PROJECT2_PART2_BUFFER_H
#include "stdlib.h"
typedef struct {
char *array;
size_t used;
size_t total_size;
} GrowthBuffer;
void initBuffer(GrowthBuffer *arr, size_t initSize);
int appendBuffer(GrowthBuffer *arr, char *value, int length);
void freeBuffer(GrowthBuffer *arr);
int hasSpaceBuffer(GrowthBuffer *arr, int length);
#endif //COMS352_PROJECT2_PART2_BUFFER_H
//
// Created by mburket on 4/11/18.
//
#include <stdio.h>
#include "http.h"
#include "utils.h"
/// Gets the HTTP verb from the
/// \param string
/// \return
HTTP_VERB get_http_verb(char *request) {
if (startsWith(request, "HEAD")) {
return HTTP_HEAD;
} else if (startsWith(request, "GET")) {
return HTTP_GET;
} else {
return HTTP_UNKNOWN;
}
}
/// Get the path from the request
/// \param request
/// \param path
void get_http_path(char *request, char *path) {
char verb[50];
sscanf(request, "%49[^ ] /%1022[^ ]", verb, path);
fprintf(stdout, "\nVerb: %s, Path: %s\n", verb, path);
}
///
/// \param header
/// \return
int parseHeader(char *header) {
}
//
// Created by mburket on 4/11/18.
//
#ifndef COMS352_PROJECT2_PART2_HTTP_H
#define COMS352_PROJECT2_PART2_HTTP_H
typedef enum {
HTTP_GET,
HTTP_HEAD,
HTTP_UNKNOWN
} HTTP_VERB;
HTTP_VERB get_http_verb(char *request);
void get_http_path(char *request, char *path);
#endif //COMS352_PROJECT2_PART2_HTTP_H
......@@ -13,30 +13,48 @@
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <poll.h>
#include "buffer.h"
#include "http.h"
#define PORT 26884
#define DEBUG 1
#define DEBUG 0
#define TRUE 1
int bind_socket();
int accept_connection(int socketfd);
int handle_client(int clientfd);
void getRequest(int clientfd, GrowthBuffer *request);
int checkFile(char *fileName);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
int main() {
int firstRun = TRUE;
fprintf(stdout, "Burket HTTP Server Starting...\n");
int socketfd = bind_socket();
int clientfd ;
int clientfd;
while (TRUE) {
if (firstRun == TRUE) {
firstRun = 0;
fprintf(stdout, "Accepting connections on port %d\n", PORT);
}
clientfd = accept_connection(socketfd);
if (clientfd == -1) {
fprintf(stderr, "Unable to accept client Error: %d", errno);
fprintf(stderr, "\nUnable to accept client Error: %d\n", errno);
fprintf(stderr, "Error: %s", strerror(errno));
} else {
handle_client(clientfd);
}
}
}
#pragma clang diagnostic pop
/// This creates and binds the socket
......@@ -45,17 +63,22 @@ int main() {
int bind_socket() {
int socketfd;
errno = 0;
socketfd = socket(AF_UNSPEC, SOCK_STREAM, 0);
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (errno != 0) {
fprintf(stderr, "\nUnable to create socket.\n");
fprintf(stderr, strerror(errno));
fprintf(stderr, "\n");
}
struct sockaddr_in addr;
addr.sin_family = AF_UNSPEC;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
errno = 0;
bind(socketfd, (struct sockaddr *) &addr, sizeof(addr));
if (errno != 0) {
fprintf(stderr, "Unable to bind: [Error %d]: %s", errno, strerror(errno));
exit(EXIT_FAILURE);
}
listen(socketfd, 2048);
return socketfd;
}
......@@ -79,10 +102,61 @@ int accept_connection(int socketfd) {
/// \return
int handle_client(int clientfd) {
int pid = fork();
if (fork() == 0) {
if (pid == 0) {
GrowthBuffer request;
getRequest(clientfd, &request);
HTTP_VERB verb = get_http_verb(request.array);
if (verb == HTTP_UNKNOWN) {
char *basicHeader = "HTTP/1.1 400 Bad Request\r\n\r\n";
write(clientfd, basicHeader, strlen(basicHeader));
shutdown(clientfd, SHUT_RDWR);
exit(EXIT_SUCCESS);
}
char *path = malloc(sizeof(char) * 1024);
get_http_path(request.array, path);
fprintf(stdout, "Verb:%d Path:%s\n", verb, path);
GrowthBuffer response;
initBuffer(&response, 500);
if (checkFile(path) != -1) {
char *basicHeader = "HTTP/1.1 200 OK\r\n\r\n";
appendBuffer(&response, basicHeader, strlen(basicHeader));
} else {
char *basicHeader = "HTTP/1.1 404 Not Found\r\n\r\n";
appendBuffer(&response, basicHeader, strlen(basicHeader));
}
fprintf(stdout, response.array);
write(clientfd, response.array, strlen(response.array));
shutdown(clientfd, SHUT_RDWR);
free(path);
freeBuffer(&request);
exit(EXIT_SUCCESS);
}
#ifdef DEBUG
#ifdef DEBUG
fprintf(stdout, "\nProcessing client on pid %d\n", pid);
#endif
#endif
}
void getRequest(int clientfd, GrowthBuffer *request) {
struct pollfd pollfd = {
.fd = clientfd,
.events = POLLIN
};
ssize_t readCount;
initBuffer(request, 500);
char *buff = malloc(1024);
poll(&pollfd, 1, 0);
while (pollfd.revents & POLLIN) {
readCount = read(clientfd, buff, 1024);
appendBuffer(request, buff, readCount);
if (readCount <= 0) {
break;
}
poll(&pollfd, 1, 0);
}
}
int checkFile(char *fileName) {
return access(fileName, R_OK);
}
\ No newline at end of file
//
// Created by mburket on 4/11/18.
//
#include "utils.h"
#include "string.h"
/// Checks if starts with startString
/// \param s string to check
/// \param startString
/// \return 1 if s starts with startString, otherwise 1
int startsWith(char *s, char *startString) {
return strncmp(startString, s, strlen(s));
}
\ No newline at end of file
//
// Created by mburket on 4/11/18.
//
#ifndef COMS352_PROJECT2_PART2_UTILS_H
#define COMS352_PROJECT2_PART2_UTILS_H
int startsWith(char *s, char *startString);
#endif //COMS352_PROJECT2_PART2_UTILS_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment