Code:
#include <fstream>
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <cstring>
using namespace std;
string resolveToIPAddress(string, string);
int getPortNum(string);
string getUrlPath(string);
string getDomain(string);
string getDomainWithFile(string);
string getUrlWithNoPort(string);
string getFileFromURL(string);
bool hasHTTPProtocol(string);
bool hasPortNum(string);
bool checkIfValidIPAddress(string);
int main(int argc, char **argv)
{
//Create a file to be opened for output
ofstream out_file;
out_file.open("output.txt", ios::out);
int connection_port = 0, send_req, recv_req;
string ip_addr = "", domain = "", ipFromDomain = "", file_to_get = "";
ip_addr = argv[1]; //point ip address argument to the 2nd indice in the arguments
//if there is a port number, Get port number (extract it from URL)
if (hasPortNum(ip_addr)) {
connection_port = getPortNum(ip_addr);
domain = getDomain(ip_addr);
}
//if there is no port number, set default port number = 80 and set domain to truncated ip address
else {
connection_port = 80;
domain = getDomain(ip_addr);
}
file_to_get = getFileFromURL(ip_addr);
cout << "Domain: " << domain << endl;
cout << "Port Number: " << connection_port << endl;
cout << "File requested: " << file_to_get << endl;
//resolve domain to ipAddress
ipFromDomain = resolveToIPAddress(domain, to_string(connection_port));
//Connect to iP Address with port and return metadata
//Create the socket
int http_client_socket = socket(AF_INET, SOCK_STREAM, 0);
// connect address and contain socket
struct sockaddr_in connection_addr;
connection_addr.sin_family = AF_INET; //set the addressfamily type to INET
connection_addr.sin_port = htons(connection_port); //set socket to parsed port number
cout << "ip address: " << ipFromDomain << endl; //checking to see if ip address is well converted
inet_aton(ipFromDomain.c_str(), &connection_addr.sin_addr); //convert ip address from IPV4 notation string and store it into structure
//Connect to server address
if (connect
(http_client_socket, (struct sockaddr *) &connection_addr,
sizeof(connection_addr)) != 0) {
cout << "Connection with the server failed..." << endl;
exit(0);
}
//Logic for HTTP GET Request
string http_request = "GET /" + file_to_get + " HTTP/1.1\r\n\r\n";
cout << http_request << endl;
//string http_response;
string http_response;
send(http_client_socket, http_request.c_str(), sizeof(http_request), 0);
recv(http_client_socket, &http_response, 999999999, 0);
out_file << http_response << endl;
//close the file
out_file.close();
//close the socket
close(http_client_socket);
return 0;
}
string getUrlWithNoPort(string url)
{
if (hasHTTPProtocol(url))
return url.substr(7, url.length() - 7);
return url;
}
//Get URL without port and path
string getDomain(string url)
{
string urlWithoutPortandPath = "";
int i = 0;
//Check if full URL has a protocol
if (hasHTTPProtocol(url)) {
//if it has a protocol truncate the protocol from FQDN
i = 7;
while (url != '/') {
//for (int i = 7; i < url.length(); i++) {
if (url == ':') {
break;
}
urlWithoutPortandPath += url;
i++;
//}
}
return urlWithoutPortandPath;
}
//if it does not have a protocol remove port number and path
while (url != '/') {
//for (int i = 0; i < url.length(); i++) {
if (url == ':') {
break;
}
urlWithoutPortandPath += url;
i++;
}
return urlWithoutPortandPath;
}
string getDomainWithFile(string url)
{
string urlWithoutPortandPath = "";
//Check if full URL has a protocol
if (hasHTTPProtocol(url)) {
//if it has a protocol truncate the protocol from FQDN
for (int i = 7; i < url.length(); i++) {
if (url == ':') {
break;
}
urlWithoutPortandPath += url;
}
return urlWithoutPortandPath;
}
//if it does not have a protocol remove port number and path
for (int i = 0; i < url.length(); i++) {
if (url == ':') {
break;
}
urlWithoutPortandPath += url;
}
return urlWithoutPortandPath;
}
bool hasHTTPProtocol(string url)
{
string httpProtocol = url.substr(0, 7);
if (httpProtocol == "http://")
return true;
return false;
}
int getPortNum(string url)
{
string port = "";
int portNum, portIdx = 0, pathIdx = 0, portEndIdx = 0;
if (hasHTTPProtocol(url)) {
for (int i = 7; i < url.length(); i++) {
if (url == ':')
portIdx = i + 1;
}
}
string fromPortToPath = url.substr(portIdx, url.length() - portIdx);
cout << "Port to Path: " << fromPortToPath << endl;
for (int i = 0; i < fromPortToPath.length(); i++) {
if (fromPortToPath == '/') {
pathIdx = i + 1;
portEndIdx = i;
break;
}
}
port = fromPortToPath.substr(0, portEndIdx);
portNum = stoi(port);
return portNum;
}
string getUrlPath(string url)
{
string urlPath = "";
int pathIdx = 0, portIdx = 0, portEndIdx = 0;
if (hasHTTPProtocol(url)) {
for (int i = 7; i < url.length(); i++) {
if (url == ':')
portIdx = i + 1;
}
}
string fromPortToPath = url.substr(portIdx, url.length() - portIdx);
cout << "Port to Path: " << fromPortToPath << endl;
for (int i = 0; i < fromPortToPath.length(); i++) {
if (fromPortToPath == '/') {
pathIdx = i + 1;
portEndIdx = i;
break;
}
}
urlPath =
fromPortToPath.substr(portEndIdx + 1, fromPortToPath.length() - pathIdx);
return urlPath;
}
bool hasPortNum(string url)
{
if (hasHTTPProtocol(url)) {
for (int i = 7; i < url.length(); i++) {
if (url == ':')
return true;
}
} else {
for (int i = 0; i < url.length(); i++) {
if (url == ':')
return true;
}
}
return false;
}
//Resolves a string hostname e.g. google.com into an ipaddress (practically a DNS function)
string resolveToIPAddress(string urlString, string portNum)
{
struct addrinfo hints, *results;
struct addrinfo *result;
int error, sock_id;
string numericalIPS[100];
//set all bits in hints to zero
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((error =
getaddrinfo(urlString.c_str(), portNum.c_str(), &hints,
&results)) != 0) {
cout << "error " << error << ":" << gai_strerror(error) << endl;
}
int i = 0;
//loop through results
for (result = results; result != nullptr; result = result->ai_next) {
struct sockaddr_in *ip_addr;
ip_addr = (struct sockaddr_in *) result->ai_addr;
numericalIPS = inet_ntoa(ip_addr->sin_addr);
i++;
}
return numericalIPS[0];
}
string getFileFromURL(string url)
{
int idxToFile;
string file_request;
string path_to_file = getDomainWithFile(url);
for (int i = 0; i < path_to_file.length(); i++) {
if (path_to_file == '/') {
idxToFile = i + 1;
}
}
file_request =
path_to_file.substr(idxToFile, path_to_file.length() - idxToFile);
return file_request;
}
I took the following measures to debug the application: