mongoose learning (1) Https communication

Preface

The previous article recorded the use of mongoose for http communication. Originally planned to further communicate with https, but finally only successfully built an https server, which can be accessed through the browser https request; but the https client written by myself cannot successfully communicate with the server.
(The editor's level is limited, please forgive me, first record some of the experience of building an https server ヾ( ̄□ ̄;)ノ)

Configure opessl library

To configure HTTPS support, you need to use the OpenSSL library,

Of course, you can also use gmssl (because gmssl can replace openssl). But this does not mean that the cipher suites in gmssl can be used. Mongoose only supports the cipher suites in openssl, not gmssl-specific cipher suites. The reason is as follows.
Insert picture description here
From the mongoose source code, it can be seen that it uses SSLv23_client_method/ SSLv23_server_method when building the context, and for gmssl, it should use GMTLS_client_method/GMTLS_server_method... so it cannot support gmtls.
----------------------------------OK, the above is a digression---------- ---------------------------------

Back to the topic, we need to compile the openssl/gmssl library. The editor has compiled the gmssl library (libcrypto.lib, libssl.lib) before, and wrote related articles on how to compile, so I’ll just "use it" here. To go into more details, children's shoes can find the information and compile it by themselves...(σ°∀°)σ...
Introduce the gmssl library (link header file and .lib file, etc.) into the project, so that the openssl library is configured.
(Note: The editor is a coding test conducted under the windows platform)

Enable SSL function

The mongoose ssl function is turned off by default, so we need to turn on the ssl function first.
The opening method is as follows: (Note. The editor uses mongoose version 6.13)
mongoose defines the MG_ENABLE_SSL macro to control the opening and closing of the ssl function. Modify the value of MG_ENABLE_SSL in the mongoose.h header file to 1 to enable the SSL function.
Insert picture description here

code

Server

The https server construction process is similar to http, and it also follows the basic logic of the server. The difference is that you need to use the mg_bind_opt function to create a monitoring connection. The struct mg_bind_opts opts parameter in the mg_bind_opts function is used to specify the certificate, private key and other parameters required for ssl communication.
Insert picture description here
The complete code of the server is as follows:

#include "stdafx.h"
#include "stdafx.h"
#include "mongoose.h"

#include <string>

static const char *s_http_port = "8443";
static const char *s_ssl_cert = "server.crt";
static const char *s_ssl_key = "server.key";
static const char *s_ssl_ca = "ca.crt";
static struct mg_serve_http_opts s_http_server_opts;

static void ev_handler(struct mg_connection *conn, int ev, void *ev_data)
{
    
    
	// 区分http和websocket
	if (ev == MG_EV_HTTP_REQUEST)
	{
    
    
		http_message *hm = (http_message *)ev_data;

		//(int)hm->message.len, hm->message.p 中存放客户端发过来的信息,包括post,Host(http地址),Content-Length(信息的长度),以及信息本身。
		//通过 std::string url = std::string(hm->uri.p, hm->uri.len); 可以得到url
		//通过 std::string body = std::string(hm->body.p, hm->body.len);可以得到body中 存储的从客户端发送过来的信息
		std::string req_str = std::string(hm->message.p, hm->message.len);
		printf("got request:\n%s\n", req_str.c_str());

		//TODO.  请求处理
		// eg.  We have received an HTTP request. Parsed request is contained in `hm`.
		//      Send HTTP reply to the client which shows full original request.
		mg_send_head(conn, 200, hm->message.len, "Content-Type: text/plain");
		mg_printf(conn, "%.*s", (int)hm->message.len, hm->message.p);

		//API函数mg_serve_http()可以轻松地从文件系统提供文件。 例如,为了创建一个从当前目录提供静态文件的Web服务器,实现如下处理:
		//mg_serve_http(conn, hm, s_http_server_opts);

	}
	else if (ev == MG_EV_WEBSOCKET_HANDSHAKE_DONE ||
		ev == MG_EV_WEBSOCKET_FRAME ||
		ev == MG_EV_CLOSE)
	{
    
    
		websocket_message *ws_message = (struct websocket_message *)ev_data;
		//TODO.  请求处理
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	//声明和初始化事件管理器,  mg_mgr是拥有所有活动连接的事件管理器
	struct mg_mgr mgr;
	//mg_connection描述连接
	struct mg_connection *nc;

	struct mg_bind_opts bind_opts;
	const char *err;

	mg_mgr_init(&mgr, NULL);

	/* Set HTTP server options */
	memset(&bind_opts, 0, sizeof(bind_opts));
	bind_opts.error_string = &err;      //
	bind_opts.ssl_cert = s_ssl_cert;    //指定服务端证书
	bind_opts.ssl_key = s_ssl_key;      //指定服务端私钥
	//bind_opts.ssl_ca_cert = s_ssl_ca;  //提供了CA证书,表示需要验证客户端的证书

	printf("Starting SSL server on port %s, cert from %s, key from %s\n", s_http_port, bind_opts.ssl_cert, bind_opts.ssl_key);
	nc = mg_bind_opt(&mgr, s_http_port, ev_handler, bind_opts);
	if (nc == NULL)
	{
    
    
		printf("Failed to create listener: %s\n", err);
		getchar();
		return 1;
	}
	// Set up HTTP server parameters,  for both http and websocket
	mg_set_protocol_http_websocket(nc);
	s_http_server_opts.document_root = ".";  // Serve current directory
	s_http_server_opts.enable_directory_listing = "yes";

	//通过调用循环创建一个事件mg_mgr_poll()循环:
	for (;;) {
    
    
		mg_mgr_poll(&mgr, 1000);
	}
	mg_mgr_free(&mgr);

	return 0;
}

Running result: (In the code, we directly return the received request to the client)
Insert picture description here

If the CA certificate is specified through bind_opts.ssl_ca_cert , it means that the server needs to verify the client's certificate. At this time, the client needs to provide its certificate when accessing, otherwise the connection with the server cannot be established.
Since we are using self-generated certificates here, we cannot access them directly from the browser.
Insert picture description here

Client

In theory, the client implementation process should also be similar to http, and also follow the basic logic of the server. The difference is that if the server needs to authenticate the client's identity, it needs to configure parameters through functions such as mg_connect_http_opt/mg_connect_opt.

The ideal is full, and the reality is cruel╮(︶﹏︶")╭Ghost knows what I have experienced
. The client cannot connect to the server when I actually code. The debug trace found that the MG_EV_CONNECT signal was triggered in the ev_handler, but the connect_status was obtained. The status value is -3.
… (•ิ_•ิ)? The reason has not been found yet. The content of the https client connection will be updated later.
If you know, please leave a comment and let the editor.

Guess you like

Origin blog.csdn.net/lt4959/article/details/112987047