SuperHouse / esp-open-rtos

Open source FreeRTOS-based ESP8266 software framework
BSD 3-Clause "New" or "Revised" License
1.53k stars 491 forks source link

HTTP/HTTPS OTA update support #20

Open projectgus opened 9 years ago

projectgus commented 9 years ago

As discussed in #10 and partially implemented in 147257efa.

Turns out that writing to flash, which requires disabling interrupts, causes dropped packets which play havoc with TCP retry times (think 10 minutes to transfer a 200KB image).

For useful TCP-based OTA support, we need a way to throttle packet flow on either the network layer or a lower layer, or alternatively to reliably trigger TCP Fast Retransmits from the other end to avoid retry backoff times climbing exponentially. See this comment for some discussion of ways that have been attempted (and failed) already.

foogod commented 9 years ago

At the TCP level, it occurs to me that it may be possible to avoid dropped packets by managing the advertised receive window size (and explicitly setting the window size to zero (telling the sender to stop sending) before disabling interrupts). One would need to be careful about packets which might already be in-flight at that point, though.. (I haven't looked to see whether explicit window size manipulation is supported by lwIP/etc or would need some custom hacking to implement, but if it's not there already it seems like it would be useful for a lot of embedded applications anyway..)

It might also be possible to mitigate/avoid dropped packet effects using a particularly clever implementation of ECN signalling, but I'm not sure how platform-dependent that behavior would be..

projectgus commented 9 years ago

At the TCP level, it occurs to me that it may be possible to avoid dropped packets by managing the advertised receive window size (and explicitly setting the window size to zero (telling the sender to stop sending) before disabling interrupts)

Yes, this isa good idea. I looked for a way to do this early on, I was using the BSD Sockets layer in LWIP. It didn't seem possible there. There is a way to set the socket receive buffer size from the BSD API but (counter-intuitively) it seems decoupled from the window size signalling - at least I couldn't see a way that they related to each other, either in the code or in observed behaviour.

However, I've since started using the LWIP netconn API, which is one layer lower in the LWIP stack. I just looked again in the netconn header and there's an interesting flag NETCONN_FLAG_NO_AUTO_RECVED that defers window resizing, so you have to explicitly mark it as received. That might do it - can defer expanding the window again until after the flash is written.

clever implementation of ECN signalling

Good suggestion too, I hadn't looked at this. At a glance, LWIP does implement a 'cwnd' congestion window size parameter, and I see one of the TCP test programs messes with it a bit. Could be good to look into.

lukas-kuna commented 7 years ago

Why not HTTP 1.1 connection + HTTP range requests? https://tools.ietf.org/html/rfc7233