ESP8266 SIP Integration / Problem mit Truncated / Fragementet Paketen

Hallo Zusammen,

ich bin gerade dabei ein Busylight für die 3CX Telefonanlage unserer Firma zu entwickeln und wollte dies auf der Basis eines NODEMCU mit angeschlossener LED realisieren. Auch interessant hierbei wäre der Anschluss von Relaikarten für Zusatzklingeln in lauten Industrieumgebungen.

Aktuell kann ich mich schon an der Anlege abmelden und eine SUBSCRIBE Message absenden woraufhin ich die NOTIFY Messages bei Statiänderungen erhalte, die ich entsprechend auswerte und somit die LEDs ansteuere.

Leider habe ich nun das Problem, dass die NOTIFY Messages teils sehr lange sind und die MTU von 1500 überschreiten und deshalb geteilt / Truncaded werden.
Seitens der 3CX Telefonanlage habe ich hier keinen Handlungsspielraum und kann hier nichts anpassen und hoffe, dass mir auf diesen Post jemand aus der Community einen hilfreichen Tipp geben kann.

Die Messages werden via Wireshark als Truncaded oder Fragmentet Pakete dargestellt. Sobald ich die Daten Seriell aus dem Nodemcu erhalte sehe ich, dass diese eigentlich eigenständige Pakete sind. Ich habe bereits versucht die Pakete zusammenzuführen, jedoch ohne Erfolg, da hier teils nicht zusammengehörige Pakte zusammengeführt werden.

Als Library verwende ich die Standard WiFiUdp Library aus der Arduino Konsole. Einen Befehl oder Flag in dieser Library der dazu führt das ich solche zusammengesetzten Pakete behandeln oder gar korrekt zusammenführen kann, habe ich leider nicht gefunden. Auch einige online Recherchen waren erfolglos, da sich die Posts in der Regel auf das Senden solcher Pakete beziehen.

Für den Zusammenbau dieser Pakete habe ich folgenden Code geschrieben welcher leider nur mittelprächtig und unzuverlässig funktioniert, da ich teils neue UDP Pakete erhalte bevor das eigentlich zu erwartende zweite zugehörige UDP Paket eintrifft:

int packetSize = 0;
packetSize = Udp.parsePacket();
  

  if ( packetSize > 0 ) {                                                    // Buffers löschen
    acSipIn_buff[0] = '\0';

    for (int i = 0; i < 1500; i++) {
      acSipIn_buff[i] = '\0';
    }

    Udp.read(acSipIn_buff, packetSize);                  // Daten in Buffer einlesen
    Serial.print("acSipIn :");                                           // ausgabe der bestehenden Daten 
    Serial.println(strlen(acSipIn));
    Serial.print("acSipIn_buff :");                               // Ausgabe des neu eingelesenen Buffers
    Serial.println(strlen(acSipIn_buff));

    if (strlen(acSipIn) + strlen(acSipIn_buff) < 2500) {                         // Wenn Summe der Buffer kleiner als 2500Byte Daten zusammenführen
      memcpy(acSipIn + strlen(acSipIn),  acSipIn_buff,   strlen(acSipIn) + strlen(acSipIn_buff) );
    } else {
      Serial.println("Drop Packet")                                                             // Sonst Daten verwerfen
      for (int i = 0; i < 3000; i++) {
        acSipIn[i] = '\0';
      }
    }

if (acSipIn_buff[packetSize - 1] == '\n') {                                                // Wenn  der Buffer, also angenommen das letzte Paket auf \n endet soll das Packet verarbeitet werden
      if ( packetSize > 0)
      {
        Serial.println(strlen(acSipIn));
          // Ausgabe der Empfangenen Packetdaten
          if ( packetSize > 0) {
            Serial.printf("\r\n----- read %i bytes from: %s:%i ----\r\n", (int)packetSize, remoteIp.toString().c_str(), Udp.remotePort());
            Serial.print(acSipIn);
            Serial.printf("----------------------------------------------------\r\n");
                  }
        HandleUdpPacket();                                                                           // Routine zum verarbeiten 
      }
   }

Das Paket von meinem Testtelefon sieht wie folgt aus:

Für Ideen oder Ratschläge bin ich sehr dankbar.

umso mehr ich drüber nachdenke und lese, desto weniger glaube ich dass es Sinn macht UDP Pakete zu senden, die größer sind als die kleinste MTU in der kompletten LAN infrastruktur.

https://github.com/espressif/arduino-esp32/issues/3874

https://serverfault.com/questions/246508/how-is-the-mtu-is-65535-in-udp-but-ethernet-does-not-allow-frame-size-more-than

https://stackoverflow.com/questions/38723393/can-udp-packet-be-fragmented-to-several-smaller-ones
...

Bist Du Dir sicher, dass die Anlage wirklich UDP und nicht TCP spricht? TCP sollte die Pakete zusammen setzen.

Gruß Tommy

Hallo noiasca,

naja über Sinn und Unsinn kann man hier streiten aber Fakt ist jedoch das ich dies nicht ändern kann da mir die Telefonanlage diese so sendet und ich hier keine Anpassung vornehmen kann.

Den Mitschnitt den ich in meinem Hauptpost angehängt habe stammte von einem SNOM Telefon welches wohl die Daten korrekt zusammensetzen kann. Irgendeinen Weg muss es doch geben?

@Tommy56 : Ja ich denke schon das es UDP Pakete sind. In der Telefonanlage kann ich zwar auf TCP umstellen aber die Pakete bleiben identisch. Ich bin sowieso der Meinung das SIP standardmäßig über UDP läuft.

TCP hätte den Vorteil, dass ein TCP-Stack die fragmentierten Pakete selbst wieder zusammen setzen sollte. UDP ist fire and forget. Den Rest muss die Anwendung machen.
Da wird Dir wohl nichts anderes übrig bleiben, als die Pakete zu sniffen (z.B. Wireshark) und zu schauen, ob da irgendwo eine Sequencenummer drin ist.

Gruß Tommy

Also ich habe nun nach euren Tipps alles auf TCP umgebaut und die Anmeldung an der 3CX Telefonanlage funktioniert normal. Auch die SUBSCRIBE Messages wurden korrekt akzeptiert.
In der Telefonanlage gab es auch eine Option, dass ich TCP auswählen konnte.

Leider erhalte ich jedoch seit der Umstellung auf TCP keine NOTIFY Messages mehr die ich auswerten könnte. Ich gehe davon aus, dass mir die 3CX keine NOTIFY Pakete via TCP zurücksenden will. Ich habe das ganze auch nochmal mit Wireshark überprüft aber auch dort sehe ich keine eingehenden Pakete.

Anschließend habe ich nochmals die UDP Konfiguration in den ESP geladen und alles mit Wireshark mitgesnifft. Eine Sequenz ID oder ähnliches konnte ich nicht finden.

Ich habe nochmal einige Optimierungen im Code vorgenommen und jetzt läuft es via UDP einigermaßen stabil. Eine Optimallösung ist das jedoch nicht.

Eventuell hat ja noch jemand eine Idee?