habe noch eine Stelle in der httpd.c gefunden, die zu einem fehlerhaften Seitenaufbau führen kann.
Folgendes Szenario:
Der Webserver soll nach Eingabe diverser Daten in einem POST-Formular diese ins EEPROM speichern. Nach dem Absenden des Formulars im Webbrowser wird der POST-Header zum Webserver geschickt. Dieser verarbeitet nun alle POST-Variablen und speichert sie in's EEPROM. Mein ungeduldiger Browser schickt aber die POST-Anfrage ERNEUT, bevor der Webserver mit seinem Header antworten kann, da er durch die Menge der Daten zu lange braucht, um diese abzuarbeiten.
Das Resultat: Der Webserver schickt nun den Header und erzeugt im Anschluss sofort das erste Datenpaket (springt also in die Routine httpd_data_send, ohne auf ein ACK zu warten). Das Problem ist, dass beide Pakete (header unddas erste Datenpaket) die gleiche Sequenznummer besitzen. Für den Browser ist das erste Datenpaket somit eine Retransmission des Header-Pakets. Der Browser nimmt nun den Inhalt des Header Pakets und setzt ihn mit dem Inhalt aus dem ersten Datenpaket zusammen, der die Länge des Header-Paketes überschreitet. Das Resultat ist, dass vom ersten Datenpaket die ersten (rund 50) Zeichen fehlen.
Die Ursache:
in der httpd-Routine wird die Routine "httpd_header_check" so lange ausgeführt, bis der app_status der TCP-Anwendung größer 2 ist.
Passt der eintreffende Header vom Browser in ein Paket (was i.d.R der Fall ist), wird der App-Status sofort auf 2 gesetzt.
Das nun eintreffende Retransmission-Header-Paket des Browsers löst im stack (tcp_socket_process) eine Erhöhung auf 3 aus, setzt aber gleichzeitig die Zähler für Seq und Ack wieder zurück. Der Webserver springt nun von "httpd_header_check" nach "httpd_data_send" und füllt das erste Paket mit Daten, ohne jemals ein ACK auf seinen Header empfangen zu haben. Der Browser erhält ein Datenpaket, was die gleiche ACK-Nummer wie der zuvor erhaltene Header hat und setzt somit beides zusammen.
Die Lösung:
Die Überprüfung, ob ein ACK-Paket empfangen wurde, sollte eigentlich durch die if-Abfrage
Code: Alles auswählen
if (tcp_entry[index].app_status > 2 && tcp_entry[index].app_status < 0xFFFE)
Ich habe die Zeile einfach um den folgenden Parameter erweitert:
Code: Alles auswählen
if (tcp_entry[index].app_status > 2 && tcp_entry[index].app_status < 0xFFFE && tcp_entry[index].status == ACK_FLAG)
Ich weiß, ist recht speziell das Problem, aber ich bin froh, es gefunden zu haben
Vielleicht hilft's ja jemandem
Lg
myjack