vooon / esp-ota-server

ESP8266 ESP32 HTTP OTA server
Apache License 2.0
34 stars 4 forks source link

OTA Server panics when receiving version data not in ESP version map format (tasmota devices) #35

Closed rmi1974 closed 9 months ago

rmi1974 commented 9 months ago

Hello! Thanks for the nice little project.

I'm using the ESP OTA server for updating my OMG BLE gateways which works fine. The server is running in Docker container in my homelab.

I have various esp8266 and esp32 based "IOT" devices, flashed with Tasmota firmware. I've tried to use the OTA server as well for them to serve tasmota firmware images The tasmota firmware is built locally and deployed to the OTA server directory. My OTA folder structure looks like this:

tree --charset=ANSI /opt/esp-ota-server/data/

/opt/esp-ota-server/data/
|-- esp32dev-ble
|   |-- firmware-v1.7.0-17-gd10ec6a7.bin
|   |-- firmware-v1.7.0-33-g3952e0a0.bin
|   |-- firmware-v1.7.0-34-gd841c3b6.bin
|   |-- firmware-v1.7.0-35-g4349d09c.bin
|   `-- firmware-v1.7.0-38-g166ff3d7.bin
|-- tasmota
|   |-- tasmota-v13.3.0.2.bin
|   |-- tasmota-v13.3.0.2.bin.gz
|   |-- tasmota-v13.3.0.3.bin
|   `-- tasmota-v13.3.0.3.bin.gz
|-- tasmota32
|   |-- tasmota32-v13.3.0.2.bin
|   `-- tasmota32-v13.3.0.3.bin
|-- tasmota-4M
|   |-- tasmota-4M-v13.3.0.2.bin
|   |-- tasmota-4M-v13.3.0.2.bin.gz
|   |-- tasmota-4M-v13.3.0.3.bin
|   `-- tasmota-4M-v13.3.0.3.bin.gz
`-- tasmota-minimal
    |-- tasmota-minimal-v13.3.0.2.bin
    |-- tasmota-minimal-v13.3.0.2.bin.gz
    |-- tasmota-minimal-v13.3.0.3.bin
    `-- tasmota-minimal-v13.3.0.3.bin.gz

Communication to tasmota devices is done via curl/http Tasmota Commands.

