Complete browser OTA responses before reboot and allow HTTP restarts
This commit is contained in:
1 parent
8e449136ca
commit
47f4581056
10 files changed
+449
-19
No files matched your search
@@ -0,0 +1,53 @@
|
||||
"""Build private AsyncTCP fixes and the current vendored OTA implementation."""
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PINNED_ASYNCTCP_SHA256 = "27e3e22a6030cc5c9c9f32f28d0a3a36189b1ea6a5fa270777b2d2790a89c365"
|
||||
ORIGINAL_BIND = " msg->err = tcp_bind(pcb, msg->bind.addr, msg->bind.port);"
|
||||
REUSABLE_BIND = """ // A stopped HTTP listener may still have completed connections in
|
||||
// TIME_WAIT. Permit immediate rebinding during WebConfig/OTA handoffs.
|
||||
#if SO_REUSE
|
||||
ip_set_option(pcb, SOF_REUSEADDR);
|
||||
#endif
|
||||
""" + ORIGINAL_BIND
|
||||
|
||||
|
||||
def patched_async_tcp(source):
|
||||
source = source.replace("\r\n", "\n")
|
||||
if (hashlib.sha256(source.encode("ascii")).hexdigest() != PINNED_ASYNCTCP_SHA256
|
||||
or source.count(ORIGINAL_BIND) != 1):
|
||||
raise RuntimeError("AsyncTCP restart fix: changed pinned source; review library update")
|
||||
return source.replace(ORIGINAL_BIND, REUSABLE_BIND, 1)
|
||||
|
||||
|
||||
def replace_async_source(build_env, node):
|
||||
source = Path(node.srcnode().get_abspath())
|
||||
if source.name == "AsyncTCP.cpp":
|
||||
content = patched_async_tcp(source.read_text(encoding="utf-8"))
|
||||
include_dir = source.parent
|
||||
elif source.name == "AsyncElegantOTA.cpp":
|
||||
# file:// dependencies can retain an earlier copy in .pio/libdeps.
|
||||
# Compile this checkout's vendored source without editing that cache.
|
||||
include_dir = Path(build_env.subst("$PROJECT_DIR")) / "arch/esp32/AsyncElegantOTA/src"
|
||||
content = (include_dir / source.name).read_text(encoding="ascii")
|
||||
else:
|
||||
return node
|
||||
destination = Path(build_env.subst("$BUILD_DIR")) / "patched-esp32-web" / source.name
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not destination.exists() or destination.read_text(encoding="ascii") != content:
|
||||
destination.write_text(content, encoding="ascii")
|
||||
build_env.PrependUnique(CPPPATH=[str(include_dir)])
|
||||
return build_env.File(str(destination))
|
||||
|
||||
|
||||
def install(build_env):
|
||||
build_env.PrependUnique(CPPPATH=[str(Path(build_env.subst("$PROJECT_DIR"))
|
||||
/ "arch/esp32/AsyncElegantOTA/src")])
|
||||
build_env.AddBuildMiddleware(replace_async_source, "*AsyncTCP*src*AsyncTCP.cpp")
|
||||
build_env.AddBuildMiddleware(replace_async_source, "*AsyncElegantOTA*src*AsyncElegantOTA.cpp")
|
||||
|
||||
|
||||
if "Import" in globals():
|
||||
Import("env")
|
||||
install(env)
|
||||
Reference in new issue
Block a user