Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions week-1/HungerArray/c#/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin/
obj/
data.json
.vscode/
3 changes: 3 additions & 0 deletions week-1/HungerArray/c++/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.o
main
.vscode/
8 changes: 8 additions & 0 deletions week-2/Hungerarray/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.vscode
CMakeFiles
cmake_install.cmake
CMakeCache.txt
main
Makefile
child
outfile
40 changes: 40 additions & 0 deletions week-2/Hungerarray/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.10)

project(fast_Request)

set(
CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Wall"
)

add_library(
objects OBJECT
Connect.cpp Connect.h
Url.h
WebRequestAbstract.h
HttpRequest.cpp HttpRequest.h
HttpsRequest.cpp HttpsRequest.h
)

target_compile_definitions(objects PUBLIC LOG)

add_executable(
child
child.cpp
)

add_executable(
main
main.cpp
)

set_property( TARGET main PROPERTY CXX_STANDARD 17 )
set_property( TARGET child PROPERTY CXX_STANDARD 17)
set_property( TARGET objects PROPERTY CXX_STANDARD 17 )

target_link_libraries(
child
PUBLIC objects
PUBLIC -ldl
PUBLIC -lssl
PUBLIC -lcrypto
)
74 changes: 74 additions & 0 deletions week-2/Hungerarray/Connect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <iostream>
#include <thread>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/io_context.hpp>

#include "Connect.h"
#include "HttpRequest.h"
#include "HttpsRequest.h"

using boost::asio::ip::tcp;

boost::asio::io_context Connect::_io_context;

Connect::Connect(const Url &url)
: _url{url},
_request_header{Create_request_header(url._host, url._path, false)},
_req_persist_header{Create_request_header(url._host, url._path, true)},
_thread_pool{17}
{
}

std::string Connect::Create_request_header(std::string_view host, std::string_view path, bool persistent)
{
std::stringstream ss;
ss << "GET " << path << " HTTP/1.1\r\n"
<< "Host: " << host << "\r\n"
<< "Accept: text/html\r\n"
<< "User-Agent: Mozilla/5.0\r\n";
if (!persistent)
ss << "Connection: close\r\n";

ss << "\r\n";

return ss.str();
}

void Connect::Start(size_t num)
{
// if evenly divisible by 16, then it will create and use 16 sockets, else will create and use 17 sockets
constexpr size_t no_of_sockets = 16;
const size_t req_per_socket = num / no_of_sockets;

size_t i;
for (i = 0; req_per_socket && i < no_of_sockets - 1; ++i)
{
Create_request(i, req_per_socket);
}
size_t lim = num - req_per_socket * (no_of_sockets - 1);
Create_request(i, lim);
}

void Connect::Create_request(size_t socketNo, size_t lim)
{
_webRequests.emplace_back(Create_WebRequest());
// std::cout << "Socket " << socketNo << " starting " << lim << " Requests" << std::endl;
boost::asio::post(_thread_pool, [socketNo, &url = _url, &Req = _req_persist_header, &endReq = _request_header, lim, &web = _webRequests.back()]()
{
web->async_Connect(url).get();
std::string response = web->async_Get_pipeline(Req, endReq, lim).get();
});
}

WebRequest Connect::Create_WebRequest()
{
if (_url._scheme == "http")
return WebRequest{new HttpRequest{_io_context}};
else
return WebRequest{new HttpsRequest{_io_context}};
}

void Connect::Wait()
{
_thread_pool.join();
}
38 changes: 38 additions & 0 deletions week-2/Hungerarray/Connect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <string>
#include <string_view>
#include <list>
#include <boost/asio.hpp>

#include "WebRequestAbstract.h"
#include "Url.h"

class Connect
{
public:
static boost::asio::io_context _io_context;

public:
Connect(const Url &url);

// Start will start asynchronously given no. of connections
void Start(size_t num);

// Wait will wait for all he asynchronous task to end
void Wait();

private:
std::string Create_request_header(std::string_view host, std::string_view path, bool persistent);

WebRequest Create_WebRequest();

void Create_request(size_t socketNo, size_t lim);

private:
Url _url;
std::list<WebRequest> _webRequests;
std::string _request_header;
std::string _req_persist_header;
boost::asio::thread_pool _thread_pool;
};
80 changes: 80 additions & 0 deletions week-2/Hungerarray/HttpRequest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <iostream>
#include <memory>
#include <boost/asio/connect.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
#include <boost/bind.hpp>
#include <boost/asio/placeholders.hpp>

#include "HttpRequest.h"

using namespace boost;
using namespace boost::asio::ip;

HttpRequest::HttpRequest(asio::io_context &io_ctx)
: WebRequestAbstract{io_ctx},
_socket{io_ctx}
{
}

void HttpRequest::Connect(Url &url)
{
auto _endpoints = _resolver.resolve(url._host, url._scheme);
asio::connect(_socket, _endpoints);
_socket.set_option(tcp::no_delay(true));
}

std::future<void> HttpRequest::async_Connect(Url &url)
{
return std::async([this, &url]() -> void
{ Connect(url); });
}

std::string HttpRequest::Get(std::string_view reqHeader)
{
boost::system::error_code ec;
asio::write(_socket, asio::buffer(reqHeader), ec);

if (ec.failed()){
std::cout << "Error on write header: " << ec.message() << std::endl;
return std::string{};
}

std::string temp;
asio::read(_socket, asio::dynamic_buffer(temp), ec);
return temp;
}

std::future<std::string> HttpRequest::async_Get(std::string_view reqHeader)
{
return std::async([this, reqHeader]() -> std::string
{ return Get(reqHeader); });
}

std::string HttpRequest::Get_pipeline(std::string_view reqHeader, std::string_view end_reqHeader, size_t num)
{
boost::system::error_code ec;
for (size_t i = 0; i < num - 1; ++i)
{
asio::write(_socket, asio::buffer(reqHeader), ec);
if(ec.failed())
std::cout << "pipeline failed at: " << i+ 1 << ec.message() << std::endl;
}
asio::write(_socket, asio::buffer(end_reqHeader), ec);

std::string temp;
asio::read(_socket, asio::dynamic_buffer(temp), ec);
return temp;
}

std::future<std::string> HttpRequest::async_Get_pipeline(std::string_view reqHeader, std::string_view end_reqHeader, size_t num)
{
return std::async([this, reqHeader, end_reqHeader, num](){
return Get_pipeline(reqHeader, end_reqHeader, num);
});
}

HttpRequest::~HttpRequest()
{
_socket.close();
}
26 changes: 26 additions & 0 deletions week-2/Hungerarray/HttpRequest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "WebRequestAbstract.h"
#include <boost/asio/io_context.hpp>

class HttpRequest : public WebRequestAbstract
{
public:
HttpRequest(boost::asio::io_context &io_ctx);

void Connect(Url &url) override;
std::future<void> async_Connect(Url &url) override;

std::string Get(std::string_view reqHeader) override;
std::future<std::string> async_Get(std::string_view reqHeader) override;

std::string Get_pipeline(std::string_view reqHeader, std::string_view end_reqHeader, size_t num) override;
std::future<std::string> async_Get_pipeline(std::string_view reqHeader, std::string_view end_reqHeader, size_t num) override;

~HttpRequest() override;

private:
boost::asio::ip::tcp::socket _socket;
std::string _reqHeader;
size_t count = 0;
};
Loading