diff --git a/lib/coopnet/linux/libcoopnet.a b/lib/coopnet/linux/libcoopnet.a index 69d3739b..76981c8f 100644 Binary files a/lib/coopnet/linux/libcoopnet.a and b/lib/coopnet/linux/libcoopnet.a differ diff --git a/src/pc/network/network.c b/src/pc/network/network.c index b55fec96..d942e677 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -309,8 +309,15 @@ void network_send_to(u8 localIndex, struct Packet* p) { if (p->keepSendingAfterDisconnect) { localIndex = 0; // Force this type of packet to use the saved addr } - int rc = gNetworkSystem->send(localIndex, p->addr, p->buffer, p->cursor + sizeof(u32)); - if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; } + u8* buffer = NULL; + u32 len = 0; + packet_compress(p, &buffer, &len); + if (!buffer || len == 0) { + LOG_ERROR("Failed to compress!"); + } else { + int rc = gNetworkSystem->send(localIndex, p->addr, buffer, len); + if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; } + } } p->sent = true; @@ -375,14 +382,16 @@ void network_receive(u8 localIndex, void* addr, u8* data, u16 dataLength) { .buffer = { 0 }, .dataLength = dataLength, }; - memcpy(p.buffer, data, dataLength); + if (!packet_decompress(&p, data, dataLength)) { + LOG_ERROR("Failed to decompress!"); + return; + } if (localIndex != UNKNOWN_LOCAL_INDEX && localIndex != 0) { gNetworkPlayers[localIndex].lastReceived = clock_elapsed(); } // subtract and check hash - p.dataLength -= sizeof(u32); if (!packet_check_hash(&p)) { LOG_ERROR("invalid packet hash!"); return; diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 0596f4f4..a030be48 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -1,8 +1,47 @@ #include +#include #include "../network.h" #include "pc/network/ban_list.h" #include "pc/debuglog.h" +static u32 sCompBufferLen = 0; +static Bytef* sCompBuffer = NULL; + +static void increase_comp_buffer(u32 compressedLen) { + if (compressedLen <= sCompBufferLen && sCompBuffer) { return; } + + if (sCompBuffer != NULL) { free(sCompBuffer); } + + sCompBufferLen = compressedLen; + sCompBuffer = (Bytef*)malloc(sCompBufferLen); +} + +void packet_compress(struct Packet* p, u8** compBuffer, u32* compSize) { + uLong sourceSize = p->dataLength + sizeof(u32); + uLongf compressedLen = compressBound(sourceSize); + increase_comp_buffer(PACKET_LENGTH); + + if (sCompBuffer && compress2((Bytef*)sCompBuffer, &compressedLen, (Bytef*)p->buffer, sourceSize, Z_BEST_COMPRESSION) == Z_OK) { + *compBuffer = sCompBuffer; + *compSize = compressedLen; + } else { + *compBuffer = NULL; + *compSize = 0; + } +} + +bool packet_decompress(struct Packet* p, u8* compBuffer, u32 compSize) { + increase_comp_buffer(PACKET_LENGTH); + if (!sCompBuffer) { return false; } + uLong decompSize = PACKET_LENGTH; + if (uncompress((Bytef*)p->buffer, &decompSize, (Bytef*)compBuffer, compSize) == Z_OK) { + p->dataLength = decompSize - sizeof(u32); + return true; + } else { + return false; + } +} + void packet_process(struct Packet* p) { if (gNetworkType == NT_NONE) { return; } if (p->levelAreaMustMatch) { diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index c74d13e5..85bec426 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -148,6 +148,8 @@ struct LSTNetworkType { }; // packet.c +void packet_compress(struct Packet* p, u8** compBuffer, u32* compSize); +bool packet_decompress(struct Packet* p, u8* compBuffer, u32 compSize); void packet_process(struct Packet* p); void packet_receive(struct Packet* packet); bool packet_spoofed(struct Packet* p, u8 globalIndex);