YAIP/src/response.c
Jonathan Hodgson 6eaad263be Moves some logic out of proxy and into main
Also fixes some segfaults caused by trying to free memory that wasn't
allocated with strdup or malloc etc.

Fixes some tests
2022-01-19 12:56:11 +00:00

130 lines
3.5 KiB
C

#include "response.h"
Response* newResponse(){
Response *response = malloc( sizeof( Response ) );
memset(response, 0, sizeof(Response));
response->headers = NULL;
response->statusMessage = NULL;
response->body = NULL;
return response;
}
void responseBarebones(Response *rsp){
rsp->headers = malloc( sizeof( HeaderList ) );
rsp->headers->header = newHeader("Content-Length: 0");
rsp->headers->next = NULL;
addHeader(rsp->headers, "Content-Type: text/plain");
rsp->statusCode = 200;
rsp->statusMessage = strdup("OK");
rsp->version = 1.1;
}
void connectionEstablished(Response *rsp){
rsp->statusCode = 200;
rsp->statusMessage = strdup("Connection Established");
rsp->version = 1.1;
}
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;
if ( rsp->body != NULL ) fullLength += strlen(rsp->body) + 2;
char retString[fullLength];
sprintf(retString, "HTTP/%.1f %3d %s\r\n%s\r\n", rsp->version, rsp->statusCode,
rsp->statusMessage,headersToString(rsp->headers));
if ( rsp->body != NULL ) sprintf(retString + strlen(retString), "%s\r\n", (char *)rsp->body);
return strdup(retString);
}
void responseSetBody(Response *rsp, char *string, bool updateContentLength){
rsp->body = strdup(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);
}
}
void responseAddHeader(Response *rsp, char header[]){
if ( rsp->headers == NULL ){
rsp->headers = malloc(sizeof( HeaderList ));
rsp->headers->header = newHeader( header );
rsp->headers->next = NULL;
} else
addHeader( rsp->headers, header );
}
void responseFirstLine( Response *rsp, char line[] ){
// HTTP/1.1 200 OK
float version = 0;
int statusCode = 0;
char statusMessage[256] = {'\0'};
sscanf( line, "HTTP/%f %i %255[^\n]", &version, &statusCode, statusMessage );
rsp->version = version;
rsp->statusCode = statusCode;
rsp->statusMessage = strdup(statusMessage);
}
Response* newResponseFromSocket(int socket){
Response *rsp = newResponse();
int valread;
char line[1024] = {0};
Header *contentLength = NULL;
unsigned int bodySize = 0, bodyRead = 0;
valread = fdReadLine( socket, line, 1024);
responseFirstLine(rsp, line);
//a length of 2 will indicate an empty line which will split the headers
//from the body (if there is a body)
valread = fdReadLine( socket, line, 1024);
while ( valread > 2 ){
responseAddHeader( rsp, line );
valread = fdReadLine( socket , line, 1024);
}
//I believe at this point all the headers are done.
contentLength = getHeader( rsp->headers, "content-length" );
if ( contentLength != NULL ){
bodySize = atoi( contentLength->value );
if (bodySize > 0){
//When the body is not binary data, it is useful to treat it as a
//string. For this reason, I want the bite immediately after it to
//be \0
rsp->body = malloc( bodySize + 1 );
memset( rsp->body + bodySize + 1, '\0', 1 );
while ( bodyRead < bodySize ){
valread=read( socket, rsp->body + bodyRead, bodySize - bodyRead );
if (valread < 0){
perror("Unable to read");
return NULL;
}
bodyRead += valread;
}
}
}
return rsp;
}
void freeResponse( Response *rsp ){
free(rsp->statusMessage);
freeHeaderList( rsp->headers );
free(rsp->body);
free(rsp);
}