Guida Risolvere "Unknown packet header" e tutti gli errori relativi ai pacchetti

Arves100

Utente Emerald
15 Febbraio 2011
515
46
378
418
Ultima modifica:
Benvenuti disperati, nel tentativo di sperare la completa abolizione di errori relativi ai pacchetti, oggi vi lascio questa "mini" guida o comunque metodo per risolvere gli amati problemi dei pacchetti.
Ovviamente la guida non può mancare di qualche classica spiegazione cosi per rendervi la ricerca della pappa pronta più difficile.

Cos'è un pacchetto e come viene usato su Metin2?
Un pacchetto è, in maniera molto grossolana, una serie di informazioni scambiati attraverso la rete nel nostro caso un Client ed un Server di Metin2.
Pensate ad esempio a quando premete il Tasto spazio, il Client invierà una informazione, un pacchetto, che istruirà al server che il player Shiba324 sta attaccando nella mappa.
Lascio il link della pagina di wikipedia per maggiori approfondimenti: https://it.wikipedia.org/wiki/Pacchetto_(reti).

Ogni peccatto deve essere identificato in modo univoco dal client e dal server, altrimenti il client/server non saprebbero che messaggio dei dati rappresentano. Per questo, ci viene aiuto Metin2, l'inizio di ogni pacchetto (BYTE bId contiene un numero identificativo del proprio dato.

La rappresentazione di questi numeri la troviamo all'interno di un blocco enum (esempio PACKET_GC_LOGIN2 definisce il numero di un pacchetto di login), mentre il suo relativo contenuto viene definito all'interno di un blocco struct (nel caso di packet login2 TPacketGCLogin2). Possiamo trovare la definizione dei pacchetti all'interno dei file Packet.h in Client (cartella UserInterface) e Server (cartella game/src).

Esistono due tipi di pacchetti, quelli dinamici e statici, quelli dinamici hanno una lunghezza (esempio inviare un messaggio in Chat) visto che non si sa la effettiva lunghezza del pacchetto (un utente potrebbe scrivere un chat 1 parola o 200).

Pacchetti statici (a dimensione fissa): id + dati
Pacchetti dinamici (a dimensione variabile): id + lunghezza + dati

Una cosa che possiamo notare nel nome dei pacchetti è la loro nomenclatura, essa si utilizza per semplicarci il lavoro e capire subito a chi è destinato questo pacchetto.

Nomenclatura pacchetti:
CG -> Dal client al game (pacchetti ricevuti al server)
GC -> Dal game al client (pacchetti inviati dal server)
GG -> Dal game a game (pacchetti utilizzati per scambiare informazioni tra i vari core utilizzando le porte P2P)

Prima di passare agli errori è necessario definire una funzionalità di Metin2 chiamata Sequenza, essa fa parte del sistema di rete di Metin2 e potrebbe capitarci errori relativi.

Cos'è il sistema di sequenza?
Si tratta di un sistema introdotto più avanti su Metin2 (non sembra essere presente in file prima dei 40k, non ho verificato i 34k).
Il sistema funziona in modo semplice, il client invia un ultimo dato (1 byte) in ogni pacchetto specificato come pacchetto con sequenza, il server verificherà se quest'ultimo dato è corretto.
Il metodo di verifica si basa sui pacchetti inviati/ricevuti dal client e dal server, ogni volta che il client invia un pacchetto incrementerà il dato della sequenza di uno (per un massimo di 32768).
Una volta raggiunto il limite il contatore verrà resettato a 0.
Penso che questo sistema sia stato aggiunto per sicurezza contro i bot? Secondo me non ha troppo senso essendo tutto in TCP.

Ora passiamo alla parte più importante, i due errori molto comuni che riguardano i pacchetti.

Tipologia errore 1:
Unknown packet header: XXX, last: YYY ZZZ

