Fethi Polat 1
Fethi Polat
xranzei 1
xranzei
Bvural41 1
Bvural41
kralhakan2009 1
kralhakan2009
noisiv 1
noisiv
Manwe Work 1
Manwe Work
Vahsi Uzman 1
Vahsi Uzman
Cannn6161 1
Cannn6161
Hikaye Ekle
Reklam vermek için turkmmo@gmail.com

P2P VE CLIENT UNKNOWN HEADER SYSERRI ARKAPLANI

  • Konuyu başlatan Konuyu başlatan victory80
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 11
  • Görüntüleme Görüntüleme 2K

victory80

Level 2
Üye
Katılım
12 Nis 2019
Konular
25
Mesajlar
87
Çözüm
5
Online süresi
28d 18h
Reaksiyon Skoru
24
Altın Konu
0
TM Yaşı
7 Yıl 1 Ay 28 Gün
Başarım Puanı
84
MmoLira
4,247
DevLira
42
Ticaret - 0%
0   0   0

ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!

Merhaba;

Bir süredir oyuncularımı rahatsız eden client kapanma sorunları hakkında çalışmalar yapıyorum.
Bu sorunların kökeni; herhangi bir client crashı değil, clientin server tarafından yollanan paketleri düzgün bir şekilde yakalayamamasında yatıyor.

Paket yapısında oynama yapılmamış server fileslerde ve daha fazlasında, bu başarısızlık sonrasında client çözümü, kendini
PostQuitMessage(0) kullanarak kapamakta buluyor:
1723129330253.png


Çözüm her ne kadar ilk bakışta gereksiz görünse de, clientteki paket buffer yapısının bu noktadan sonra bozulduğu ve kendisini hali hazırda düzeltemeyecek yapıda olduğu için, bu çözümü şuanlık en iyi çözüm olarak yorumladım.

Bu çözüme benzer olarak, P2P yoluyla iletişim kuran gameler arasında da herhangi bir tanımlanamayan header bulunduğunda, yani game syserr lerimize UNKNOWN HEADER düştüğünde, gameler çözümü birbiri arasındaki soketlerini kapatmakta buluyor.
Fakat buradaki fark; P2P konusunda yaşanan header tanımsızlığı, en basitinde packet_info.cpp'de tanımlanmayan headerlar ya da büyük paketli buffered paketler sayesınde oluşuyor olmasıdır.

Zaman zaman yaşadığımız P2P kopmaları da tam olarak gamelerimize düşen UNKOWN HEADER syserrlerinden sonra yaşanıyor. Neyseki P2P kopmalarının analizi konusunda çözüm genelde basit. En son yollanan yüksek boyutlu paketleri loglamak ve boyutu indirgemek bu iş için yeterli bir çözüm.

Clientim için yaptığım çalışmalarda, kapanma sorunu yaşayan oyuncular için, serverden teslim aldıkları son paketleri loglayacak bir sistem yazdım.
Bu konuyu açmamdaki amaç, konuyla ilgilenenlerle analizlerimi paylaşıp çözüm için sizlerle bilgi paylaşımı yapmaktır.

Oluşturduğum log sistemindeki amaç, kapanmadan hemen önce servere bilgi gönderilip, oyuncunun soketine son yollanan 10 paketin server tarafında loglanmasındır:


1723129346005.png


Server tarafında saklanan bazı logları paylaşıyorum:

1723129357411.png


Sorunu yaşayan son oyuncuların aldığı headerler gösteriyorki, spesifk olarak son yollanan header bu soruna sebep olmuyor. Başka bir deyişle spesifik bir header bu soruna sebep olmuyor, ya da oluyor mu?

Bu gözlemlerden sonra, hatayı clientlere yollanan büyük boyutlu paketlerde aradım. Bu paketlerin en büyüğü 15814 byte ile offline shop sistemimdeki bir yapıydı.
Ve bu boyutun gerçekten sorun yaratacağını düşünmeyerek farklı bir yorum aramaya başladım. Bir şey veya bir şeyler, clientteki paket sequence yapısını sekteye uğratıyor olmalı diye düşündüm. Yani aslında sorun dolaylı olarak gerçekleşiyor gibi görünüyor.

