下载的文件约有800KB,但是单片机内存没有那么大,
程序用的是示例程序
webclient_file.c
MBEDTLS的内存最大增到过最大限制长度16384,但是还是原因mbedtls的大小,小于下载文件大小导致失败
//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384
#define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_ECP_WINDOW_SIZE 2
#define MBEDTLS_SSL_MAX_CONTENT_LEN 3584*2
每次读文件的大小都限制了2048字节
#define WEBCLIENT_HEADER_BUFSZ 2048
#define WEBCLIENT_RESPONSE_BUFSZ 2048
下载失败日志如下:
下载失败日志如下:
[D/mbedtls.clnt] Set debug level (1)
[D/mbedtls.clnt] mbedtls client struct init success...
[D/web] host address: unilink-uat.crland.com.cn , port: 443
[D/mbedtls.clnt] mbedtls client context init success...
[D/mbedtls.clnt] Connected unilink-uat.crland.com.cn:443 success...
[D/mbedtls.clnt] Certificate verified success...
[D/web] request header:
[D/web] GET /uat-api/file/I5MaXMTfXiI2M-JhmfNFz4_LPSeuvsvh?accessKey=I5MaXMV7JBd2Nr2wmoy_ysqmVJn1u9_t HTTP/1.1
[D/web] Host: unilink-uat.crland.com.cn
[D/web] User-Agent: RT-Thread HTTP Agent
[D/web] response header:
[D/web] HTTP/1.1 200 OK
[D/web] Date: Thu, 14 Nov 2024 12:00:51 GMT
[D/web] Content-Type: application/octet-stream
[D/web] Content-Length: 738482
[D/web] Connection: keep-alive
[D/web] traceparent: 00-932a8c34cba8dcb89c2e97c565f81768-70bc13c3e3b97d2d-01
[D/web] Vary: Origin
[D/web] Vary: Access-Control-Request-Method
[D/web] Vary: Access-Control-Request-Headers
[D/web] traceparent: 00-932a8c34cba8dcb89c2e97c565f81768-0f4e5e5146cc9664-01
[D/web] Vary: Origin
[D/web] Vary: Access-Control-Request-Method
[D/web] Vary: Access-Control-Request-Headers
[D/web] Accept-Ranges: bytes
[D/web] Content-MD5: 288bbbefb2e7adba49bee0408df74757
[D/web] Digest: sha-256=459e9106a46221589d5ceb6eac43920f08ccefb3c9d080c74d7cb189261a8c97
[D/web] Content-Disposition: attachment; filename*=UTF-8''EACSS_HD_HR_4.0.0.4.bin
[D/web] get position handle response(200).
[D/web.file] len:2048
>[D/web.file] len:4096
>[D/web.file] len:6144
>[D/web.file] len:8192
>[D/web.file] len:10240
>[D/web.file] len:12288
>[D/web.file] len:14336
>[D/web.file] len:16384
>[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:1897: requesting more data than fits
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:4719: mbedtls_ssl_fetch_input() returned -28928 (-0x7100)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:3974: ssl_get_next_record() returned -28928 (-0x7100)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:5464: mbedtls_ssl_read_record() returned -28928 (-0x7100)
[E/mbedtls.clnt] mbedtls_client_read data error, return -0x7100
[D/web] receive data error(-28928).
[D/web.file] len:16942
>[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:1897: requesting more data than fits
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:4719: mbedtls_ssl_fetch_input() returned -28928 (-0x7100)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:3974: ssl_get_next_record() returned -28928 (-0x7100)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:5464: mbedtls_ssl_read_record() returned -28928 (-0x7100)
[E/mbedtls.clnt] mbedtls_client_read data error, return -0x7100
[D/web] receive data error(-28928).
[D/web.file] read err
[D/web.file] save 16942 bytes.
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:2866: mbedtls_ssl_flush_output() returned -26752 (-0x6880)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:5000: mbedtls_ssl_write_record() returned -26752 (-0x6880)
[D/mbedtls.clnt] ../packages/mbedtls-latest/mbedtls/library/ssl_msg.c:5871: mbedtls_ssl_send_alert_message() returned -26752 (-0x6880)
下面是mbedtls源码,nb_want的值是一直增加的是随着webclient_read一直增加的,这样子内存一直不够。
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
size_t in_buf_len = ssl->in_buf_len;
#else
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
"or mbedtls_ssl_set_bio()" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
uint32_t timeout;
/*
* The point is, we need to always read a full datagram at once, so we
* sometimes read more then requested, and handle the additional data.
* It could be the rest of the current record (while fetching the
* header) and/or some other records in the same datagram.
*/
/*
* Move to the next record in the already read datagram if applicable
*/
if( ssl->next_record_offset != 0 )
{
if( ssl->in_left < ssl->next_record_offset )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
ssl->in_left -= ssl->next_record_offset;
if( ssl->in_left != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
MBEDTLS_PRINTF_SIZET,
ssl->next_record_offset ) );
memmove( ssl->in_hdr,
ssl->in_hdr + ssl->next_record_offset,
ssl->in_left );
}
ssl->next_record_offset = 0;
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
/*
* Done if we already have enough data.
*/
if( nb_want <= ssl->in_left)
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
return( 0 );
}
/*
* A record can't be split across datagrams. If we need to read but
* are not at the beginning of a new record, the caller did something
* wrong.
*/
if( ssl->in_left != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
/*
* Don't even try to read if time's out already.
* This avoids by-passing the timer when repeatedly receiving messages
* that will end up being dropped.
*/
if( mbedtls_ssl_check_timer( ssl ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
ret = MBEDTLS_ERR_SSL_TIMEOUT;
}
else
{
len = in_buf_len - ( ssl->in_hdr - ssl->in_buf );
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
timeout = ssl->handshake->retransmit_timeout;
else
timeout = ssl->conf->read_timeout;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
if( ssl->f_recv_timeout != NULL )
ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
timeout );
else
ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
if( ret == 0 )
return( MBEDTLS_ERR_SSL_CONN_EOF );
}
if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
mbedtls_ssl_set_timer( ssl, 0 );
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
{
if( ssl_double_retransmit_timeout( ssl ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
return( MBEDTLS_ERR_SSL_TIMEOUT );
}
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
return( ret );
}
return( MBEDTLS_ERR_SSL_WANT_READ );
}
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
{
if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
ret );
return( ret );
}
return( MBEDTLS_ERR_SSL_WANT_READ );
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
}
if( ret < 0 )
return( ret );
ssl->in_left = ret;
}
else
#endif
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
while( ssl->in_left < nb_want )
{
len = nb_want - ssl->in_left;
if( mbedtls_ssl_check_timer( ssl ) != 0 )
ret = MBEDTLS_ERR_SSL_TIMEOUT;
else
{
if( ssl->f_recv_timeout != NULL )
{
ret = ssl->f_recv_timeout( ssl->p_bio,
ssl->in_hdr + ssl->in_left, len,
ssl->conf->read_timeout );
}
else
{
ret = ssl->f_recv( ssl->p_bio,
ssl->in_hdr + ssl->in_left, len );
}
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
", nb_want: %" MBEDTLS_PRINTF_SIZET,
ssl->in_left, nb_want ) );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
if( ret == 0 )
return( MBEDTLS_ERR_SSL_CONN_EOF );
if( ret < 0 )
return( ret );
if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
ret, len ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
ssl->in_left += ret;
}
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
return( 0 );
}
尝试过写个简单的断点续传的程序,还是报同样的错误。
请问各位大佬有什么头绪解决这个问题,或者说mbedtls是不是还有些参数可以配置,
怎么修改webclient_read,让mbedtls_ssl_fetch_input中的nb_want不会一直增加下去?
已解决,单片机ssl解密太慢,下载文件超时了,导致出错了。
http下载支持断点续传,文件大也没关系,你的http请求heard是啥
[D/web] GET /uat-api/file/I5MaXMTfXiI2M-JhmfNFz4_LPSeuvsvh?accessKey=I5MaXMV7JBd2Nr2wmoy_ysqmVJn1u9_t HTTP/1.1
[D/web] Host: unilink-uat.crland.com.cn
[D/web] User-Agent: RT-Thread HTTP Agent
请求头部就是上面日志的内容,这个问题和断点续传没关系,他那个报的这个错是接收到的数据包比预期的要大,或者解析时超出了可用缓冲区的大小。
就是我每webclient_get一次mebdtls的nb_want就会增大一次,最后增大到超过预定的一帧数据大小减去当前已接收数据的大小即MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf )
,所以才会出错,
webclient_get
时或者mbedtls_client_read
的某个地方是不是要想办法情况这个nb_want呢。
硬件上有AES和RSA不?看看能不能用起来。
也可以看看服务器上面是否支持对低算力CPU更友好的加密算法,如chacha20这类
另外,使用 http1.1 keepalive 或 http2.0 可以减少握手次数。