openssl3.2 - 官方demo学习 - guide - quic-client-block.c

文章目录

    • openssl3.2 - 官方demo学习 - guide - quic-client-block.c
    • 概述
    • 笔记
    • END

openssl3.2 - 官方demo学习 - guide - quic-client-block.c

概述

在程序运行时, 要指定环境变量 SSL_CERT_FILE=rootcert.pem, 同时将rootcert.pem拷贝到工程目录下, 否则不好使
吐槽啊, 为啥不用命令行参数或者API参数传进来啊, 整啥环境变量啊, 看着膈应.

quic服务启动(openssl3.2 - quic服务的运行)时的命令行为 quicserver.exe -trace localhost 23456 servercert.pem serverkey.pem
本程序(quic客户端)命令行只能为 localhost 23456 才行
用 127.0.0.1 23456 不好使.

如果要单步调试, 得赶紧的. quic服务启动后, 如果30秒内没有客户端来, quic服务会退出, 这太不礼貌了…
只能跑一下, 听个响, 学不到东西.

这个demo, 是不是只想展示, openssl可以作为quic客户端程序的tls实现?

笔记

/*!
* \file quic-client-block.c
* \note openssl3.2 - 官方demo学习 - guide - quic-client-block.c
* 在程序运行时, 要指定环境变量 SSL_CERT_FILE=rootcert.pem, 同时将rootcert.pem拷贝到工程目录下, 否则不好使
* 吐槽啊, 为啥不用命令行参数或者API参数传进来啊, 整啥环境变量啊, 看着膈应.
* 
* quic服务启动时的命令行为 quicserver.exe -trace localhost 23456 servercert.pem serverkey.pem
本程序(quic客户端)命令行只能为 localhost 23456 才行
用 127.0.0.1 23456 不好使.如果要单步调试, 得赶紧的. quic服务启动后, 如果30秒内没有客户端来, quic服务会退出, 这太不礼貌了...
只能跑一下, 听个响, 学不到东西.这个demo, 是不是只想展示, openssl可以作为quic客户端程序的tls实现?
*//**  Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.**  Licensed under the Apache License 2.0 (the "License").  You may not use*  this file except in compliance with the License.  You can obtain a copy*  in the file LICENSE in the source distribution or at*  https://www.openssl.org/source/license.html*//** NB: Changes to this file should also be reflected in* doc/man7/ossl-guide-quic-client-block.pod*/#include <string.h>/* Include the appropriate header file for SOCK_DGRAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
#endif#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>#include "my_openSSL_lib.h"/* Helper function to create a BIO connected to the server */
static BIO* create_socket_bio(const char* hostname, const char* port,int family, BIO_ADDR** peer_addr)
{int sock = -1;BIO_ADDRINFO* res;const BIO_ADDRINFO* ai = NULL;BIO* bio;/** Lookup IP address info for the server.*/if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,&res))return NULL;/** Loop through all the possible addresses for the server and find one* we can connect to.*/for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {/** Create a UDP socket. We could equally use non-OpenSSL calls such* as "socket" here for this and the subsequent connect and close* functions. But for portability reasons and also so that we get* errors on the OpenSSL stack in the event of a failure we use* OpenSSL's versions of these functions.*/sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);if (sock == -1)continue;/* Connect the socket to the server's address */if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {BIO_closesocket(sock);sock = -1;continue;}/* Set to nonblocking mode */if (!BIO_socket_nbio(sock, 1)) {BIO_closesocket(sock);sock = -1;continue;}break;}if (sock != -1) {*peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));if (*peer_addr == NULL) {BIO_closesocket(sock);return NULL;}}/* Free the address information resources we allocated earlier */BIO_ADDRINFO_free(res);/* If sock is -1 then we've been unable to connect to the server */if (sock == -1)return NULL;/* Create a BIO to wrap the socket */bio = BIO_new(BIO_s_datagram());if (bio == NULL) {BIO_closesocket(sock);return NULL;}/** Associate the newly created BIO with the underlying socket. By* passing BIO_CLOSE here the socket will be automatically closed when* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which* case you must close the socket explicitly when it is no longer* needed.*/BIO_set_fd(bio, sock, BIO_CLOSE);return bio;
}/** Simple application to send a basic HTTP/1.0 request to a server and* print the response on the screen. Note that HTTP/1.0 over QUIC is* non-standard and will not typically be supported by real world servers. This* is for demonstration purposes only.*/
int main(int argc, char* argv[])
{SSL_CTX* ctx = NULL;SSL* ssl = NULL;BIO* bio = NULL;int res = EXIT_FAILURE;int ret;unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };const char* request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";const char* request_end = "\r\n\r\n";size_t written, readbytes;char buf[160];BIO_ADDR* peer_addr = NULL;char* hostname, * port;int argnext = 1;int ipv6 = 0;if (argc < 3) {printf("Usage: quic-client-block [-6] hostname port\n");goto end;}if (!strcmp(argv[argnext], "-6")) {if (argc < 4) {printf("Usage: quic-client-block [-6] hostname port\n");goto end;}ipv6 = 1;argnext++;}hostname = argv[argnext++];port = argv[argnext];/** Create an SSL_CTX which we can use to create SSL objects from. We* want an SSL_CTX for creating clients so we use* OSSL_QUIC_client_method() here.*/ctx = SSL_CTX_new(OSSL_QUIC_client_method());if (ctx == NULL) {printf("Failed to create the SSL_CTX\n");goto end;}/** Configure the client to abort the handshake if certificate* verification fails. Virtually all clients should do this unless you* really know what you are doing.*/SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);/* Use the default trusted certificate store */if (!SSL_CTX_set_default_verify_paths(ctx)) {printf("Failed to set the default trusted certificate store\n");goto end;}/* Create an SSL object to represent the TLS connection */ssl = SSL_new(ctx);if (ssl == NULL) {printf("Failed to create the SSL object\n");goto end;}/** Create the underlying transport socket/BIO and associate it with the* connection.*/bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET, &peer_addr);if (bio == NULL) {printf("Failed to crete the BIO\n");goto end;}SSL_set_bio(ssl, bio, bio);/** Tell the server during the handshake which hostname we are attempting* to connect to in case the server supports multiple hosts.*/if (!SSL_set_tlsext_host_name(ssl, hostname)) {printf("Failed to set the SNI hostname\n");goto end;}/** Ensure we check during certificate verification that the server has* supplied a certificate for the hostname that we were expecting.* Virtually all clients should do this unless you really know what you* are doing.*/if (!SSL_set1_host(ssl, hostname)) {printf("Failed to set the certificate verification hostname");goto end;}/* SSL_set_alpn_protos returns 0 for success! */if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {printf("Failed to set the ALPN for the connection\n");goto end;}/* Set the IP address of the remote peer */if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {printf("Failed to set the initial peer address\n");goto end;}/*! 到这就要将quic服务开起来, 否则连接失败 *//* Do the handshake with the server */if (SSL_connect(ssl) < 1) {printf("Failed to connect to the server\n");/** If the failure is due to a verification error we can get more* information about it from SSL_get_verify_result().*/if (SSL_get_verify_result(ssl) != X509_V_OK)printf("Verify error: %s\n",X509_verify_cert_error_string(SSL_get_verify_result(ssl)));goto end;}/* Write an HTTP GET request to the peer */if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {printf("Failed to write start of HTTP request\n");goto end;}if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {printf("Failed to write hostname in HTTP request\n");goto end;}if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {printf("Failed to write end of HTTP request\n");goto end;}/** Get up to sizeof(buf) bytes of the response. We keep reading until the* server closes the connection.*//*! 这前面, 给服务器发了3句话这下面循环, 然后将服务器回包读完, 就往下走了 */while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {/** OpenSSL does not guarantee that the returned data is a string or* that it is NUL terminated so we use fwrite() to write the exact* number of bytes that we read. The data could be non-printable or* have NUL characters in the middle of it. For this simple example* we're going to print it to stdout anyway.*/fwrite(buf, 1, readbytes, stdout);}/* In case the response didn't finish with a newline we add one now */printf("\n");/** Check whether we finished the while loop above normally or as the* result of an error. The 0 argument to SSL_get_error() is the return* code we received from the SSL_read_ex() call. It must be 0 in order* to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In* QUIC terms this means that the peer has sent FIN on the stream to* indicate that no further data will be sent.*/switch (SSL_get_error(ssl, 0)) {case SSL_ERROR_ZERO_RETURN:/* Normal completion of the stream *//*! 最后是从这里break的 */break;case SSL_ERROR_SSL:/** Some stream fatal error occurred. This could be because of a stream* reset - or some failure occurred on the underlying connection.*/switch (SSL_get_stream_read_state(ssl)) {case SSL_STREAM_STATE_RESET_REMOTE:printf("Stream reset occurred\n");/* The stream has been reset but the connection is still healthy. */break;case SSL_STREAM_STATE_CONN_CLOSED:printf("Connection closed\n");/* Connection is already closed. Skip SSL_shutdown() */goto end;default:printf("Unknown stream failure\n");break;}break;default:/* Some other unexpected error occurred */printf("Failed reading remaining data\n");break;}/** Repeatedly call SSL_shutdown() until the connection is fully* closed.*/do {ret = SSL_shutdown(ssl); // 关断ssl需要好久...if (ret < 0) {printf("Error shutting down: %d\n", ret);goto end;}} while (ret != 1);/* Success! */res = EXIT_SUCCESS;
end:/** If something bad happened then we will dump the contents of the* OpenSSL error stack to stderr. There might be some useful diagnostic* information there.*/if (res == EXIT_FAILURE)ERR_print_errors_fp(stderr);/** Free the resources we allocated. We do not free the BIO object here* because ownership of it was immediately transferred to the SSL object* via SSL_set_bio(). The BIO will be freed when we free the SSL object.*/SSL_free(ssl);SSL_CTX_free(ctx);BIO_ADDR_free(peer_addr);return res;
}

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/630014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Centos7 安装Jenkins2.440

