Explorar o código

Merge branch 'master' of https://github.com/civetweb/civetweb

bel2125 %!s(int64=3) %!d(string=hai) anos
pai
achega
4e172b5b40

+ 24 - 0
examples/linux_ws_server_cpp/CMakeLists.txt

@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.5.1)
+project(linux_ws_server)
+
+set(TARGET_NAME ${PROJECT_NAME})
+set(CMAKE_CXX_STANDARD 14)
+
+find_package(PkgConfig REQUIRED)
+find_package(civetweb)
+
+
+include_directories(
+    ${civetweb_INCLUDE_DIR}
+)
+
+link_directories (
+    /usr/local/lib
+)
+
+add_executable(${TARGET_NAME} main.cc)
+
+target_link_libraries(${TARGET_NAME}
+    libcivetweb-cpp.so
+    libcivetweb.so
+)

+ 17 - 0
examples/linux_ws_server_cpp/README.md

@@ -0,0 +1,17 @@
+[TOC]
+
+# Civetweb websocket cpp
+
+## #1 Installation
+
+```shell
+git clone https://github.com/civetweb/civetweb.git
+mkdir buildx && cd buildx
+cmake -DBUILD_SHARED_LIBS=ON -DCIVETWEB_ENABLE_WEBSOCKETS=ON -DCIVETWEB_ENABLE_CXX=ON ..
+make
+sudo make install
+```
+
+
+
+

+ 150 - 0
examples/linux_ws_server_cpp/main.cc

@@ -0,0 +1,150 @@
+#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;
+}

+ 16 - 5
src/civetweb.c

@@ -12986,9 +12986,11 @@ mg_unlock_context(struct mg_context *ctx)
 #if defined(USE_WEBSOCKET)
 
 #if !defined(NO_SSL_DL)
+#if !defined(OPENSSL_API_3_0)
 #define SHA_API static
 #include "sha1.inl"
 #endif
+#endif
 
 static int
 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
@@ -12996,6 +12998,9 @@ send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 	static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 	char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
 	size_t dst_len = sizeof(b64_sha);
+#if !defined(OPENSSL_API_3_0)
+   SHA_CTX sha_ctx;
+#endif
 	int truncated;
 
 	/* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
@@ -13007,8 +13012,14 @@ send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 
 	DEBUG_TRACE("%s", "Send websocket handshake");
 
+#if defined(OPENSSL_API_3_0)
 	EVP_Digest((unsigned char *)buf, (uint32_t)strlen(buf), (unsigned char *)sha,
 		NULL, EVP_get_digestbyname("sha1"), NULL);
+#else
+   SHA1_Init(&sha_ctx);
+   SHA1_Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
+   SHA1_Final((unsigned char *)sha, &sha_ctx);
+#endif
 	mg_base64_encode((unsigned char *)sha, sizeof(sha), b64_sha, &dst_len);
 	mg_printf(conn,
 	          "HTTP/1.1 101 Switching Protocols\r\n"
@@ -22226,12 +22237,12 @@ mg_get_handler_info(struct mg_context *ctx,
     mg_lock_context(ctx);
 
     for (tmp_rh = ctx->dd.handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
-                
+
         if (buflen > handler_info_len+ tmp_rh->uri_len) {
         memcpy(buffer+handler_info_len, tmp_rh->uri, tmp_rh->uri_len);
         }
         handler_info_len += tmp_rh->uri_len;
-        
+
         switch (tmp_rh->handler_type) {
             case REQUEST_HANDLER:
                 (void)tmp_rh->handler;
@@ -22240,12 +22251,12 @@ mg_get_handler_info(struct mg_context *ctx,
         (void)tmp_rh->connect_handler;
        (void) tmp_rh->ready_handler;
        (void) tmp_rh->data_handler;
-       (void) tmp_rh->close_handler; 
+       (void) tmp_rh->close_handler;
             break;
             case AUTH_HANDLER:
-             (void) tmp_rh->auth_handler; 
+             (void) tmp_rh->auth_handler;
             break;
-        }      
+        }
         (void)cbdata;
     }