Spiegazione dei numeri:
  • XXX è il pacchetto sconosciuto
  • YYY e ZZZ sono gli ultimi due pacchetti ricevuti prima di questo (molto utile per rintracciare l'ultimo dato nella rete inviata)

Questo errore si può verificare per due motivi:
  1. Avete fatto una modifica e non avete incluso nello switch di PythonNetworkPhaseGame.cpp il riconoscimento del pacchetto
  2. Avete delle grandezze dei pacchetti errati quindi un dato viene erroniamente riconosciuto come un nuovo pacchetto.
Tipologia errore 2:
SEQUENCE XXXXXXX mismatch 0xYY != 0xZZ header KK

Questo errore si può verificare per due motivi:
  1. Avete specificato che il pacchetto usa la sequenza in packet_info.cpp (ultimo valore true/false) e nel client dopo l'invio del pacchetto non è stato aggiunto "SendSequence()" (o viceversa)
  2. Avete delle grandezze dei pacchetti errati quindi un dato aggiuntivo viene riconosciuto come numero di sequenza
Tipologia errore 3:
Qui non abbiamo dei veri e propri syserr ma possiamo vedere il client crashare oppure fare cose strane durante il gioco, oppure vediamo il server/client non processare tutti i dati inviati o ricevuti.

Questo errore si verifica per questo motivo:
  • Avete delle grandezze dei pacchetti errati quindi un dato aggiuntivo viene riconosciuto come numero di sequenza
Consigli generali quando avete errori simili:
  • Se avete le sequenze attive, controllate sempre di aver aggiunto SendSequence e i true o false
  • Controllate SEMPRE che i Packet.h contengano strutture e ID uguali
  • Controllate sempre l'azione che vi causa l'errore cosi saprete subito di chi è la colpa
  • Controllate sempre gli ultimi header inviati, molto spesso si tratta di un byte non inviato alla fine di uno dei due pacchetti
  • Controllate di aver implementato bene i file PythonNetworkPhaseXXXXX (Client) e inputXXXXX (Server)

Pro hack tip: per chi li ha __PACKETDUMP__ e ENABLE_SEQUENCE_SYSTEM sono molto utili.

Buona fortuna.
 
Benvenuti disperati, nel tentativo di sperare la completa abolizione di errori relativi ai pacchetti, oggi vi lascio questa "mini" guida o comunque metodo per risolvere gli amati problemi dei pacchetti.
Ovviamente la guida non può mancare di qualche classica spiegazione cosi per rendervi la ricerca della pappa pronta più difficile.

Cos'è un pacchetto e come viene usato su Metin2?
Un pacchetto è, in maniera molto grossolana, una serie di informazioni scambiati attraverso la rete nel nostro caso un Client ed un Server di Metin2.
Pensate ad esempio a quando premete il Tasto spazio, il Client invierà una informazione, un pacchetto, che istruirà al server che il player Shiba324 sta attaccando nella mappa.
Lascio il link della pagina di wikipedia per maggiori approfondimenti: https://it.wikipedia.org/wiki/Pacchetto_(reti).

Ogni peccatto deve essere identificato in modo univoco dal client e dal server, altrimenti il client/server non saprebbero che messaggio dei dati rappresentano. Per questo, ci viene aiuto Metin2, l'inizio di ogni pacchetto (BYTE bId contiene un numero identificativo del proprio dato.

La rappresentazione di questi numeri la troviamo all'interno di un blocco enum (esempio PACKET_GC_LOGIN2 definisce il numero di un pacchetto di login), mentre il suo relativo contenuto viene definito all'interno di un blocco struct (nel caso di packet login2 TPacketGCLogin2). Possiamo trovare la definizione dei pacchetti all'interno dei file Packet.h in Client (cartella UserInterface) e Server (cartella game/src).

Esistono due tipi di pacchetti, quelli dinamici e statici, quelli dinamici hanno una lunghezza (esempio inviare un messaggio in Chat) visto che non si sa la effettiva lunghezza del pacchetto (un utente potrebbe scrivere un chat 1 parola o 200).

Pacchetti statici (a dimensione fissa): id + dati
Pacchetti dinamici (a dimensione variabile): id + lunghezza + dati

Una cosa che possiamo notare nel nome dei pacchetti è la loro nomenclatura, essa si utilizza per semplicarci il lavoro e capire subito a chi è destinato questo pacchetto.

Nomenclatura pacchetti:
CG -> Dal client al game (pacchetti ricevuti al server)
GC -> Dal game al client (pacchetti inviati dal server)
GG -> Dal game a game (pacchetti utilizzati per scambiare informazioni tra i vari core utilizzando le porte P2P)

Prima di passare agli errori è necessario definire una funzionalità di Metin2 chiamata Sequenza, essa fa parte del sistema di rete di Metin2 e potrebbe capitarci errori relativi.

Cos'è il sistema di sequenza?
Si tratta di un sistema introdotto più avanti su Metin2 (non sembra essere presente in file prima dei 40k, non ho verificato i 34k).
Il sistema funziona in modo semplice, il client invia un ultimo dato (1 byte) in ogni pacchetto specificato come pacchetto con sequenza, il server verificherà se quest'ultimo dato è corretto.
Il metodo di verifica si basa sui pacchetti inviati/ricevuti dal client e dal server, ogni volta che il client invia un pacchetto incrementerà il dato della sequenza di uno (per un massimo di 32768).
Una volta raggiunto il limite il contatore verrà resettato a 0.
Penso che questo sistema sia stato aggiunto per sicurezza contro i bot? Secondo me non ha troppo senso essendo tutto in TCP.

Ora passiamo alla parte più importante, i due errori molto comuni che riguardano i pacchetti.

Tipologia errore 1:
Unknown packet header: XXX, last: YYY ZZZ

Spiegazione dei numeri:
  • XXX è il pacchetto sconosciuto
  • YYY e ZZZ sono gli ultimi due pacchetti ricevuti prima di questo (molto utile per rintracciare l'ultimo dato nella rete inviata)

Questo errore si può verificare per due motivi:
  1. Avete fatto una modifica e non avete incluso nello switch di PythonNetworkPhaseGame.cpp il riconoscimento del pacchetto
  2. Avete delle grandezze dei pacchetti errati quindi un dato viene erroniamente riconosciuto come un nuovo pacchetto.
Tipologia errore 2:
SEQUENCE XXXXXXX mismatch 0xYY != 0xZZ header KK

Questo errore si può verificare per due motivi:
  1. Avete specificato che il pacchetto usa la sequenza in packet_info.cpp (ultimo valore true/false) e nel client dopo l'invio del pacchetto non è stato aggiunto "SendSequence()" (o viceversa)
  2. Avete delle grandezze dei pacchetti errati quindi un dato aggiuntivo viene riconosciuto come numero di sequenza
Tipologia errore 3:
Qui non abbiamo dei veri e propri syserr ma possiamo vedere il client crashare oppure fare cose strane durante il gioco, oppure vediamo il server/client non processare tutti i dati inviati o ricevuti.

Questo errore si verifica per questo motivo:
  • Avete delle grandezze dei pacchetti errati quindi un dato aggiuntivo viene riconosciuto come numero di sequenza
Consigli generali quando avete errori simili:
  • Se avete le sequenze attive, controllate sempre di aver aggiunto SendSequence e i true o false
  • Controllate SEMPRE che i Packet.h contengano strutture e ID uguali
  • Controllate sempre l'azione che vi causa l'errore cosi saprete subito di chi è la colpa
  • Controllate sempre gli ultimi header inviati, molto spesso si tratta di un byte non inviato alla fine di uno dei due pacchetti
  • Controllate di aver implementato bene i file PythonNetworkPhaseXXXXX (Client) e inputXXXXX (Server)

Pro hack tip: per chi li ha __PACKETDUMP__ e ENABLE_SEQUENCE_SYSTEM sono molto utili.

Buona fortuna.
Thanks, al momento giusto!