| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 | 
							- #include <iostream>
 
- #include <memory>
 
- #include <mutex>
 
- #include <sstream>
 
- #include <unistd.h>
 
- #include <unordered_map>
 
- #include "CivetServer.h"
 
- class WebSocketBase : public CivetWebSocketHandler
 
- {
 
-   public:
 
- 	explicit WebSocketBase(std::string name) : name_(std::move(name))
 
- 	{
 
- 	}
 
- 	bool
 
- 	handleConnection(CivetServer *server, const mg_connection *conn) override
 
- 	{
 
- 		return true;
 
- 	}
 
- 	void
 
- 	handleReadyState(CivetServer *server, mg_connection *conn) override
 
- 	{
 
- 		std::unique_lock<std::mutex> lock(mutex_);
 
- 		pool_.emplace(conn, std::make_shared<std::mutex>());
 
- 	}
 
- 	bool
 
- 	handleData(CivetServer *server,
 
- 	           mg_connection *conn,
 
- 	           int bits,
 
- 	           char *data,
 
- 	           size_t data_len) override
 
- 	{
 
- 		if ((bits & 0x0F) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE) {
 
- 			return false;
 
- 		}
 
- 		data_.write(data, data_len);
 
- 		if (current_opcode_ == 0x00) {
 
- 			current_opcode_ = bits & 0x7f;
 
- 		}
 
- 		bool is_final_fragment = bits & 0x80;
 
- 		if (is_final_fragment) {
 
- 			switch (current_opcode_) {
 
- 			case MG_WEBSOCKET_OPCODE_TEXT:
 
- 				std::cout << data_.str() << std::endl; // print request data
 
- 				break;
 
- 			default:
 
- 				break;
 
- 			}
 
- 			current_opcode_ = 0x00;
 
- 			this->sendData(conn, data_.str()); // response
 
- 			data_.clear();
 
- 			data_.str(std::string());
 
- 		}
 
- 		return true;
 
- 	}
 
- 	void
 
- 	handleClose(CivetServer *server, const mg_connection *conn) override
 
- 	{
 
- 		auto *connection = const_cast<mg_connection *>(conn);
 
- 		std::shared_ptr<std::mutex> user_lock;
 
- 		{
 
- 			std::unique_lock<std::mutex> lock(mutex_);
 
- 			user_lock = pool_[connection];
 
- 		}
 
- 		{
 
- 			std::unique_lock<std::mutex> lock_connection(*user_lock);
 
- 			std::unique_lock<std::mutex> lock(mutex_);
 
- 			pool_.erase(connection);
 
- 		}
 
- 	}
 
- 	bool
 
- 	sendData(mg_connection *conn,
 
- 	         const std::string &data,
 
- 	         bool skippable = false,
 
- 	         int op_code = MG_WEBSOCKET_OPCODE_TEXT)
 
- 	{
 
- 		std::shared_ptr<std::mutex> connection_lock;
 
- 		{
 
- 			std::unique_lock<std::mutex> lock(mutex_);
 
- 			connection_lock = pool_[conn];
 
- 		}
 
- 		if (!connection_lock->try_lock()) {
 
- 			if (skippable) {
 
- 				return false;
 
- 			}
 
- 			connection_lock->lock();
 
- 			std::unique_lock<std::mutex> lock(mutex_);
 
- 		}
 
- 		int ret = mg_websocket_write(conn, op_code, data.c_str(), data.size());
 
- 		connection_lock->unlock();
 
- 		if (ret != static_cast<int>(data.size())) {
 
- 			if (data.empty() && ret == 2) {
 
- 				return true;
 
- 			}
 
- 			return false;
 
- 		}
 
- 		return true;
 
- 	}
 
- 	thread_local static std::stringstream data_;
 
- 	thread_local static unsigned char current_opcode_;
 
-   private:
 
- 	const std::string name_;
 
- 	mutable std::mutex mutex_;
 
- 	std::unordered_map<mg_connection *, std::shared_ptr<std::mutex>> pool_;
 
- };
 
- thread_local unsigned char WebSocketBase::current_opcode_ = 0x00;
 
- thread_local std::stringstream WebSocketBase::data_;
 
- int
 
- main()
 
- {
 
- 	std::cout << "Hello, Civetweb Websocket port:8080!" << std::endl;
 
- 	mg_init_library(0);
 
- 	std::vector<std::string> options = {
 
- 	    "document_root",
 
- 	    ".",
 
- 	    "listening_ports",
 
- 	    "8080",
 
- 	    "access_control_allow_headers",
 
- 	    "*",
 
- 	    "access_control_allow_methods",
 
- 	    "*",
 
- 	    "access_control_allow_origin",
 
- 	    "*",
 
- 	};
 
- 	auto server = std::make_shared<CivetServer>(options);
 
- 	auto ws = std::make_shared<WebSocketBase>("simple");
 
- 	server->addWebSocketHandler("/ws", *ws);
 
- 	while (true) {
 
- 		sleep(1);
 
- 	}
 
- 	server->close();
 
- 	return 0;
 
- }
 
 
  |