#include <awh/server/awh.hpp>
using namespace awh;
using namespace placeholders;
class WebServer {
private:
hash_t _hash;
private:
const fmk_t * _fmk;
const log_t * _log;
private:
awh::web_t::method_t _method;
public:
string password(const uint64_t bid, const string & login){
this->_log->print("USER: %s, PASS: %s, ID: %zu", log_t::flag_t::INFO, login.c_str(), "password", bid);
return "password";
}
bool auth(const uint64_t bid, const string & login, const string & password){
this->_log->print("USER: %s, PASS: %s, ID: %zu", log_t::flag_t::INFO, login.c_str(), password.c_str(), bid);
return true;
}
public:
bool accept(const string & ip, const string & mac, const uint32_t port){
this->_log->print("ACCEPT: IP=%s, MAC=%s, PORT=%d", log_t::flag_t::INFO, ip.c_str(), mac.c_str(), port);
return true;
}
void active([[maybe_unused]] const uint64_t bid, const server::web_t::mode_t mode){
this->_log->print("%s client", log_t::flag_t::INFO, (mode == server::web_t::mode_t::CONNECT ? "Connect" : "Disconnect"));
}
void error([[maybe_unused]] const uint64_t bid, const uint32_t code, const string & mess){
this->_log->print("%s [%u]", log_t::flag_t::CRITICAL, mess.c_str(), code);
}
void message(const uint64_t bid, const vector <char> & buffer, const bool text, server::awh_t * awh){
if(!buffer.empty()){
string subprotocol = "";
const auto subprotocols = awh->subprotocols(bid);
if(!subprotocols.empty())
subprotocol = (* subprotocols.begin());
this->_log->print("Message: %s [%s]", log_t::flag_t::INFO, string(buffer.begin(), buffer.end()).c_str(), subprotocol.c_str());
awh->sendMessage(bid, buffer, text);
}
}
void handshake(const int32_t sid, const uint64_t bid, const server::web_t::agent_t agent, server::awh_t * awh){
if((this->_method == awh::web_t::method_t::GET) && (agent == server::web_t::agent_t::HTTP)){
cout << " URL: " << awh->parser(sid, bid)->request().url << endl;
const string body = "<html>\n<head>\n<title>Hello World!</title>\n</head>\n<body>\n"
"<h1>\"Hello, World!\" program</h1>\n"
"<div>\nFrom Wikipedia, the free encyclopedia<br>\n"
"(Redirected from Hello, world!)<br>\n"
"Jump to navigationJump to search<br>\n"
"<strong>\"Hello World\"</strong> redirects here. For other uses, see Hello World (disambiguation).<br>\n"
"A <strong>\"Hello, World!\"</strong> program generally is a computer program that outputs or displays the message \"Hello, World!\".<br>\n"
"Such a program is very simple in most programming languages, and is often used to illustrate the basic syntax of a programming language. It is often the first program written by people learning to code. It can also be used as a sanity test to make sure that computer software intended to compile or run source code is correctly installed, and that the operator understands how to use it.\n"
"</div>\n</body>\n</html>\n";
if(awh->trailers(sid, bid)){
awh->trailer(sid, bid, "Goga", "Hello");
awh->trailer(sid, bid, "Hello", "World");
awh->trailer(sid, bid, "Anyks", "Best of the best");
awh->trailer(sid, bid, "Checksum", this->_hash.hashing <string> (body, hash_t::type_t::MD5));
}
awh->send(sid, bid, 200, "OK", vector <char> (body.begin(), body.end()));
}
}
void request(const int32_t sid, const uint64_t bid, const awh::web_t::method_t method, const uri_t::url_t & url, server::awh_t * awh){
this->_method = method;
if(!url.empty() && (!url.path.empty() && url.path.back().compare("favicon.ico") == 0))
awh->send(sid, bid, 404);
}
void headers([[maybe_unused]] const int32_t sid, [[maybe_unused]] const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, [[maybe_unused]] const uri_t::url_t & url, const unordered_multimap <string, string> & headers){
for(auto & header : headers)
cout << "HEADER: " << header.first << ": " << header.second << endl;
}
void entity(const int32_t sid, const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, const uri_t::url_t & url, const vector <char> & entity, server::awh_t * awh){
cout << "URL: " << url << endl << endl;
cout << "BODY: " << string(entity.begin(), entity.end()) << endl;
awh->send(sid, bid, 200, "OK", entity, {{"Connection", "close"}});
}
void complete(const int32_t sid, const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, const uri_t::url_t & url, const vector <char> & entity, const unordered_multimap <string, string> & headers, server::awh_t * awh){
for(auto & header : headers)
cout << "HEADER: " << header.first << ": " << header.second << endl;
cout << "URL: " << url << endl << endl;
if(!entity.empty()){
cout << "BODY: " << string(entity.begin(), entity.end()) << endl;
awh->send(sid, bid, 200, "OK", entity, {{"Connection", "close"}});
}
}
public:
WebServer(const fmk_t * fmk, const log_t * log) : _hash(log), _fmk(fmk), _log(log), _method(awh::web_t::method_t::NONE) {}
};
int32_t main(int32_t argc, char * argv[]){
fmk_t fmk;
log_t log(&fmk);
server::core_t core(&fmk, &log);
server::awh_t awh(&core, &fmk, &log);
WebServer executor(&fmk, &log);
log.name("WEB Server");
log.format("%H:%M:%S %d.%m.%Y");
awh.mode({
server::web_t::flag_t::TAKEOVER_CLIENT,
server::web_t::flag_t::TAKEOVER_SERVER,
server::web_t::flag_t::WEBSOCKET_ENABLE,
server::web_t::flag_t::CONNECT_METHOD_ENABLE
});
core.sonet(awh::scheme_t::sonet_t::TLS);
core.proto(awh::engine_t::proto_t::HTTP2);
// core.proto(awh::engine_t::proto_t::HTTP1_1);
core.cluster(awh::scheme_t::mode_t::ENABLED);
node_t::ssl_t ssl;
ssl.verify = false;
ssl.key = "./certs/certificates/server-key.pem";
ssl.cert = "./certs/certificates/server-cert.pem";
core.ssl(ssl);
// awh.authType(auth_t::type_t::BASIC);
awh.authType(auth_t::type_t::DIGEST, auth_t::hash_t::MD5);
awh.init(2222, "127.0.0.1", {
awh::http_t::compressor_t::ZSTD,
awh::http_t::compressor_t::BROTLI,
awh::http_t::compressor_t::GZIP,
awh::http_t::compressor_t::DEFLATE,
});
/*
awh.init("anyks", {
awh::http_t::compressor_t::ZSTD,
awh::http_t::compressor_t::BROTLI,
awh::http_t::compressor_t::GZIP,
awh::http_t::compressor_t::DEFLATE,
});
*/
awh.addOrigin("example.net");
awh.addAltSvc("example.net", "h2=\":2222\"");
awh.addAltSvc("example.com", "h2=\":8000\"");
awh.subprotocols({"test1", "test2", "test3"});
awh.on <string (const uint64_t, const string &)> ("extractPassword", &WebServer::password, &executor, _1, _2);
awh.on <bool (const uint64_t, const string &, const string &)> ("checkPassword", &WebServer::auth, &executor, _1, _2, _3);
awh.on <void (const uint64_t, const server::web_t::mode_t)> ("active", &WebServer::active, &executor, _1, _2);
awh.on <bool (const string &, const string &, const uint32_t)> ("accept", &WebServer::accept, &executor, _1, _2, _3);
awh.on <void (const uint64_t, const uint32_t, const string &)> ("errorWebsocket", &WebServer::error, &executor, _1, _2, _3);
awh.on <void (const uint64_t, const vector <char> &, const bool)> ("messageWebsocket", &WebServer::message, &executor, _1, _2, _3, &awh);
awh.on <void (const int32_t, const uint64_t, const server::web_t::agent_t)> ("handshake", &WebServer::handshake, &executor, _1, _2, _3, &awh);
awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &)> ("request", &WebServer::request, &executor, _1, _2, _3, _4, &awh);
// awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const vector <char> &)> ("entity", &WebServer::entity, &executor, _1, _2, _3, _4, _5, &awh);
// awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const unordered_multimap <string, string> &)> ("headers", &WebServer::headers, &executor, _1, _2, _3, _4, _5);
awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const vector <char> &, const unordered_multimap <string, string> &)> ("complete", &WebServer::complete, &executor, _1, _2, _3, _4, _5, _6, &awh);
awh.start();
return EXIT_SUCCESS;
}