216 lines
5.4 KiB
C++
216 lines
5.4 KiB
C++
#include <algorithm>
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <thread>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
struct Credentail {
|
|
int cert_;
|
|
};
|
|
|
|
struct Download {
|
|
enum ConnectionType { Telnet,
|
|
Ssh };
|
|
|
|
std::string url_;
|
|
Credentail credentail_;
|
|
int maxMbps_;
|
|
bool cache_;
|
|
ConnectionType type_;
|
|
};
|
|
|
|
struct Upload {
|
|
enum ConnectionType { Telnet,
|
|
Ssh };
|
|
|
|
std::string url_;
|
|
Credentail credentail_;
|
|
int maxMbps_;
|
|
int size_;
|
|
ConnectionType type_;
|
|
};
|
|
|
|
struct RemoveFromCache {
|
|
std::string url_;
|
|
};
|
|
|
|
struct ClearCache {
|
|
};
|
|
|
|
struct Image {
|
|
std::vector<uint8_t> bitmap_;
|
|
};
|
|
|
|
class Server {
|
|
public:
|
|
void handle(const Download& request, void (*callback)(bool, Image)) {
|
|
Image image;
|
|
|
|
for (const auto& pair : cache_) {
|
|
if (pair.second == request.url_) {
|
|
image = pair.first;
|
|
callback(true, image);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (download(request, &image)) {
|
|
if (request.cache_) {
|
|
cache_.push_back(std::pair<Image, std::string>(image, request.url_));
|
|
}
|
|
|
|
callback(true, image);
|
|
return;
|
|
}
|
|
|
|
callback(false, Image{});
|
|
}
|
|
|
|
void handle(const Upload& request, void (*callback)(bool, Image)) {
|
|
if (request.size_ > 100) {
|
|
callback(false, Image{});
|
|
return;
|
|
}
|
|
|
|
Image image;
|
|
bool succes = upload(request, &image);
|
|
|
|
callback(succes, Image{});
|
|
}
|
|
|
|
void handle(const RemoveFromCache& request, void (*callback)(bool, Image)) {
|
|
for (auto it = cache_.begin(); it != cache_.end(); ++it) {
|
|
if (it->second == request.url_) {
|
|
cache_.erase(it);
|
|
callback(true, Image{});
|
|
return;
|
|
}
|
|
}
|
|
|
|
callback(false, Image{});
|
|
}
|
|
|
|
void handle(const ClearCache& request, void (*callback)(bool, Image)) {
|
|
cache_.clear();
|
|
|
|
callback(true, Image{});
|
|
}
|
|
|
|
private:
|
|
bool download(const Download& request, Image* image) {
|
|
if (request.type_ == Download::Ssh && request.credentail_.cert_ != 123) {
|
|
return false;
|
|
}
|
|
if (request.type_ == Download::Telnet && request.credentail_.cert_ != 231) {
|
|
return false;
|
|
}
|
|
|
|
// Simulate some other error
|
|
if (request.maxMbps_ % 2) {
|
|
return false;
|
|
}
|
|
image->bitmap_ = {97, 98, 99, 100, 101, 102};
|
|
return true;
|
|
}
|
|
|
|
bool upload(const Upload& request, const Image* image) {
|
|
if (request.type_ == Upload::Ssh && request.credentail_.cert_ != 1234) {
|
|
return false;
|
|
}
|
|
if (request.type_ == Upload::Telnet && request.credentail_.cert_ != 5432) {
|
|
return false;
|
|
}
|
|
|
|
// Simulate some other error
|
|
if (!request.maxMbps_ % 2) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::vector<std::pair<Image, std::string>> cache_;
|
|
};
|
|
|
|
class RequestHandler {
|
|
public:
|
|
enum RequestType { Download,
|
|
Upload,
|
|
Remove,
|
|
Clear };
|
|
|
|
void start(Server* server) {
|
|
std::thread(&RequestHandler::run, this, server).detach();
|
|
}
|
|
|
|
void stop() {
|
|
stop_ = true;
|
|
}
|
|
|
|
void pushRequest(void* request, RequestType type, void (*callback)(bool, Image)) {
|
|
requests_.push(std::tuple<void*, RequestType, void (*)(bool, Image)>(request, type, callback));
|
|
}
|
|
|
|
private:
|
|
void run(Server* server) {
|
|
while (!stop_) {
|
|
auto tuple = waitForRequest();
|
|
switch (std::get<1>(tuple)) {
|
|
case Download:
|
|
server->handle(*((::Download*)(std::get<0>(tuple))), std::get<2>(tuple));
|
|
break;
|
|
case Upload:
|
|
server->handle(*((::Upload*)(std::get<0>(tuple))), std::get<2>(tuple));
|
|
break;
|
|
case Remove:
|
|
server->handle(*((RemoveFromCache*)(std::get<0>(tuple))), std::get<2>(tuple));
|
|
break;
|
|
case Clear:
|
|
server->handle(*((ClearCache*)(std::get<0>(tuple))), std::get<2>(tuple));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::tuple<void*, RequestType, void (*)(bool, Image)> waitForRequest() {
|
|
while (requests_.empty() || !stop_) {
|
|
}
|
|
|
|
auto pair = requests_.front();
|
|
requests_.pop();
|
|
|
|
return pair;
|
|
}
|
|
|
|
bool stop_;
|
|
std::queue<std::tuple<void*, RequestType, void (*)(bool, Image)>> requests_;
|
|
};
|
|
|
|
int main() {
|
|
Server server;
|
|
RequestHandler handler;
|
|
|
|
handler.start(&server);
|
|
|
|
Download d{"sth.png", 123, 100, true, Download::Ssh};
|
|
handler.pushRequest((void*)(&d),
|
|
RequestHandler::Download,
|
|
[](bool succes, Image image) {
|
|
if (succes) {
|
|
for (auto el : image.bitmap_) {
|
|
std::cout << el << ' ';
|
|
}
|
|
std::cout << '\n';
|
|
} else {
|
|
std::cout << "FAILED!\n";
|
|
}
|
|
});
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
handler.stop();
|
|
}
|