Fixed split HTTP Headers

This commit is contained in:
Martin Ger
2018-09-12 11:31:18 +02:00
parent 872bc29e57
commit 5d7220d306
6 changed files with 72 additions and 39 deletions
+25 -16
View File
@@ -325,6 +325,21 @@ You can send the ESP to sleep manually once by using the "sleep" command.
Caution: If you save a _vmin_ value higher than the max supply voltage to flash, the repeater will immediately shutdown every time after reboot. Then you have to wipe out the whole config by flashing blank.bin (or any other file) to 0x0c000.
# Building and Flashing
To build this binary you download and install the esp-open-sdk (https://github.com/pfalcon/esp-open-sdk). Make sure, you can compile and download the included "blinky" example.
Then download this source tree in a separate directory and adjust the BUILD_AREA variable in the Makefile and any desired options in user/user_config.h. Changes of the default configuration can be made in user/config_flash.c. Build the esp_wifi_repeater firmware with "make". "make flash" flashes it onto an esp8266.
The source tree includes a binary version of the liblwip_open plus the required additional includes from my fork of esp-open-lwip and a binary of the rboot tool. *No additional install action is required for that.* Only if you don't want to use the precompiled library, checkout the sources from https://github.com/martin-ger/esp-open-lwip . Use it to replace the directory "esp-open-lwip" in the esp-open-sdk tree. "make clean" in the esp_open_lwip dir and once again a "make" in the upper esp_open_sdk directory. This will compile a liblwip_open.a that contains the NAT-features. Replace liblwip_open_napt.a with that binary. Also you might build the "rboot.bin" binary from https://github.com/raburton/rboot and replace it in the root directory of the project.
If you want to use the complete precompiled firmware binaries you can flash them with "esptool.py --port /dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x02000 firmware/0x02000.bin" (use -fs 1MB for an ESP-01). For the esp8285 you must use -fs 1MB and -fm dout.
On Windows you can flash it using the "ESP8266 Download Tool" available at https://espressif.com/en/support/download/other-tools. Download the two files 0x00000.bin and 0x02000.bin from the firmware directory. For a generic ESP12, a NodeMCU or a Wemos D1 use the following settings (for an ESP-01 change FLASH SIZE to "8Mbit"):
<img src="https://raw.githubusercontent.com/martin-ger/esp_wifi_repeater/master/FlashRepeaterWindows.jpg">
If "QIO" mode fails on your device, try "DIO" instead. Also have a look at the "Detected Info" to check size and mode of the flash chip. If your downloaded firmware still doesn't start properly, please check with the enclosed checksums whether the binary files are possibly corrupted.
# OTA (Over the air) update support (experimental)
Based on using the rboot lib: https://github.com/raburton/rboot and thanks to the contribution of christianchristensen.
@@ -340,7 +355,16 @@ Now you can control the OTA features with the following commands:
- ota update: tries to download a new binary (0x02000.bin or 0x82000.bin) via HTTP from ota_host:ota_port and starts it
- ota switch: switches to the other binary (if installed)
Known Issue: currently the download has some quirks and doesn't work for all HTTP-servers.
To test the OTA feature, configure your ESP (as STA or AP) to be connected to the network with the update server. There start a simple Web server in the firmware directory, e.g.;
```
cd firmware
python -m SimpleHTTPServer 8080
```
Set the parameter _hostname_ to the hostname or IP of your computer, set _portno_ to 8080, and "save". The type on the CLI:
```
ota upgrade
```
If configured correctly, the update will start and the ESP will reboot with the new binary.
# ENC28J60 Ethernet Support (experimental)
If you enable the HAVE_ENC28J60 option in user_config.h and recompile the project, you get support for an ENC28J60 Ethernet NIC connected via SPI.
@@ -367,21 +391,6 @@ Now you can configure the new Ethernet interface:
- set eth_gw _gw-addr_: sets a static gateway address for the ETH interface
# Building and Flashing
To build this binary you download and install the esp-open-sdk (https://github.com/pfalcon/esp-open-sdk). Make sure, you can compile and download the included "blinky" example.
Then download this source tree in a separate directory and adjust the BUILD_AREA variable in the Makefile and any desired options in user/user_config.h. Changes of the default configuration can be made in user/config_flash.c. Build the esp_wifi_repeater firmware with "make". "make flash" flashes it onto an esp8266.
The source tree includes a binary version of the liblwip_open plus the required additional includes from my fork of esp-open-lwip and a binary of the rboot tool. *No additional install action is required for that.* Only if you don't want to use the precompiled library, checkout the sources from https://github.com/martin-ger/esp-open-lwip . Use it to replace the directory "esp-open-lwip" in the esp-open-sdk tree. "make clean" in the esp_open_lwip dir and once again a "make" in the upper esp_open_sdk directory. This will compile a liblwip_open.a that contains the NAT-features. Replace liblwip_open_napt.a with that binary. Also you might build the "rboot.bin" binary from https://github.com/raburton/rboot and replace it in the root directory of the project.
If you want to use the complete precompiled firmware binaries you can flash them with "esptool.py --port /dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x02000 firmware/0x02000.bin" (use -fs 1MB for an ESP-01). For the esp8285 you must use -fs 1MB and -fm dout.
On Windows you can flash it using the "ESP8266 Download Tool" available at https://espressif.com/en/support/download/other-tools. Download the two files 0x00000.bin and 0x02000.bin from the firmware directory. For a generic ESP12, a NodeMCU or a Wemos D1 use the following settings (for an ESP-01 change FLASH SIZE to "8Mbit"):
<img src="https://raw.githubusercontent.com/martin-ger/esp_wifi_repeater/master/FlashRepeaterWindows.jpg">
If "QIO" mode fails on your device, try "DIO" instead. Also have a look at the "Detected Info" to check size and mode of the flash chip. If your downloaded firmware still doesn't start properly, please check with the enclosed checksums whether the binary files are possibly corrupted.
# Known Issues
- Due to the limitations of the ESP's SoftAP implementation, there is a maximum of 8 simultaniously connected stations.
- The ESP8266 requires a good power supply as it produces current spikes of up to 170 mA during transmit (typical average consumption is around 70 mA when WiFi is on). Check the power supply first, if your ESP runs unstable and reboots from time to time. A large capacitor between Vdd and Gnd can help if you experience problems here.
Binary file not shown.
+2 -2
View File
@@ -1,3 +1,3 @@
f35be9cf5af5018d871f12ee70f9aaeeda356b02 firmware/0x02000.bin
7a3cf6d304d3c927461366ff891e43283c570eb1 firmware/0x82000.bin
3373f9e9d95ef3b8d628cf8c342ab91614d7c628 firmware/0x02000.bin
fbf4fe56f13e73dfdeba041ced22ad622811a780 firmware/0x82000.bin
9bd7d25204d71b3db5f35e0b2def8a6aaa7f765c firmware/0x00000.bin
+43 -19
View File
@@ -29,6 +29,8 @@ typedef struct {
ota_callback callback; // user callback when completed
uint32 total_len;
uint32 content_len;
bool ok;
uint8_t col_cnt;
struct espconn *conn;
ip_addr_t ip;
rboot_write_status write_status;
@@ -86,12 +88,28 @@ static void ICACHE_FLASH_ATTR upgrade_recvcb(void *arg, char *pusrdata, unsigned
// disarm the timer
os_timer_disarm(&ota_timer);
// first reply?
if (!upgrade->ok && length < 12) {
os_printf("HTTP error - response too short\r\n");
rboot_ota_deinit();
return;
}
// Still in header?
if (upgrade->content_len == 0) {
// valid http response?
// http response 200 ok?
if (!upgrade->ok) {
os_printf("HTTP %c%c%c\r\n", pusrdata[9], pusrdata[10], pusrdata[11]);
if (os_strncmp(pusrdata + 9, "200", 3) == 0) {
upgrade->ok = true;
} else {
// fail, not a 200 response
rboot_ota_deinit();
return;
}
}
if ((ptrLen = (char*)os_strstr(pusrdata, "Content-Length: "))
&& (ptrData = (char*)os_strstr(ptrLen, "\r\n\r\n"))
&& (os_strncmp(pusrdata + 9, "200", 3) == 0)) {
&& (ptrData = (char*)os_strstr(ptrLen, "\r\n\r\n"))) {
// end of header/start of data
ptrData += 4;
@@ -110,13 +128,18 @@ static void ICACHE_FLASH_ATTR upgrade_recvcb(void *arg, char *pusrdata, unsigned
ptr = (char *)os_strstr(ptrLen, "\r\n");
*ptr = '\0'; // destructive
upgrade->content_len = atoi(ptrLen);
os_printf("Binary length: %d\r\n", upgrade->content_len);
} else {
// fail, not a valid http header/non-200 response/etc.
rboot_ota_deinit();
return;
}
} else {
// not the first chunk, process it
// not the first chunk, process it
os_printf(".");
if (upgrade->col_cnt++ > 40) {
upgrade->col_cnt = 0;
os_printf(" %d KB\r\n", upgrade->total_len/1024);
}
upgrade->total_len += length;
if (!rboot_write_flash(&upgrade->write_status, (uint8*)pusrdata, length)) {
// write error
@@ -128,6 +151,7 @@ static void ICACHE_FLASH_ATTR upgrade_recvcb(void *arg, char *pusrdata, unsigned
// check if we are finished
if (upgrade->total_len == upgrade->content_len) {
system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
os_printf("\r\nUpdate completed\r\n", upgrade->total_len/1024);
// clean up and call user callback
rboot_ota_deinit();
} else if (upgrade->conn->state != ESPCONN_READ) {
@@ -183,7 +207,7 @@ static void ICACHE_FLASH_ATTR upgrade_connect_cb(void *arg) {
// http request string
request = (uint8 *)os_malloc(512);
if (!request) {
to_console("No ram!\r\n");
os_printf("No ram!\r\n");
rboot_ota_deinit();
return;
}
@@ -201,7 +225,7 @@ static void ICACHE_FLASH_ATTR upgrade_connect_cb(void *arg) {
// connection attempt timed out
static void ICACHE_FLASH_ATTR connect_timeout_cb() {
to_console("Connect timeout.\r\n");
os_printf("Connect timeout.\r\n");
// not connected so don't call disconnect on the connection
// but call our own disconnect callback to do the cleanup
upgrade_disconcb(upgrade->conn);
@@ -236,9 +260,9 @@ static const char* ICACHE_FLASH_ATTR esp_errstr(sint8 err) {
// call back for lost connection
static void ICACHE_FLASH_ATTR upgrade_recon_cb(void *arg, sint8 errType) {
to_console("Connection error: ");
to_console(esp_errstr(errType));
to_console("\r\n");
os_printf("Connection error: %s\r\n", esp_errstr(errType));
//os_printf(esp_errstr(errType));
//os_printf("\r\n");
// not connected so don't call disconnect on the connection
// but call our own disconnect callback to do the cleanup
upgrade_disconcb(upgrade->conn);
@@ -248,9 +272,9 @@ static void ICACHE_FLASH_ATTR upgrade_recon_cb(void *arg, sint8 errType) {
static void ICACHE_FLASH_ATTR upgrade_resolved(const char *name, ip_addr_t *ip, void *arg) {
if (ip == 0) {
to_console("DNS lookup failed for: ");
to_console(config.ota_host);
to_console("\r\n");
os_printf("DNS lookup failed for: %s\r\n", config.ota_host);
//os_printf(config.ota_host);
//os_printf("\r\n");
// not connected so don't call disconnect on the connection
// but call our own disconnect callback to do the cleanup
upgrade_disconcb(upgrade->conn);
@@ -291,7 +315,7 @@ bool ICACHE_FLASH_ATTR rboot_ota_start(ota_callback callback) {
// create upgrade status structure
upgrade = (upgrade_status*)os_zalloc(sizeof(upgrade_status));
if (!upgrade) {
to_console("No ram!\r\n");
os_printf("No ram!\r\n");
return false;
}
@@ -315,13 +339,13 @@ bool ICACHE_FLASH_ATTR rboot_ota_start(ota_callback callback) {
// create connection
upgrade->conn = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (!upgrade->conn) {
to_console("No ram!\r\n");
os_printf("No ram!\r\n");
os_free(upgrade);
return false;
}
upgrade->conn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
if (!upgrade->conn->proto.tcp) {
to_console("No ram!\r\n");
os_printf("No ram!\r\n");
os_free(upgrade->conn);
os_free(upgrade);
return false;
@@ -338,7 +362,7 @@ bool ICACHE_FLASH_ATTR rboot_ota_start(ota_callback callback) {
} else if (result == ESPCONN_INPROGRESS) {
// lookup taking place, will call upgrade_resolved on completion
} else {
to_console("DNS error!\r\n");
os_printf("DNS error!\r\n");
os_free(upgrade->conn->proto.tcp);
os_free(upgrade->conn);
os_free(upgrade);
+1 -1
View File
@@ -27,7 +27,7 @@ extern "C" {
// general http header
#define HTTP_HEADER "Connection: keep-alive\r\n\
Cache-Control: no-cache\r\n\
User-Agent: rBoot-Sample/1.0\r\n\
User-Agent: rboot-ota/1.0\r\n\
Accept: */*\r\n\r\n"
/* this comment to keep notepad++ happy */
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef _USER_CONFIG_
#define _USER_CONFIG_
#define ESP_REPEATER_VERSION "V2.0.0"
#define ESP_REPEATER_VERSION "V2.0.1"
#define LOCAL_ACCESS 0x01
#define REMOTE_ACCESS 0x02