關於 k210 的 micropython 新增 ussl 模組,實現 https 訪問支援的那些事。
阿新 • • 發佈:2020-05-11
## 起因
事情已經過去快一週了吧,繼上次修復 maixpy k210 的 esp8285 at 通訊後,突然遇到澤畔大大問,要不要做 ussl 的支援?
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511161240772-919687151.png)
評估了一下各方的實現,想了一下自己也剛好在做網路層的優化和處理,況且 micropython 在 stm32 、 esp32 上的也有對應的實現,那就新增實現進去吧,選取了 mbedtls 版本的 ussl 模組,實現相關檔案如下。
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511161628241-723980256.png)
這裡說一下 ussl 的工作機制。
首先建立在 micropython 的 network 架構下的 socket 模組,提供了關鍵的 steam->write 和 steam->read 基礎介面,實際上就是繼承一個抽象 steam 物件的介面。
因此 ussl 提供了 wrap_socket 用來提升 socket 的功能,從而支援 https 的訪問。
我們看一下 micropython 的例項就知道了。
```python
try:
import usocket as _socket
except:
import _socket
try:
import ussl as ssl
except:
import ssl
def main(use_stream=True):
s = _socket.socket()
ai = _socket.getaddrinfo("google.com", 443)
print("Address infos:", ai)
addr = ai[0][-1]
print("Connect address:", addr)
s.connect(addr)
s = ssl.wrap_socket(s)
print(s)
if use_stream:
# Both CPython and MicroPython SSLSocket objects support read() and
# write() methods.
s.write(b"GET / HTTP/1.0\r\n\r\n")
print(s.read(4096))
else:
# MicroPython SSLSocket objects implement only stream interface, not
# socket interface
s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096))
s.close()
main()
```
實現的最終結果如下,不過目前的實測效果距離商業使用,保守來講,還有很大的優化空間,主要在核心函式和配置方面要改善效能。
- esp32 的效果
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162645196-1236849552.png)
- k210 的效果
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162658266-1634262996.png)
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162728976-904228570.png)
## 實現細節
MaixPy k210 採用 components/micropython/CMakeLists.txt 來管理 micropython 的編譯命令。
所以在不脫離主流的基礎上,在 micropython-ulab 的配置後面繼續新增如下配置。
```cmake
if(1 OR CONFIG_MICROPY_SSL_MBEDTLS)
list(APPEND ADD_INCLUDE "${mpy_core_dir}/lib/mbedtls/include")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE='\"${mpy_port_dir}/src/mbedtls/include/mbedtls_config.h\"'")
# message(${CMAKE_C_FLAGS})
append_srcs_dir(ADD_SRCS "port/src/mbedtls")
append_srcs_dir(ADD_SRCS "core/lib/mbedtls/library")
list(REMOVE_ITEM ADD_SRCS "${mpy_core_dir}/lib/mbedtls/library/net_sockets.c")
endif()
```
稍微解釋一下
- 將 mbedtls/include 和 mbedtls/library 新增到環境中,並排除 net_sockets.c 的實現,問題下述。
![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511171655283-358539972.png)
- 給 CMAKE_C_FLAGS 新增 -DMBEDTLS_CONFIG_FILE 自定義的 mbedtls 配置檔案,從而遮蔽內建的 config.h 。(奇怪的是 add_definitions 不 work ,就直接用 set 了)
```c
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
```
所以現在把程式碼編譯了進去,就完成了大部分的移植,是不是很簡單?
[修改記錄在這裡,可供參考。](https://github.com/junhuanchen/MaixPy/commit/ec7506219f7ebd14bac711c8d48d6e4c5bc87191)
當然,事情不會這麼順利的,在沒有進行專門配置的時候,啟動模組是可以的,現在開始實踐發起一次 get https 網站的請求,測試 python code 如下:
```python
wCli = MicroWebCli('https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13631786501')
# wCli = MicroWebCli('https://www.baifubao.com/callback?cmd=1059&callback=phone&phone=13631786501')
# wCli = MicroWebCli('https://github.com')
# wCli = MicroWebCli('https://ssl.logink.cn/')
# wCli = MicroWebCli('https://cn.bing.com/?FORM=Z9FD1')
# wCli = MicroWebCli('https://www.sojson.com')
# wCli = MicroWebCli('https://www.baidu.com')
while True:
try:
print('GET %s' % wCli.URL)
wCli.OpenRequest()
buf = memoryview(bytearray(1024))
resp = wCli.GetResponse()
if resp.IsSuccess() :
while not resp.IsClosed() :
x = resp.ReadContentInto(buf)
if x < len(buf) :
buf = buf[:x]
print(bytes(buf))
print('GET success with "%s" content type' % resp.GetContentType())
else :
print('GET return %d code (%s)' % (resp.GetStatusCode(), resp.GetStatusMessage()))
except Exception as E:
print(E)
time.sleep(2)
```
## 問題一: -0x0034 錯誤程式碼
Gather entropy_len bytes of entropy to seed state
mbedtls_ctr_drbg_seed returned -52 或者-0x0034
錯誤解釋:
MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
原因:
給mbedtls提供的熵源不夠混亂,應該用硬體隨機數發生器。
解決:
mbedtls\config.h
`#define MBEDTLS_ENTROPY_HARDWARE_ALT`
解決方案可以參考
https://blog.csdn.net/liaofeifly/article/details/88899655
mbedtls_hardware_poll 實現可以參考 esp32 、stm32 的,如下是我後來實踐到 k210 的,這個函式只會在發起連結的時候呼叫。
```c
#include