Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Опкоды (http://mangos.ytdb.ru/forumdisplay.php?f=36)
-   -   PACKED данные (http://mangos.ytdb.ru/showthread.php?t=1824)

Йоха 18.07.2010 14:20

PACKED данные
 
как известно некоторые опкоды приходят не по одному, а пачками, как например SMSG_COMPRESSED_MOVES, COMPRESSED_UPDATE_OBJECT...
Где можно глянуть как распаковать такие данные ? или подкиньте кусок кода.

alien 18.07.2010 14:52

Дак тамже простейший zlib.
Или ты не про это?

Йоха 18.07.2010 15:11

Про то.
Просто я никогда не использовал zlib библиотеку и не знаю что там с чем едят

10.05.2011 19:02

пусть я буду некропостером, но блин, из-за "простейший zlib" я пол дня мозг выносил с проблемой декодирования. Хорошо потом стал проверять, отсекая первые байты.
что то вроде:
1. uint32 - размер данных после декодирования
2. 2 байта относятся к zlib , никакой полезной нагрузки не несут.
3. остальное - сжатые данные, без заголовков

зы в подтверждение у TOM_RUS-а увидел распаковку :D

Йоха 10.05.2011 19:10

ну да, так и есть, сперва идет DWORD - размер данных после распаковки, а потом кусок данных который нужно отдать для обработки функции inflate
Я тогда сразу написал класс для распаковки:
Код:

bool CZlib::decompress(BYTE* in_buffer, int in_size, int out_size)
{
        m_out_buffer = new BYTE[out_size];
        if (!m_out_buffer)
        {
                return false;
        }
        m_zstream.next_in = in_buffer;
        m_zstream.avail_in = in_size;
        m_zstream.next_out = m_out_buffer;
        m_zstream.avail_out = out_size;
        if (inflateInit(&m_zstream) == Z_OK)
        {
                if (inflate(&m_zstream, Z_FINISH) == Z_STREAM_END)
                {
                        return true;
                }
                inflateEnd(&m_zstream);
        }
        return false;
}

И использовался он так:
Код:

void CDataHandler::on_SMSG_COMPRESSED_UPDATE_OBJECT(BYTE* _packet, DWORD _len)
{
        int unpacked_len = 0;
        memcpy(&unpacked_len, _packet, 4);
        CZlib zlib;
        if (zlib.decompress(_packet + 4, _len - 4, unpacked_len))
        {
                parse_update(zlib.get_data());
        }
}


RomanRom2 10.05.2011 19:24

спросил бы :)
все правильно сделал. только inflateEnd надо еще на Z_OK проверять.

Йоха 10.05.2011 19:32

Я сейчас точно не помню, но судя по своему же коду вызов inflateEnd не нужен, ибо возврат из функции идет сразу после проверки (inflate(&m_zstream, Z_FINISH) == Z_STREAM_END)
насколько я помню документацию на злиб, то если вызов inflate завершился кодом Z_STREAM_END, то данные полностью распакованы.
В данном случае поскольку нам известна заранее длина распакованных данных, то можно сразу выделять буфер нужной длины.
Что у меня в коде и делается, так что строчку с inflateEnd надо удалить нафиг -)

RomanRom2 10.05.2011 19:52

представь, что будет, если тебе придется обрабатывать битый пакет или пакет с ошибками Lordronn =)
проверять надо всё, включая переполнения буфера и inflateEnd.

и вообще строго говоря, кто сказал что надо сразу inflate(&m_zstream, Z_FINISH) вызывать? пакеты с ачивками в волке очень большие могут быть. размер m_zstream.avail_out делать больше одной страницы - не по феншую как бэ... но можно. в спецификации там WORD был вроде (тоже не помню), но я пробовал и longword в полмега и распаковывается все за один раз без проблем в принципе. но в таких случаях могут возникать ошибки stack overflow когда прога разрастется и хрен ты их найдешь сходу =)

Йоха 10.05.2011 19:56

ну в идеале конечно да

RomanRom2 10.05.2011 20:02

а мы разве не к нему стремимся?

Йоха 10.05.2011 20:07

Цитата:

Сообщение от RomanRom2 (Сообщение 22120)
и вообще строго говоря, кто сказал что надо сразу inflate(&m_zstream, Z_FINISH) вызывать? пакеты с ачивками в волке очень большие могут быть. размер m_zstream.avail_out делать больше одной страницы - не по феншую как бэ... но можно. в спецификации там WORD был вроде (тоже не помню), но я пробовал и longword в полмега и распаковывается все за один раз без проблем в принципе. но в таких случаях могут возникать ошибки stack overflow когда прога разрастется и хрен ты их найдешь сходу =)

С этим тоже согласен, у меня сперва была такая мысля, сделать универсальную функцию которая корректно обрабатывала бы данные любого размера, но потом решил не заморачиваться и оставить как есть =)))
Для моего случая этого было достаточно

Lordronn 10.05.2011 20:16



Текущее время: 17:19. Часовой пояс GMT +3.

ru-mangos.ru - Русское сообщество MaNGOS