首先&#xff0c;确保您的CentOS 7系统已经安装了Java 11。您可以使用以下命令来安装Java 11&#xff1a; bash 从官网下载jdk11&#xff0c;例如&#xff1a;jdk-11.0.21_linux-x64_bin.tar.gz&#xff0c;使用命令tar -zxvf jdk-11.0.21_linux-x64_bin.tar.gz -C / 直接解压…

kafka简单介绍和代码示例

“这是一篇理论文章&#xff0c;给大家讲一讲kafka” 简介 在大数据领域开发者常常会听到MQ这个术语&#xff0c;该术语便是消息队列的意思&#xff0c; Kafka是分布式的发布—订阅消息系统。它最初由LinkedIn(领英)公司发布&#xff0c;使用Scala语言编写&#xff0c;与2010年…

HTML---Jquery选择器

文章目录 目录 文章目录 本章目标 一.Jquery选择器概述 二.Jquery选择器分类 基本选择器 层次选择器 属性选择器 三.基本过滤选择器 练习 本章目标 会使用基本选择器获取元素会使用层次选择器获取元素会使用属性选择器获取元素会使用过滤选择器获取元素 …

Mysql单行函数

文章目录 数值函数基本函数角度与弧度转化三角函数指数与对数进制间转换 字符串函数日期和时间函数获取日期、时间日期与时间戳的转换获取月份、星期、星期数、天数等函数日期的操作函数 时间和秒钟转换的函数计算日期和时间的函数日期的格式化与解析 流程控制函数加密与解密函…

