diff --git a/client/http_client.c b/client/http_client.c index 433ca73..921c387 100644 --- a/client/http_client.c +++ b/client/http_client.c @@ -33,14 +33,18 @@ int main(int argc, char* argv[]) { get_parts(dest, path_buffer, host_buffer); printf("%s\n%s\n", path_buffer, host_buffer); struct http_message req = build_basic_request("GET", host_buffer, path_buffer, port_num); - char * req_result = send_request(req); - if (req_result == NULL) { + struct response_info res; + enum socket_read_result read_result = send_request(req, &res); + if (read_result != RESULT_OK) { printf("An error occured while opening the socket. Please try again.\n"); } else { - printf("%s\n", req_result); + if (print_rtt) { + printf("RTT: %lld ms\n\n", res.rtt); + } + printf("%s\n", res.contents); } free_basic_request(req); - free(req_result); + free(res.contents); free(host_buffer); free(path_buffer); } diff --git a/client/http_socket.c b/client/http_socket.c index f97420c..e4dba8a 100644 --- a/client/http_socket.c +++ b/client/http_socket.c @@ -7,6 +7,7 @@ #include #include #include +#include #include /** @@ -101,31 +102,46 @@ static int get_addr_info(const char *hostname, int port, struct addrinfo **info) * Send a given HTTP request * * @param req The HTTP request to send + * @param res_info A pointer to an already allocated response_info. res_info.contents must be freed by the caller. * - * @return The data returned from the socket - must be freed by caller. + * @return A socket_read_result representing the status of the response. */ -char *send_request(struct http_message req) { +enum socket_read_result send_request(struct http_message req, struct response_info *res_info) { struct addrinfo *addr_info; int addr_status = get_addr_info(req.address, req.port, &addr_info); if (addr_status != 0) { - return NULL; + return RESULT_READ_ERROR; } int socket_fd = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol); if (socket_fd < 0) { - return NULL; + return RESULT_READ_ERROR; } int connection_status = connect(socket_fd, addr_info->ai_addr, addr_info->ai_addrlen); if (connection_status != 0) { - return NULL; + return RESULT_READ_ERROR; } send(socket_fd, req.contents, strlen(req.contents), 0); struct http_message res; memset(&res, 0, sizeof(struct http_message)); + struct timeval req_time; + int start_time_result = gettimeofday(&req_time, NULL); + if (start_time_result != 0) { + return RESULT_PROCESSING_ERROR; + } enum socket_read_result result = get_all_remote_parts(socket_fd, &res); + struct timeval res_time; + int end_time_result = gettimeofday(&res_time, NULL); + if (end_time_result != 0) { + return RESULT_PROCESSING_ERROR; + } + long long start_time = req_time.tv_sec + req_time.tv_usec/1000; + long long end_time = res_time.tv_sec + res_time.tv_usec/1000; + res_info->rtt = end_time - start_time; + res_info->contents = res.contents; close(socket_fd); - return res.contents; + return result; } diff --git a/client/http_socket.h b/client/http_socket.h index 56867d2..634a4b5 100644 --- a/client/http_socket.h +++ b/client/http_socket.h @@ -2,13 +2,20 @@ #define HTTP_SOCKET_H #include "../common/http_types.h" +#include "../common/socket_helper.h" +#include #define HTTP_VERSION "HTTP/1.1" #define MIN_PORT 1 #define MAX_PORT 65535 +struct response_info { + char *contents; + long long rtt; +}; + struct http_message build_basic_request(const char *method, const char *host, const char *path, int port); void free_basic_request(struct http_message req); -char *send_request(struct http_message req); +enum socket_read_result send_request(struct http_message req, struct response_info *res_info); #endif diff --git a/common/socket_helper.h b/common/socket_helper.h index b2c162c..a5daa05 100644 --- a/common/socket_helper.h +++ b/common/socket_helper.h @@ -9,7 +9,7 @@ #define ENCODING_TYPE_CHUNKED "chunked" enum line_type {RESULT_START_LINE, RESULT_HEADER, RESULT_BLANK_LINE, RESULT_NO_LINE}; -enum socket_read_result {RESULT_OK, RESULT_MALFORMED, RESULT_READ_ERROR}; +enum socket_read_result {RESULT_OK, RESULT_MALFORMED, RESULT_READ_ERROR, RESULT_PROCESSING_ERROR}; enum socket_read_strategy {STRATEGY_CHUNKED, STRATEGY_CONTENT_LENGTH, STRATEGY_EOF}; struct line_read_result { enum line_type line_type;