curl -s http://192.168.xxx.xxx/cm?cmnd=STATUS+2 | jq
 {
  "StatusFWR": {
    "Version": "13.3.0.2(tasmota32)",
    "BuildDateTime": "2024-01-07T11:46:11",
    "Core": "2_0_14",
    "SDK": "4.4.6.231122",
    "CpuFrequency": 160,
    "Hardware": "ESP32-D0WD-V3 v3.1",
    "CR": "437/699"
  }

When requesting a firmware update over the same command interface (setting OTA url and initiating the update with special command), it doesn't work.

The server crashes when the binary is requested from the target device. Relevant part of crash:

...
2024-01-17T15:52:05.038900779Z - prefix=echo file=server.go line=82 esp_request_headers={"Connection":["close"],"Content-Length":["0"],"User-Agent":["ESP8266-http-Update"],"X-Esp8266-Ap-Mac":["9A:CD:AC:1D:2D:44"],"X-Esp8266-Chip-Id":["1912132"],"X-Esp8266-Chip-Size":["4194304"],"X-Esp8266-Free-Space":["1454080"],"X-Esp8266-Mode":["sketch"],"X-Esp8266-Sdk-Version":["2.2.2-dev(38a443e)"],"X-Esp8266-Sketch-Md5":["4d76b17c945b23a919214b0d9dfbc6e2"],"X-Esp8266-Sketch-Size":["639344"],"X-Esp8266-Sta-Mac":["98:CD:AC:1D:2D:44"],"X-Esp8266-Version":["13.3.0.3(tasmota-4M)"]}
...
2024-01-17T15:52:05.039654106Z 2024-01-17T15:52:05.039654106Z - [PANIC RECOVER] runtime error: index out of range [1] with length 1 goroutine 6 [running]:
github.com/vooon/esp-ota-server/server.Serve.Recover.RecoverWithConfig.func3.1.1()
    /go/pkg/mod/github.com/labstack/echo/v4@v4.11.4/middleware/recover.go:100 +0x150
panic({0x89c520?, 0xc000028348?})
    /usr/local/go/src/runtime/panic.go:914 +0x21f
github.com/vooon/esp-ota-server/server.server.getBinaryFile({{{0xc000012dc0, 0x5}, {0xc000028180, 0x15}, {0xc000012dd0, 0x5}}, 0xc00002a880}, {0x9858f0, 0xc000109720})
    /build/server/server.go:108 +0x10f5
github.com/labstack/echo/v4.(*Echo).add.func1({0x9858f0, 0xc000109720})
    /go/pkg/mod/github.com/labstack/echo/v4@v4.11.4/echo.go:582 +0x4b
github.com/vooon/esp-ota-server/server.Serve.Recover.RecoverWithConfig.func3.1({0x9858f0?, 0xc000109720})
    /go/pkg/mod/github.com/labstack/echo/v4@v4.11.4/middleware/recover.go:131 +0x11d
github.com/labstack/echo/v4/middleware.LoggerWithConfig.func2.1({0x9858f0?, 0xc000109720})
    /go/pkg/mod/github.com/labstack/echo/v4@v4.11.4/middleware/logger.go:126 +0xd2
github.com/labstack/echo/v4.(*Echo).ServeHTTP(0xc000140900, {0x980038?, 0xc00019c0e0}, 0xc00016a100)
    /go/pkg/mod/github.com/labstack/echo/v4@v4.11.4/echo.go:669 +0x399
net/http.serverHandler.ServeHTTP({0xc000173110?}, {0x980038?, 0xc00019c0e0?}, 0x6?)
    /usr/local/go/src/net/http/server.go:2938 +0x8e
net/http.(*conn).serve(0xc00013a510, {0x980a40, 0xc000173020})
    /usr/local/go/src/net/http/server.go:2009 +0x5f4
created by net/http.(*Server).Serve in goroutine 1
    /usr/local/go/src/net/http/server.go:3086 +0x5cb
...

<repeats>

Here is a case that works (OMG BLE device), with no "Version" data returned:

2024-01-17T16:20:12.809200451Z - prefix=echo file=server.go line=82 esp_request_headers={"Cache-Control":["no-cache"],"Connection":["close"],"User-Agent":["ESP32-http-Update"],"X-Esp32-Ap-Mac":["A0:B7:65:68:6A:D1"],"X-Esp32-Chip-Size":["4194304"],"X-Esp32-Free-Space":["1966080"],"X-Esp32-Mode":["sketch"],"X-Esp32-Sdk-Version":["v4.4.4"],"X-Esp32-Sketch-Md5":["1b85cd3b2f14d082b890e836bb308e7f"],"X-Esp32-Sketch-Sha256":["65E31424EA51E42A1CA6AACD6E03420AC6B71884873A027F9EBA5C13E1002B38"],"X-Esp32-Sketch-Size":["1605456"],"X-Esp32-Sta-Mac":["A0:B7:65:68:6A:D0"]}

Apparently the OTA server code requires Version value(s) in specific format. It can't handle version strings of format 13.3.0.3(tasmota-4M).

The problem seems to be here:

https://github.com/vooon/esp-ota-server/blob/ff477f6b501de1e4dd16f18bc6c56d532746d1a1/server/server.go#L105

    if vok {
        vmap := map[string]string{}
        for _, kv := range strings.Split(version[0], " ") {
            n := strings.SplitN(kv, ":", 2)
            vmap[n[0]] = n[1]
        }

        c.Logger().Printj(log.JSON{
            "esp_version_map": vmap,
        })

Maybe such cases, that is any non-conformant version data returned could be ignored and pretend there was no version data sent by the device.

Regards

vooon commented 9 months ago

Hmm, could you try to get exact headers that tasmota sends? I'd like to make unit test...

Initially i designed that parsing for my own version string format like here:

https://github.com/vooon/elehant-to-mqtt/blob/efb078b61252092e1ce09cd152a9296393643e6c/src/ota.cpp#L20-L23

(i.e. fw:1.2.3 hw:1.0 core:foo)

vooon commented 9 months ago

@rmi1974 i think should be fixed now. Could you please check?

rmi1974 commented 9 months ago

Hello @vooon

thanks for the bugfix, I can confirm it works. Here are the requested log entries for completeness:

esp-ota-server  | 2024-01-23T20:28:08.430279000Z {"time":"2024-01-23T20:28:08.42934969Z","level":"-","prefix":"echo","file":"server.go","line":"79","esp_request_headers":{"Connection":["close"],"Content-Length":["0"],"User-Agent":["ESP8266-http-Update"],"X-Esp8266-Ap-Mac":["82:64:6F:81:17:65"],"X-Esp8266-Chip-Id":["8460133"],"X-Esp8266-Chip-Size":["2097152"],"X-Esp8266-Free-Space":["372736"],"X-Esp8266-Mode":["sketch"],"X-Esp8266-Sdk-Version":["2.2.2-dev(38a443e)"],"X-Esp8266-Sketch-Md5":["75527e3d45b55bbcfac9162494214fcc"],"X-Esp8266-Sketch-Size":["655248"],"X-Esp8266-Sta-Mac":["80:64:6F:81:17:65"],"X-Esp8266-Version":["13.3.0.3(tasmota)"]}}
esp-ota-server  | 2024-01-23T20:28:08.436067000Z {"time":"2024-01-23T20:28:08.435672611Z","level":"-","prefix":"echo","file":"server.go","line":"104","esp_version_map":{"ver":"13.3.0.3(tasmota)"}}
esp-ota-server  | 2024-01-23T20:31:37.907449000Z {"time":"2024-01-23T20:31:37.90687794Z","level":"-","prefix":"echo","file":"server.go","line":"79","esp_request_headers":{"Connection":["close"],"Content-Length":["0"],"User-Agent":["ESP8266-http-Update"],"X-Esp8266-Ap-Mac":["9A:CD:AC:1D:2D:44"],"X-Esp8266-Chip-Id":["1912132"],"X-Esp8266-Chip-Size":["4194304"],"X-Esp8266-Free-Space":["1454080"],"X-Esp8266-Mode":["sketch"],"X-Esp8266-Sdk-Version":["2.2.2-dev(38a443e)"],"X-Esp8266-Sketch-Md5":["4d76b17c945b23a919214b0d9dfbc6e2"],"X-Esp8266-Sketch-Size":["639344"],"X-Esp8266-Sta-Mac":["98:CD:AC:1D:2D:44"],"X-Esp8266-Version":["13.3.0.3(tasmota-4M)"]}}
esp-ota-server  | 2024-01-23T20:31:37.907905000Z {"time":"2024-01-23T20:31:37.906910568Z","level":"-","prefix":"echo","file":"server.go","line":"104","esp_version_map":{"ver":"13.3.0.3(tasmota-4M)"}}
esp-ota-server  | 2024-01-23T20:32:17.709282000Z {"time":"2024-01-23T20:32:17.709054323Z","level":"-","prefix":"echo","file":"server.go","line":"79","esp_request_headers":{"Cache-Control":["no-cache"],"Connection":["close"],"User-Agent":["ESP32-http-Update"],"X-Esp32-Ap-Mac":["A0:B7:65:6C:5B:4D"],"X-Esp32-Chip-Size":["4194304"],"X-Esp32-Free-Space":["2949120"],"X-Esp32-Mode":["sketch"],"X-Esp32-Sdk-Version":["4.4.6.231011"],"X-Esp32-Sketch-Md5":["b5b226c6a084e2461a6cee7ace745600"],"X-Esp32-Sketch-Sha256":["F8FB136202B1C28EC2A55FEE31B76668B57E78D81DD6127FFB8753B99981E482"],"X-Esp32-Sketch-Size":["789424"],"X-Esp32-Sta-Mac":["A0:B7:65:6C:5B:4C"],"X-Esp32-Version":["13.2.0.1(safeboot)"]}}
esp-ota-server  | 2024-01-23T20:32:17.709893000Z {"time":"2024-01-23T20:32:17.709086595Z","level":"-","prefix":"echo","file":"server.go","line":"104","esp_version_map":{"ver":"13.2.0.1(safeboot)"}}

Regards