SQL Server 数据类型

文章目录 一、文本类型&#xff08;字母、符号或数字字符的组合&#xff09;二、整数类型三、精确数字类型四、近似数字&#xff08;浮点&#xff09;类型五、日期类型六、货币类型七、位类型八、二进制类型 一、文本类型&#xff08;字母、符号或数字字符的组合&#xff09; 在…

【物联网】物联网设备和应用程序涉及协议的概述

物联网设备和应用程序涉及协议的概述。帮助澄清IoT层技术栈和头对头比较。 物联网涵盖了广泛的行业和用例&#xff0c;从单一受限制的设备扩展到大量跨平台部署嵌入式技术和实时连接的云系统。 将它们捆绑在一起是许多传统和新兴的通信协议&#xff0c;允许设备和服务器以新的…

奥伦德光电耦合器5G通信领域及其相关领域推荐

光电耦合器是以光为媒介传输电信号的一种电-光-电转换器件。由于该器件使用寿命长、工作温度范围宽&#xff0c;所以在过程控制、工业通信、家用电器、医疗设备、通信设备、计算机以及精密仪器等方面有着广泛应用在当前工艺技术持续发展与提升的过程中&#xff0c;其工作速度、…

java常见面试题:如何使用Java进行MyBatis框架开发?

MyBatis是一个优秀的持久层框架&#xff0c;它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解来配置和映射原生信息&#xff0c;将接口和Java的POJOs(Plain Old Java Objects,普通的Java…

新能源汽车智慧充电桩方案:如何实现充电停车智慧化管理?

一、方案概述 基于新能源汽车充电桩的监管运营等需求&#xff0c;安徽旭帆科技携手合作伙伴触角云共同打造“智能充电设备&#xff0b;云平台&#xff0b;APP小程序”一体化完整的解决方案&#xff0c;为充电桩车位场所提供精细化管理车位的解决办法&#xff0c;解决燃油车恶意…