Ekstra olarak, code base'mde herhangi spesifik bir paket yapısının yanlış tanımlandığını düşünmüyorum. Bu düşüncemin sebebi de bu sorunu yaşayan kitlenin tüm oyuncularım değil yaklaşık %15'lik bir dilimin olması. Client rapor loglarında ismi geçen birkaç oyuncuma ulaştım ve bu sorunu oyunda herhangi bir aksiyom yaşamadan yani ilk girişte login ekranında bile yaşadıklarını söylediler.

Bu biraz kafa karıştıcı. Hala sorunun kaynağını aramaktayım. Herhangi bir tecrübesi olan, bir şeyler paylaşmak isteyenleri konuya katkı yapmaya davet ediyorum.
 

En Çok Reaksiyon Alan Mesajlar

İnternet bağlantısı stabil oyuncular için bu sorunun tespiti için nasıl bir yol izleyebileceğimiz konusunda kararsızım açıkçası.

temel olarak bahsettiğim şekilde paket gönderim sisteminin düzenlenmesi gerekiyor. mevcut haliyle en temel olarak CInputProcessor::Process fonksiyonunda paket işleme sisteminin nasıl çalıştığını görebilirsiniz. mevcut haliyle sadece header idini arayıp onun tanımlı olduğu paket boyutu kadar işleme sokuyor.

