C

W801(W80X_SDK_v1.00.10)https请求mbedtls报错0x7780问题解决记录

事情的起因是想通过W801实现检测到gpio电平变化后,通过telegram发送bot通知消息,结果在调用自己的tg api反代(caddy v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=)接口时,串口日志提示标题上的ssl握手0x7780错误。

代码是直接抄的SDK示例中的demo\wm_https_demo.c代码,报错的函数是在握手时,也就是调用HTTPWrapperSSLConnect的时候,如下:

                    wm_printf("step 1: ssl connect to...\r\n");
                    ret = HTTPWrapperSSLConnect(&ssl_p, fd, (const struct sockaddr *)&server, sizeof(server), HTTPS_DEMO_SERVER);
                    if (ret < 0)
                    {
                        wm_printf("https connect error\r\n");
                        close(fd);
                        break;
                    }

开始的时候只是能看到串口输出step 1: ssl connect to…,然后报了个0x7780的错误,接下来https connect error,请求失败返回,研究了下内部使用的mbedtls库,发现其实还有更详细的调试日志,要在SDK的\src\app\mbedtls\include\mbedtls\config.h中打开“define MBEDTLS_DEBUG_C”这行宏定义(并且需要确保makefile项目的lib目标重新构建,如果是参考我之前的CLion IDE用法,就是在构建的configuration里选择lib,然后rebuild),打开后就能看到类似:https://forums.mbed.com/t/error-0x7780-during-handshake/6883 这里提到的错误信息:

Continue reading…

也记一篇关于strncpy和snprintf中n的不同之处

关于这俩c库函数的使用方法,百度上一搜能搜到很多,但是实际上用了这么多年的我有时候还是会犯迷糊,分不清哪个是处理0结尾的,哪个是没有的,因此今天趁着放假有时间,再整理记录一下。

#include <cstring>

int main(int argc, char *argv[])
{
    char sz_test1[10] = {};
    char sz_test2[10] = {};

    char sz_source[10] = "123456789";

    strncpy(sz_test1, sz_source, 10);
    snprintf(sz_test2, 10, "%s", sz_source);

    return 0;
}

上面是一段很简单的写在cpp里的c代码,纯c也差不多,主要说的是这俩c函数的区别,可以看到sz_source有9个字符,带1个结尾0凑成10字节的字符串,上面还有两个同样是10字节的char缓冲区用于测试,可以看到strncpysnprintf的n都给10的时候,sz_test1和sz_test2都是和sz_source一样的结果,包括结尾0。

接下来把两个函数的n都换成9,这时候可以看到如下结果:

Continue reading…

一种通过C++模板方式识别无用户数据C回调函数的方法

今天记录一个个人觉得有点意思的问题:C++代码中调用C API时,对于C回调函数的处理问题,如何识别出调用API时的信息?

这个问题,大部分API都是通过调用时提供传递用户数据的方式实现的,如libcurl中的CURLOPT_WRITEDATA,CURLOPT_READDATA ,通过curl_easy_setopt方式将任意用户数据指针传递给CURL句柄,并在执行上传下载时的回调函数内透传给调用方,这样在例如多线程并发上传下载时就可以很方便的识别出是哪个上传下载任务的回调了。但是,如果API及回调函数内没有提供传递用户数据的接口和回调参数的话,是不是就一定无法完成识别调用上下文信息的功能呢?比如下列的C函数API:

// C-Style callback function without user context
typedef void (*c_api_callback_no_context)(int count);
// C-Style callback function with user context
typedef void (*c_api_callback_context)(int count, void * user_context);

// C API function that will trigger the callback function
void c_api_start_counting_no_context(c_api_callback_no_context callback, int max);
void c_api_start_counting_context(c_api_callback_context callback, int max, void * user_context);

c_api_start_counting_context及配套的c_api_callback_context回调为可以透传用户数据的版本,而c_api_start_counting_no_context及c_api_callback_no_context则只提供了逻辑用回调参数count,没有可用于识别context的用户数据指针,那么如何在不碰C源码的前提下(闭源C库或不想做侵入式修改)做到和带用户数据回调一样的效果呢?目前想到的一种方法是通过C++模板生成不同地址的回调函数配合上下文信息映射来实现:

Continue reading…