用时序数据库 DolphinDB 搭建一套轻量化工业试验平台解决方案

DolphinDB 作为集成了高容量高速度流数据分析系统和强大编程语言的一站式解决方案&#xff0c;旨在为用户提供快速存储、检索、分析和计算庞大的结构化数据服务。本文将提供一个轻量化的工业试验平台数据处理解决方案&#xff0c;快速简单地实现海量数据采集、存储、处理和分析…

Spring MVC学习之——Controller类中方法的返回值

Controller类中方法的返回值 1.返回ModelAndView RequestMapping("/hello")public ModelAndView hello(){//封装了页面和数据ModelAndView view new ModelAndView();//对这个请求的页面添加属性&#xff08;数据&#xff09;view.addObject("hello",&quo…

HTML 列表 iframe

文章目录 列表无序列表有序列表自定义列表 iframe 引入外部页面 列表 列表 是 装载 结构 , 样式 一致的 文字 或 图表 的容器 ; 列表 由于其 整齐 , 整洁 , 有序 的特征 , 类似于表格 , 但是其 组合的自由程度高于表格 , 经常用来进行布局 ; HTML 列表包括如下类型 : 无序列…

【IAP】核心开发流程

最近做了IAP U盘升级模块开发&#xff0c;总结下IAP基本开发流程&#xff0c;不深入讨论原理。 详细原理参考 首先需要知道我们需要把之前的APP区域拆一块出来做BOOT升级程序区域。 以STM32F103为例&#xff0c;0x08000000到0x0807FFFF为FLASH空间&#xff0c;即上图代码区域…

Unity解决Udp客户端无法接收数据的问题

Unity解决Udp客户端无法接收数据的问题 在我之前做过的项目中&#xff0c;其中不少涉及Udp客户端的项目。在这些项目中&#xff0c;一般只需要实现客户端向服务器端发送数据的功能就可以了&#xff0c;一般都不用接收服务器端发送的数据&#xff0c;但是也有同学使用了我分享的…

vue-router之路由钩子函数应用解析

vue-router是vue开发中不可或缺的一部分&#xff0c;也是vue全家桶生态的重要部分&#xff0c;平时开发vue时会高频率使用&#xff0c;那么它除了在routes上的应用外&#xff0c;还有一些钩子函数具体可以应用在哪些地方呢 路由的钩子函数共有6个 全局的路由钩子函数&#xff…

DOM 的 diff 算法

经典面试题&#xff1a; 1&#xff09;react/vue中的 key 有什么作用&#xff1f;&#xff08;key的内部原理是什么&#xff1f;&#xff09; 2&#xff09;为什么遍历列表时&#xff0c;key 最好不用 index&#xff1f; 1、虚拟dom中key的作用&#xff1a; 1&#xff09; 简…

【二、自动化测试】为什么要做自动化测试?哪种项目适合做自动化?

自动化测试是一种软件测试方法&#xff0c;通过编写和使用自动化脚本和工具&#xff0c;以自动执行测试用例并生成结果。 自动化旨在替代手动测试过程&#xff0c;提高测试效率和准确性。 自动化测试可以覆盖多种测试类型&#xff0c;包括功能测试、性能测试、安全测试等&…

Spring06

一、SpirngMvc的基本概念 Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架&#xff0c;本质上相当于 Servlet。 MVC&#xff08;Model View Controller&#xff09;&#xff0c;一种用于设计创建Web应用程序的开发模式 Model&#xff08;模型&#xff…

软件测试|使用matplotlib绘制气泡图

简介 气泡图&#xff08;Bubble Chart&#xff09;是一种数据可视化工具&#xff0c;通常用于展示三维数据的分布情况&#xff0c;其中数据点以气泡的形式显示在二维平面上&#xff0c;每个气泡的位置表示两个变量的值&#xff0c;气泡的大小表示第三个变量的值。在Python中&a…

广告效果评估的意义 | 广告效果评估的重要性有哪些?

本文由群狼调研&#xff08;长沙品牌推广测试&#xff09;出品&#xff0c;欢迎转载&#xff0c;请注明出处。广告效果评估的重要性体现在多个方面&#xff0c;以下是一些关键点&#xff1a; 1.投资回报评估&#xff1a; 广告活动往往需要巨大的投资&#xff0c;通过评估广告效…