for (m_iBufferLeft = iBytes; m_iBufferLeft > 0;)
{
BYTE bHeader = (BYTE) *(c_pData);
const char * c_pszName;

if (bHeader == 0)
iPacketLen = 1;
else if (!m_pPacketInfo->Get(bHeader, &iPacketLen, &c_pszName))
{
sys_err("UNKNOWN HEADER: %d, LAST HEADER: %d(%d), REMAIN BYTES: %d, fd: %d",
bHeader, bLastHeader, iLastPacketLen, m_iBufferLeft, lpDesc->GetSocket());
//printdata((BYTE *) c_pvOrig, m_iBufferLeft);
lpDesc->SetPhase(PHASE_CLOSE);
return true;
}

if (m_iBufferLeft < iPacketLen)
return true;

bu kısmı daha güvenli bir şekilde düzenlemeden bu sorunun önüne geçemezsiniz, örnek olarak kapsamlı bir şekilde;
for (m_iBufferLeft = iBytes; m_iBufferLeft > 0;)
{
if (m_iBufferLeft < sizeof(PacketHeader))
{
return true; // Not enough data to read the header
}

const PacketHeader* packetHeader = reinterpret_cast<const PacketHeader*>(c_pData);
uint16_t packetId = packetHeader->id;
uint32_t packetSize = packetHeader->size;

if (m_iBufferLeft < packetSize)
{
return true; // Not enough data to read the entire packet
}

std::string strName;
bool bIsStatic = false;

if (!m_pPacketInfo->Get(packetId, packetSize, strName, bIsStatic))
{
LogUnknownHeader(lpDesc, packetId);
lpDesc->SetCloseReason("WRONG_PACKET_HEADER");
lpDesc->SetPhase(PHASE_CLOSE);
return true;
}

if (bIsStatic && !ValidatePacketSize(packetId, packetSize, lpDesc))
{
lpDesc->SetCloseReason("WRONG_PACKET_LENGTH");
lpDesc->SetPhase(PHASE_CLOSE);
return true;
}

m_pPacketInfo->Start();
int32_t iExtraPacketSize = Analyze(lpDesc, packetId, c_pData + sizeof(PacketHeader));

ve header kısmı için paket verisinden bağımsız olarak mevcut halindeki "TDynamicSizePacketHeader" gibi bir header üzerinden veriyi tanımlamanız gerekir örnek olarak;
#pragma pack(push, 1)
struct PacketHeader
{
uint16_t id; // Packet ID
uint32_t size; // Size of the packet
uint32_t hash; // Hash for integrity check
uint32_t order_sec_id; // Order section identifier (aka. sequence)
uint8_t flags; // Flags for encryption/compression

PacketHeader(uint16_t id, uint32_t size, uint32_t hash, uint32_t order_sec_id, uint8_t flags) :
id(id), size(size), hash(hash), order_sec_id(order_sec_id), flags(flags)
{
}
};
#pragma pack(pop)

bütün network transferini bu şekilde yaparsanız, asio gibi nispeten daha güvenli bir yapı üzerinden iletişim sağlarsanız ve bufferları buradan yönetirseniz, şifreleme içinde bufferların işleme mantığını tekrar gözden geçirirseniz hiçbir problem yaşamazsınız.
bu sorunun belli başlı bir sebebi yok genellikle server'da meydana gelebiliyor özellikle farkettiğim kadarıyla paket sistemi tamamen düzgün olsa bile phase uyuşmazlığından ya da hilelerin gönderdiği hatalı verilerden kaynaklı meydana gelmesi olası. ancak client kısmında tetiklenen unknown packet headerlar pek normal bir durum değil yüksek ihtimalle hatalı paket yapısı ya da eşleşmeyen veri kaynaklı bir durumdan kaynaklanıyodur, paketleri ortak bir dosyadan ve client&server her iki işletim sistemindede ortak boyutlu veri tipleriyle tanımlamadıkça çözülmesi imkansız ancak bu da kesin çözüm değil default halindeki buffer yapısı, şifrelemeler, sequence her biri problemli halde üzerine network tarafında herhangi bir wrapper kullanmadan client&server her iki taraftada direkt os seviyesinde apiler ile iletişim kurduğundan sistem yapısı temel olarak bozuk diye özetleyebiliriz

ek olarak yaptığınız log düzenlemeside mantık dışı, client'e son gelen paket değil ondan önce gelenin headerını yazdırıyosunuz onun yerine desc'e son gönderilen paket verisini server'da tutarak log paketi gittiğinde o veri ile eğer verilerin şifresiz hali eşleşirse asıl sorunlu pakete ulaşabilirsiniz ancak salt halde verinin bozuk olmama ihtimalide mevcut bahsettiğim gibi veriyi saklama aşamasında(buffer) ya da gönderirken(şifreleme) ya da gönderdiğinde(network) bozulmuşta olabilir bunu mevcut haliyle tespit edemezsiniz. bunun için tamamen paket yapısını değiştirip gönderilen verilerin tamamını mevcut dinamik paket yapısı gibi düzenleyip hash veriside ekleyip onu karşılaştırmanız gerekir, basitçe; "header(veri boyutu, veri hashi) + veri" şeklinde.
orjinal metin2de bile paket hatası doluyken pvplerde en aza indirgenmesi bile normal ama %100 indirgenmedi
metin2 developerleri bile çözüm sağlıyamamışken zor yani bu sorunun bitmesi
üstüne knight vesayre oyunlardada bu sorun yaşanıyor direk oyun kapanıyor veya oyuna girişte direk kapanabiliyor client
crash sorununa çare bulunmadı çünkü pc'den pc'ye değişiyor herkeste yaşanmıyor bazı sorunlar
 
Ben bu konu hakkında biraz kafa yormuştum TCP protokolü ve Paketli iletişimler hakkında vs. Şimdi paket tabanlı iletişimlerde şunlara dikkat etmek gerekiyor.

1: Paket boyutu uyuşmazlığı
2: Veri bozulması(İletim sırasında)
3: Yanlış paket sıralaması(TCP protokolüne uygun sıralanmaması)
4: Eksik veya Hatalı başlık(header) bilgisi
5: Beklenmeyen veri tipleri
6: Yetersiz Hata yöntemi

Mesela yetersiz hata yönetimi hakkında örneğin bir paketin beklenenden büyük olması durumunda ve bu hata yakalanıp düzgün bir şekilde işlenmezse oyundan atma yaşanır.
 
bu sorunun belli başlı bir sebebi yok genellikle server'da meydana gelebiliyor özellikle farkettiğim kadarıyla paket sistemi tamamen düzgün olsa bile phase uyuşmazlığından ya da hilelerin gönderdiği hatalı verilerden kaynaklı meydana gelmesi olası. ancak client kısmında tetiklenen unknown packet headerlar pek normal bir durum değil yüksek ihtimalle hatalı paket yapısı ya da eşleşmeyen veri kaynaklı bir durumdan kaynaklanıyodur, paketleri ortak bir dosyadan ve client&server her iki işletim sistemindede ortak boyutlu veri tipleriyle tanımlamadıkça çözülmesi imkansız ancak bu da kesin çözüm değil default halindeki buffer yapısı, şifrelemeler, sequence her biri problemli halde üzerine network tarafında herhangi bir wrapper kullanmadan client&server her iki taraftada direkt os seviyesinde apiler ile iletişim kurduğundan sistem yapısı temel olarak bozuk diye özetleyebiliriz

ek olarak yaptığınız log düzenlemeside mantık dışı, client'e son gelen paket değil ondan önce gelenin headerını yazdırıyosunuz onun yerine desc'e son gönderilen paket verisini server'da tutarak log paketi gittiğinde o veri ile eğer verilerin şifresiz hali eşleşirse asıl sorunlu pakete ulaşabilirsiniz ancak salt halde verinin bozuk olmama ihtimalide mevcut bahsettiğim gibi veriyi saklama aşamasında(buffer) ya da gönderirken(şifreleme) ya da gönderdiğinde(network) bozulmuşta olabilir bunu mevcut haliyle tespit edemezsiniz. bunun için tamamen paket yapısını değiştirip gönderilen verilerin tamamını mevcut dinamik paket yapısı gibi düzenleyip hash veriside ekleyip onu karşılaştırmanız gerekir, basitçe; "header(veri boyutu, veri hashi) + veri" şeklinde.
 
Son düzenleme:
bu sorunun belli başlı bir sebebi yok genellikle server'da meydana gelebiliyor özellikle farkettiğim kadarıyla paket sistemi tamamen düzgün olsa bile phase uyuşmazlığından ya da hilelerin gönderdiği hatalı verilerden kaynaklı meydana gelmesi olası. ancak client kısmında tetiklenen unknown packet headerlar pek normal bir durum değil yüksek ihtimalle hatalı paket yapısı ya da eşleşmeyen veri kaynaklı bir durumdan kaynaklanıyodur, paketleri ortak bir dosyadan ve client&server her iki işletim sistemindede ortak boyutlu veri tipleriyle tanımlamadıkça çözülmesi imkansız ancak bu da kesin çözüm değil default halindeki buffer yapısı, şifrelemeler, sequence her biri problemli halde üzerine network tarafında herhangi bir wrapper kullanmadan client&server her iki taraftada direkt os seviyesinde apiler ile iletişim kurduğundan sistem yapısı temel olarak bozuk diye özetleyebiliriz

ek olarak yaptığınız log düzenlemeside mantık dışı, client'e son gelen paket değil ondan önce gelenin headerını yazdırıyosunuz onun yerine desc'e son gönderilen paket verisini server'da tutarak log paketi gittiğinde o veri ile asıl sorunlu pakete ulaşabilirsiniz ancak salt halde verinin bozuk olmama ihtimalide mevcut bahsettiğim gibi veriyi saklama aşamasında(buffer) ya da gönderirken(şifreleme) ya da gönderdiğinde(network) bozulmuşta olabilir bunu mevcut haliyle tespit edemezsiniz. bunun için tamamen paket yapısını değiştirip gönderilen verilerin tamamını mevcut dinamik paket yapısı gibi düzenleyip hash veriside ekleyip onu karşılaştırmanız gerekir, basitçe; "header(veri boyutu, veri hashi) + veri" şeklinde.
Evet paket düzenlemeleri konusunda eksikliğin ben de farkındayım. Ortak bir paket .header dosyası tanımlanması fikri de oldukca mantıklı.

Detay olarak, göz gezdirdiğim bazı server fileslerde geliştiriciler tarafından client taraflı düzenlemelere gidilmiş. Düzenleme gerektiren bir yerler olduğu aşikar.

Sorunun kesinlikle çözülebilir olduğundan emin değilim fakat server-client arasında veri uyuşmazlığı olduğunu da sanmıyorum.
Veri uyuşmazlığı sorunu var olsaydı safe user diyebilecegimiz herhangi bir tool kullanmadan oyununu oynayan oyuncular bu sorundan bolca nasibini alırdı. Fakat sorunu yaşayan yüzdelik dilim nadir diyebileceğimiz kadar az. (En azından benim dosyalarımda yaptığım gözlemlere göre.)

Log düzenlemesinde zaten bahsettiğiniz gibi son gönderilen de dahil 10 paket gösteriliyor. O düzenlemedeki amaç eğer spesifik olarak bir header sorun yaratıyorsa bunu tespit edeilmem içindi. Fakat gördüğünüz gibi genellikle son gönderilen header MOVE paketine ait ya da alakasız paketler. Dolayısıyla spesifik bir paket, bu hataya sebep oluyor ve direkt clienti kapatıyor diyemeyiz. Yani 'sorunlu paket' olarak bahsettiğiniz bir paket gerçekten var mı emin değilim.

Bahsettiğiniz, paketler buffer ve network aşamasındayken bozulması sorunu meydana gelmesi muhtemel evet. İnternet bağlantısı stabil oyuncular için bu sorunun tespiti için nasıl bir yol izleyebileceğimiz konusunda kararsızım açıkçası.
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst