Skip to content

Example WebSocket‐server

ANYKS edited this page Mar 2, 2025 · 7 revisions
#include <server/ws.hpp>

using namespace awh;
using namespace placeholders;

class Executor {
	private:
		const fmk_t * _fmk;
		const log_t * _log;
	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){
			switch(static_cast <uint8_t> (mode)){
				case static_cast <uint8_t> (server::web_t::mode_t::CONNECT):
					this->_log->print("CONNECT", log_t::flag_t::INFO);
				break;
				case static_cast <uint8_t> (server::web_t::mode_t::DISCONNECT):
					this->_log->print("DISCONNECT", log_t::flag_t::INFO);
				break;
			}
		}

		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::websocket_t * ws){
			if(!buffer.empty()){
				string subprotocol = "";

				const auto subprotocols = ws->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());

				ws->sendMessage(bid, buffer, text);
			}
		}

		void headers([[maybe_unused]] const int32_t sid, [[maybe_unused]] const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, const uri_t::url_t & url, const unordered_multimap <string, string> & headers){
			uri_t uri(this->_fmk, this->_log);

			this->_log->print("REQUEST ID=%zu URL=%s", log_t::flag_t::INFO, bid, uri.url(url).c_str());

			for(auto & header : headers)
				cout << "HEADER: " << header.first << ": " << header.second << endl;
		}
	public:
		Executor(const fmk_t * fmk, const log_t * log) : _fmk(fmk), _log(log) {}
};

int32_t main(int32_t argc, char * argv[]){
	fmk_t fmk;
	log_t log(&fmk);

	server::core_t core(&fmk, &log);
	server::websocket_t ws(&core, &fmk, &log);

	Executor executor(&fmk, &log);

	log.name("WebSocket Server");
	log.format("%H:%M:%S %d.%m.%Y");

	ws.mode({
		server::web_t::flag_t::TAKEOVER_CLIENT,
		server::web_t::flag_t::TAKEOVER_SERVER
	});

	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);

	ws.subprotocols({"test1", "test2", "test3"});

	// ws.authType(awh::auth_t::type_t::BASIC);
	ws.authType(awh::auth_t::type_t::DIGEST, awh::auth_t::hash_t::MD5);

	// ws.init("anyks", {awh::http_t::compressor_t::DEFLATE});
	// ws.init(2222, "", {awh::http_t::compressor_t::DEFLATE});
	ws.init(2222, "127.0.0.1", {awh::http_t::compressor_t::DEFLATE});

	ws.callback <string (const uint64_t, const string &)> ("extractPassword", std::bind(&Executor::password, &executor, _1, _2));
	ws.callback <bool (const uint64_t, const string &, const string &)> ("checkPassword", std::bind(&Executor::auth, &executor, _1, _2, _3));
	ws.callback <bool (const string &, const string &, const uint32_t)> ("accept", std::bind(&Executor::accept, &executor, _1, _2, _3));
	ws.callback <void (const uint64_t, const server::web_t::mode_t)> ("active", std::bind(&Executor::active, &executor, _1, _2));
	ws.callback <void (const uint64_t, const uint32_t, const string &)> ("errorWebsocket", std::bind(&Executor::error, &executor, _1, _2, _3));
	ws.callback <void (const uint64_t, const vector <char> &, const bool)> ("messageWebsocket", std::bind(&Executor::message, &executor, _1, _2, _3, &ws));
	ws.callback <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const unordered_multimap <string, string> &)> ("headers", std::bind(&Executor::headers, &executor, _1, _2, _3, _4, _5));

	ws.start();

	return EXIT_SUCCESS;
}
Clone this wiki locally