Split out some stuff that is shared between request and response

I now have files with the infinitely imaginative names
requestrespons.{c,h,test.c}.
This commit is contained in:
Jonathan Hodgson 2022-01-10 09:36:18 +00:00
parent 0e2b9dae2b
commit 48e3092317
9 changed files with 533 additions and 70 deletions

View file

@ -1,45 +1,5 @@
#include "request.h"
Header* newHeader(char *str){
Header *header = malloc(sizeof(Header));
memset(header, 0, sizeof(Header));
int position = -1;
for ( unsigned int i = 0; i < strlen(str); i++ ){
if ( str[i] == ':' ){
position = i;
break;
}
}
if ( position == -1 ){
printf("Header without colon. Not sure what to do\n");
return NULL;
}
// We want to allocate 1 more than the length so we can have a \0 at the end
header->name = malloc( sizeof(char) * ( position + 1 ) );
memset(header->name, '\0', position+1);
strncpy( header->name, str, position );
for ( unsigned int i = position+1; i < strlen(str); i++ ){
if ( str[i] == '\t' || str[i] == ' ' ) continue;
position = i;
break;
}
//Anything left is the value
header->value = malloc( sizeof(char) * ( strlen(str) - position ) );
memset(header->value, '\0', ( strlen(str) - position ) );
strcpy( header->value, str + position );
return header;
}
Request* newRequest(){
Request *request = malloc(sizeof(Request));
@ -101,18 +61,15 @@ Request* newRequestFromSocket(int socket){
int valread;
char line[1024] = {0};
// The first line will give us some important information
//valread = fdReadLine( socket, line, 1024);
char hello[] = "this is a test";
valread = fdReadLine( socket, line, 1024);
printf("HERE\nLine is %s\n", line);
requestFirstLine(req, line);
//a length of 2 will indicate an empty line which will split the headers
//from the body (if there is a body)
while ( valread > 2 ){
printf("%s",line );
//valread = fdReadLine( socket , line, 1024);
}
send(socket , "this is a test" , 15 , 0 );
printf("Hello message sent\n");
//while ( valread > 2 ){
// printf("%s",line );
// //valread = fdReadLine( socket , line, 1024);
//}
return req;
}

View file

@ -4,27 +4,11 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "readline.h"
#include <netinet/in.h>
#include "readline.h"
#include "requestresponse.h"
/*
* A struct reperesenting an http header
*/
typedef struct {
char *name;
// The spec doesn't specify a max size for headers, but nginx doesn't accept headers bigger than 4096 so that's probably ok for us
char *value;
} Header;
/*
* A linked list wrapper around the headers
*/
typedef struct HeaderList HeaderList;
struct HeaderList {
Header header;
HeaderList *next;
};
/*
* A struct reperesenting an http request
@ -41,12 +25,10 @@ typedef struct {
char *body;
} Request;
Header* newHeader();
Request* newRequest();
void requestFirstLine( Request *req, char line[] );
Request* newRequestFromSocket(int socket);
void* addHeader(Request *req, char line[]);
void* interpretLine1(Request *req, char line[]);
//void* requestAddHeader(Request *req, char line[]);

106
src/requestresponse.c Normal file
View file

@ -0,0 +1,106 @@
#include "requestresponse.h"
Header* newHeader(char *str){
Header *header = malloc(sizeof(Header));
memset(header, 0, sizeof(Header));
int position = -1;
for ( unsigned int i = 0; i < strlen(str); i++ ){
if ( str[i] == ':' ){
position = i;
break;
}
}
if ( position == -1 ){
printf("Header without colon. Not sure what to do\n");
return NULL;
}
// We want to allocate 1 more than the length so we can have a \0 at the end
header->name = malloc( sizeof(char) * ( position + 1 ) );
memset(header->name, '\0', position+1);
strncpy( header->name, str, position );
for ( unsigned int i = position+1; i < strlen(str); i++ ){
if ( str[i] == '\t' || str[i] == ' ' ) continue;
position = i;
break;
}
//Anything left is the value
header->value = malloc( sizeof(char) * ( strlen(str) - position ) );
memset(header->value, '\0', ( strlen(str) - position ) );
strcpy( header->value, str + position );
return header;
}
void addHeader(HeaderList *headers, char *str){
HeaderList *newListItem = malloc(sizeof(HeaderList));
newListItem->header = newHeader(str);
newListItem->next = NULL;
HeaderList *last = headers;
while ( last->next != NULL ) last = last->next;
last->next = newListItem;
}
// Will return the first header in a header list with the name matching name
// It matches name case insensitively as header names are case insensitive
Header* getHeader(HeaderList *headers, char *name){
HeaderList *curr = headers;
while ( curr != NULL ){
// Header names are case insensitive
if ( strcasecmp( curr->header->name, name) == 0 ){
return curr->header;
}
curr = curr->next;
}
return NULL;
}
unsigned int countHeaders(HeaderList *headers){
unsigned int count = 0;
while (headers != NULL){
count++;
headers = headers->next;
}
return count;
}
unsigned int headerListCharLength(HeaderList *headers){
unsigned int length = 0;
while (headers != NULL){
// 4 = colon + space + \r + \n
length += strlen(headers->header->name) + strlen(headers->header->value) + 4;
headers = headers->next;
}
return length;
}
char* headersToString(HeaderList *headers){
int len = headerListCharLength(headers) + 1; //null pointer
HeaderList *curr = headers;
char *retStr = malloc( len * sizeof(char) );
memset(retStr, '\0', len * sizeof(char) );
while ( curr != NULL ){
strcat( retStr, curr->header->name );
strcat( retStr, ": " );
strcat( retStr, curr->header->value );
strcat( retStr, "\r\n" );
curr = curr->next;
}
return retStr;
}

46
src/requestresponse.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef REQUESTRESPONSE
#define REQUESTRESPONSE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//This file contains definitions that are shared between requests and responses such as header
/*
* A struct reperesenting an http header
*/
typedef struct {
char *name;
// The spec doesn't specify a max size for headers, but nginx doesn't accept headers bigger than 4096 so that's probably ok for us
char *value;
} Header;
/*
* A linked list wrapper around the headers
*/
typedef struct HeaderList HeaderList;
struct HeaderList {
Header *header;
HeaderList *next;
};
//Creates a new header struct from a string like "Content-Length: 123"
Header* newHeader(char *str);
//Adds a header to the end of a header list
void addHeader(HeaderList *headers, char *str);
Header* getHeader(HeaderList *headers, char *name);
unsigned int countHeaders(HeaderList *headers);
unsigned int headerListCharLength(HeaderList *headers);
char* headersToString(HeaderList *headers);
#endif /* ifndef REQUESTRESPONSE
//THis file contains definitions that are shared between requests and responses such as header
*/

38
src/response.c Normal file
View file

@ -0,0 +1,38 @@
#include "response.h"
Response* newResponse(){
Response *response = malloc( sizeof( Response ) );
memset(response, 0, sizeof(Response));
response->headers = malloc( sizeof( HeaderList ) );
response->headers->header = newHeader("Content-Length: 0");
response->headers->next = NULL;
addHeader(response->headers, "Content-Type: text/plain");
response->statusCode = 200;
response->statusMessage = "OK";
response->version = 1.1;
return response;
}
char* responseToString( Response *rsp ){
// HTTP/x.x xxx OK \r\n
int fullLength = 13 + strlen(rsp->statusMessage) + 2 +
// Headers \r\n\r\n
headerListCharLength(rsp->headers) + 4 + strlen(rsp->body);
char retString[fullLength];
sprintf(retString, "HTTP/%.1f %3d %s\r\n%s\r\n%s", rsp->version, rsp->statusCode,
rsp->statusMessage,headersToString(rsp->headers),rsp->body);
return strdup(retString);
}
void responseSetBody(Response *rsp, char *string, bool updateContentLength){
rsp->body = string;
if ( updateContentLength ){
Header *contentLengthHeader = getHeader(rsp->headers, "content-length");
char *value = malloc(sizeof(char) * 20);
sprintf(value, "%lu", strlen(string) );
contentLengthHeader->value = strdup(value);
}
}

34
src/response.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef RESPONSE_H
#define RESPONSE_H
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "readline.h"
#include "requestresponse.h"
/*
* A struct reperesenting an http request
*/
typedef struct {
// Common versions are: 0.9, 1.0, 1.1, 2.0
float version;
int statusCode;
char *statusMessage;
HeaderList *headers;
char *body;
unsigned int headerLength;
} Response;
Response* newResponse();
char *responseToString(Response *rsp);
void responseSetBody(Response *rsp, char *string, bool updateContentLength);
//void* responseAddHeader(Response *req, char line[]);
#endif /* ifndef REQUEST_H */