1
0
Fork 0

zlib -> libdeflate (#5085)

+ Use libdeflate
+ Use std::byte
* Fix passing temporary to string_view
+ Emulate make_unique_for_overwrite
master
Tiger Wang 2021-01-11 16:39:43 +00:00 committed by GitHub
parent 00c0a23ace
commit eeb63b8901
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 1419 additions and 2040 deletions

7
.gitmodules vendored
View File

@ -55,10 +55,6 @@
path = lib/tolua++
url = https://github.com/cuberite/toluapp.git
ignore = dirty
[submodule "lib/zlib"]
path = lib/zlib
url = https://github.com/cuberite/zlib.git
ignore = dirty
[submodule "lib/fmt"]
path = lib/fmt
url = https://github.com/fmtlib/fmt.git
@ -66,3 +62,6 @@
[submodule "Tools/BlockTypePaletteGenerator/lib/lunajson"]
path = Tools/BlockTypePaletteGenerator/lib/lunajson
url = https://github.com/grafi-tt/lunajson.git
[submodule "lib/libdeflate"]
path = lib/libdeflate
url = https://github.com/cuberite/libdeflate

View File

@ -28,7 +28,7 @@ function(build_dependencies)
# Enumerate all submodule libraries
# SQLiteCpp needs to be included before sqlite so the lsqlite target is available:
set(DEPENDENCIES expat fmt jsoncpp libevent lua luaexpat mbedtls SQLiteCpp sqlite tolua++ zlib)
set(DEPENDENCIES expat fmt jsoncpp libdeflate libevent lua luaexpat mbedtls SQLiteCpp sqlite tolua++)
foreach(DEPENDENCY ${DEPENDENCIES})
# Check that the libraries are present:
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/lib/${DEPENDENCY}/CMakeLists.txt")
@ -62,13 +62,13 @@ function(link_dependencies TARGET)
event_extra
fmt::fmt
jsoncpp_lib
libdeflate
lsqlite
lualib
luaexpat
mbedtls
SQLiteCpp
tolualib
zlib
)
# Link process information library:

View File

@ -9,6 +9,7 @@ function(group_sources)
expat
fmt
jsoncpp_lib
libdeflate
lualib
luaexpat
mbedcrypto
@ -18,7 +19,6 @@ function(group_sources)
sqlite3
SQLiteCpp
tolualib
zlib
PROPERTIES FOLDER Libraries
)

View File

@ -1765,17 +1765,6 @@ end
},
Notes = "Sets the locale that Cuberite keeps on record. Initially the locale is initialized in protocol handshake, this function allows plugins to override the stored value (but only server-side and only until the user disconnects).",
},
SetUsername =
{
Params =
{
{
Name = "Name",
Type = "string",
},
},
Notes = "Sets the username",
},
SetViewDistance =
{
Params =
@ -14459,7 +14448,7 @@ end
dtMagma =
{
Notes = "Damage from contact with a magma block"
},
},
dtDrown =
{
Notes = "Damage received by drowning in water / lava"

View File

@ -17,10 +17,6 @@ function(flatten_files arg1)
endfunction()
# Include the libraries:
add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
# Include the shared files:
set(SHARED_SRC
../../src/StringCompression.cpp
@ -66,11 +62,9 @@ source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
# Include the main source files:
set(SOURCES
MCADefrag.cpp
Globals.cpp
)
set(HEADERS
MCADefrag.h
Globals.h
)
source_group("" FILES ${SOURCES} ${HEADERS})
@ -84,7 +78,7 @@ add_executable(MCADefrag
${SHARED_OSS_HDR}
)
target_link_libraries(MCADefrag zlib fmt::fmt Threads::Threads)
target_link_libraries(MCADefrag fmt::fmt libdeflate Threads::Threads)
include(../../SetFlags.cmake)
set_exe_flags(MCADefrag)

View File

@ -1,10 +0,0 @@
// Globals.cpp
// This file is used for precompiled header generation in MSVC environments
#include "Globals.h"

View File

@ -1,174 +0,0 @@
// Globals.h
// This file gets included from every module in the project, so that global symbols may be introduced easily
// Also used for precompiled header generation in MSVC environments
// Compiler-dependent stuff:
#if defined(_MSC_VER)
// MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
#pragma warning(disable:4100)
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
#define abstract
#else
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
#endif
// Integral types with predefined sizes:
typedef long long Int64;
typedef int Int32;
typedef short Int16;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char Byte;
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
void operator=(const TypeName &)
// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
#define UNUSED(X) (void)(X)
// OS-dependent stuff:
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
#undef min
#undef max
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
#ifdef GetFreeSpace
#undef GetFreeSpace
#endif // GetFreeSpace
#define SocketError WSAGetLastError()
#else
#include <sys/types.h>
#include <sys/stat.h> // for mkdir
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <pthread.h>
#include <semaphore.h>
#include <cerrno>
#include <fcntl.h>
typedef int SOCKET;
enum
{
INVALID_SOCKET = -1,
};
#define closesocket close
#define SocketError errno
#endif
// CRT stuff:
#include <cassert>
#include <cstdio>
#include <cmath>
#include <cstdarg>
#include <ctime>
// STL stuff:
#include <vector>
#include <list>
#include <deque>
#include <string>
#include <map>
#include <algorithm>
#include <memory>
#include <atomic>
#include <mutex>
#include <thread>
#include <condition_variable>
// Common headers (without macros):
#include "fmt.h"
#include "LoggerSimple.h"
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Event.h"
#include "OSSupport/IsThread.h"
#include "OSSupport/File.h"
// Common definitions:
/** Evaluates to the number of elements in an array (compile-time!) */
#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
/** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */
#define KiB * 1024
#define MiB * 1024 * 1024
/** Faster than (int)floorf((float)x / (float)div) */
#define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div))
// Own version of assert() that writes failed assertions to the log for review
#ifdef NDEBUG
#define ASSERT(x) ((void)0)
#else
#define ASSERT assert
#endif
// Pretty much the same as ASSERT() but stays in Release builds
#define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0))

View File

@ -8,7 +8,6 @@
#include "Logger.h"
#include "LoggerSimple.h"
#include "LoggerListeners.h"
#include "zlib/zlib.h"
@ -129,7 +128,8 @@ AString cMCADefrag::GetNextFileName(void)
cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) :
super("MCADefrag thread"),
m_Parent(a_Parent),
m_IsChunkUncompressed(false)
m_IsChunkUncompressed(false),
m_Compressor(12) // Set the highest compression factor
{
}
@ -384,27 +384,33 @@ bool cMCADefrag::cThread::UncompressChunkGzip(void)
bool cMCADefrag::cThread::UncompressChunkZlib(void)
{
// Uncompress the data:
z_stream strm;
strm.zalloc = nullptr;
strm.zfree = nullptr;
strm.opaque = nullptr;
inflateInit(&strm);
strm.next_out = m_RawChunkData;
strm.avail_out = sizeof(m_RawChunkData);
strm.next_in = m_CompressedChunkData + 1; // The first byte is the compression method, skip it
strm.avail_in = static_cast<uInt>(m_CompressedChunkDataSize);
int res = inflate(&strm, Z_FINISH);
inflateEnd(&strm);
if (res != Z_STREAM_END)
try
{
LOGWARNING("Failed to uncompress chunk data: %s", strm.msg);
// Uncompress the data
const auto ExtractedData = m_Extractor.ExtractZLib(
{
reinterpret_cast<const std::byte *>(m_CompressedChunkData + 1), // The first byte is the compression method, skip it
static_cast<size_t>(m_CompressedChunkDataSize - 1)
});
const auto Extracted = ExtractedData.GetView();
if (Extracted.size() > MAX_RAW_CHUNK_DATA_SIZE)
{
LOGINFO("Too much data for the internal decompression buffer!");
return false;
}
std::copy(Extracted.begin(), Extracted.end(), reinterpret_cast<std::byte *>(m_RawChunkData));
m_RawChunkDataSize = static_cast<int>(Extracted.size());
return true;
}
catch (const std::exception & Oops)
{
LOGWARNING("Failed to uncompress chunk data. %s", Oops.what());
return false;
}
ASSERT(strm.total_out < static_cast<uLong>(std::numeric_limits<int>::max()));
m_RawChunkDataSize = static_cast<int>(strm.total_out);
return true;
}
@ -413,23 +419,33 @@ bool cMCADefrag::cThread::UncompressChunkZlib(void)
bool cMCADefrag::cThread::CompressChunk(void)
{
// Check that the compressed data can fit:
uLongf CompressedSize = compressBound(static_cast<uLong>(m_RawChunkDataSize));
if (CompressedSize > sizeof(m_CompressedChunkData))
try
{
LOGINFO("Too much data for the internal compression buffer!");
return false;
}
// Compress the data (using the highest compression factor, as set in the constructor)
// Compress the data using the highest compression factor:
int errorcode = compress2(m_CompressedChunkData + 1, &CompressedSize, m_RawChunkData, static_cast<uLong>(m_RawChunkDataSize), Z_BEST_COMPRESSION);
if (errorcode != Z_OK)
const auto CompressedData = m_Compressor.CompressZLib(
{
reinterpret_cast<const std::byte *>(m_RawChunkData),
static_cast<size_t>(m_RawChunkDataSize)
});
const auto Compressed = CompressedData.GetView();
// Check that the compressed data can fit:
if (Compressed.size() > MAX_COMPRESSED_CHUNK_DATA_SIZE)
{
LOGINFO("Too much data for the internal compression buffer!");
return false;
}
m_CompressedChunkData[0] = COMPRESSION_ZLIB;
std::copy(Compressed.begin(), Compressed.end(), reinterpret_cast<std::byte *>(m_CompressedChunkData + 1));
m_CompressedChunkDataSize = static_cast<int>(Compressed.size()) + 1;
return true;
}
catch (const std::exception & Oops)
{
LOGINFO("Recompression failed: %d", errorcode);
LOGWARNING("Recompression failed. %s", Oops.what());
return false;
}
m_CompressedChunkData[0] = COMPRESSION_ZLIB;
ASSERT(CompressedSize < static_cast<uLong>(std::numeric_limits<int>::max()));
m_CompressedChunkDataSize = static_cast<int>(CompressedSize + 1);
return true;
}

View File

@ -13,10 +13,18 @@
#include "OSSupport/IsThread.h"
#include "StringCompression.h"
class cMCADefrag
{
public:
enum
{
MAX_COMPRESSED_CHUNK_DATA_SIZE = (1 MiB),
@ -33,6 +41,7 @@ public:
void Run(void);
protected:
/** A single thread processing MCA files from the queue */
class cThread :
public cIsThread
@ -40,9 +49,11 @@ protected:
typedef cIsThread super;
public:
cThread(cMCADefrag & a_Parent);
protected:
/** The compression methods, as specified by the MCA compression method byte. */
enum
{
@ -75,6 +86,12 @@ protected:
WriteChunk() tests this flag to decide whether to call Compress(). */
bool m_IsChunkUncompressed;
/** An instance of the compressor. */
Compression::Compressor m_Compressor;
/** An instance of the extractor. */
Compression::Extractor m_Extractor;
/** Processes the specified file. */
void ProcessFile(const AString & a_FileName);

View File

@ -36,11 +36,9 @@ source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR})
# Include the main source files:
set(SOURCES
NoiseSpeedTest.cpp
Globals.cpp
)
set(HEADERS
NoiseSpeedTest.h
Globals.h
SimplexNoise.h
)

View File

@ -1,10 +0,0 @@
// Globals.cpp
// This file is used for precompiled header generation in MSVC environments
#include "Globals.h"

View File

@ -1,196 +0,0 @@
// Globals.h
// This file gets included from every module in the project, so that global symbols may be introduced easily
// Also used for precompiled header generation in MSVC environments
// Compiler-dependent stuff:
#if defined(_MSC_VER)
// MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
#pragma warning(disable:4100)
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
#define abstract
#else
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
#endif
#ifndef TOLUA_TEMPLATE_BIND
#define TOLUA_TEMPLATE_BIND(x)
#endif
// Integral types with predefined sizes:
typedef long long Int64;
typedef int Int32;
typedef short Int16;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char Byte;
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
void operator=(const TypeName &)
// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
#define UNUSED(X) (void)(X)
// OS-dependent stuff:
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
#undef min
#undef max
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
#ifdef GetFreeSpace
#undef GetFreeSpace
#endif // GetFreeSpace
#define SocketError WSAGetLastError()
#else
#include <sys/types.h>
#include <sys/stat.h> // for mkdir
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <pthread.h>
#include <semaphore.h>
#include <cerrno>
#include <fcntl.h>
typedef int SOCKET;
enum
{
INVALID_SOCKET = -1,
};
#define closesocket close
#define SocketError errno
#endif
// CRT stuff:
#include <cassert>
#include <cstdio>
#include <cmath>
#include <cstdarg>
#include <ctime>
// STL stuff:
#include <vector>
#include <list>
#include <deque>
#include <string>
#include <map>
#include <algorithm>
#include <memory>
#include <atomic>
#include <mutex>
#include <thread>
#include <condition_variable>
// Common headers (without macros):
#include "fmt.h"
#include "LoggerSimple.h"
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Event.h"
#include "OSSupport/IsThread.h"
#include "OSSupport/File.h"
// Common definitions:
/** Evaluates to the number of elements in an array (compile-time!) */
#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
/** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */
#define KiB * 1024
#define MiB * 1024 * 1024
/** Faster than (int)floorf((float)x / (float)div) */
#define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div))
// Own version of assert() that writes failed assertions to the log for review
#ifdef NDEBUG
#define ASSERT(x) ((void)0)
#else
#define ASSERT assert
#endif
// Pretty much the same as ASSERT() but stays in Release builds
#define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0))
/** Clamps the value into the specified range. */
template <typename T>
T Clamp(T a_Value, T a_Min, T a_Max)
{
return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
}
template <typename T>
auto ToUnsigned(T a_Val)
{
ASSERT(a_Val >= 0);
return static_cast<std::make_unsigned_t<T>>(a_Val);
}

View File

@ -15,8 +15,6 @@ function(flatten_files arg1)
set(${arg1} "${res}" PARENT_SCOPE)
endfunction()
add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
# Include the shared files:
set(SHARED_SRC
../../src/ByteBuffer.cpp
@ -33,6 +31,7 @@ set(SHARED_SRC
)
set(SHARED_HDR
../../src/ByteBuffer.h
../../src/Globals.h
../../src/StringUtils.h
../../src/UUID.h
../../src/mbedTLS++/AesCfb128Decryptor.h
@ -72,13 +71,11 @@ source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
# Include the main source files:
set(SOURCES
Connection.cpp
Globals.cpp
ProtoProxy.cpp
Server.cpp
)
set(HEADERS
Connection.h
Globals.h
Server.h
)
source_group("" FILES ${SOURCES} ${HEADERS})
@ -92,7 +89,7 @@ add_executable(ProtoProxy
${SHARED_OSS_HDR}
)
target_link_libraries(ProtoProxy zlib mbedtls fmt::fmt Threads::Threads)
target_link_libraries(ProtoProxy fmt::fmt libdeflate mbedtls Threads::Threads)
include(../../SetFlags.cmake)
set_exe_flags(ProtoProxy)

View File

@ -12,6 +12,8 @@
#ifdef _WIN32
#include <direct.h> // For _mkdir()
#else
#include <sys/stat.h> // for mkdir
#endif
@ -59,25 +61,25 @@
#define COPY_TO_SERVER() \
do { \
AString ToServer; \
ContiguousByteBuffer ToServer; \
m_ClientBuffer.ReadAgain(ToServer); \
switch (m_ServerState) \
{ \
case csUnencrypted: \
{ \
SERVERSEND(ToServer.data(), ToServer.size()); \
SERVERSEND(ToServer); \
break; \
} \
case csEncryptedUnderstood: \
case csEncryptedUnknown: \
{ \
SERVERENCRYPTSEND(ToServer.data(), ToServer.size()); \
SERVERENCRYPTSEND(ToServer); \
break; \
} \
case csWaitingForEncryption: \
{ \
Log("Waiting for server encryption, queued %u bytes", ToServer.size()); \
m_ServerEncryptionBuffer.append(ToServer.data(), ToServer.size()); \
m_ServerEncryptionBuffer += ToServer; \
break; \
} \
} \
@ -86,19 +88,19 @@
#define COPY_TO_CLIENT() \
do { \
AString ToClient; \
ContiguousByteBuffer ToClient; \
m_ServerBuffer.ReadAgain(ToClient); \
switch (m_ClientState) \
{ \
case csUnencrypted: \
{ \
CLIENTSEND(ToClient.data(), ToClient.size()); \
CLIENTSEND(ToClient); \
break; \
} \
case csEncryptedUnderstood: \
case csEncryptedUnknown: \
{ \
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
CLIENTENCRYPTSEND(ToClient); \
break; \
} \
case csWaitingForEncryption: \
@ -114,7 +116,7 @@
do { \
if (!Proc) \
{ \
AString Leftover; \
ContiguousByteBuffer Leftover; \
m_ClientBuffer.ReadAgain(Leftover); \
DataLog(Leftover.data(), Leftover.size(), "Leftover data after client packet parsing, %d bytes:", Leftover.size()); \
m_ClientBuffer.ResetRead(); \
@ -374,15 +376,15 @@ bool cConnection::RelayFromServer(void)
}
case csEncryptedUnderstood:
{
m_ServerDecryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
m_ServerDecryptor.ProcessData(reinterpret_cast<std::byte *>(Buffer), reinterpret_cast<const Byte *>(Buffer), static_cast<size_t>(res));
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the SERVER", res);
return DecodeServersPackets(Buffer, res);
}
case csEncryptedUnknown:
{
m_ServerDecryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
m_ServerDecryptor.ProcessData(reinterpret_cast<std::byte *>(Buffer), reinterpret_cast<const Byte *>(Buffer), static_cast<size_t>(res));
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the SERVER", res);
return CLIENTSEND(Buffer, static_cast<size_t>(res));
return CLIENTSEND({ reinterpret_cast<const std::byte *>(Buffer), static_cast<size_t>(res) });
}
}
ASSERT(!"Unhandled server state while relaying from server");
@ -419,8 +421,8 @@ bool cConnection::RelayFromClient(void)
case csEncryptedUnknown:
{
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the CLIENT", res);
m_ServerEncryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
return SERVERSEND(Buffer, static_cast<size_t>(res));
m_ServerEncryptor.ProcessData(reinterpret_cast<std::byte *>(Buffer), reinterpret_cast<const std::byte *>(Buffer), static_cast<size_t>(res));
return SERVERSEND({ reinterpret_cast<const std::byte *>(Buffer), static_cast<size_t>(res) });
}
}
ASSERT(!"Unhandled server state while relaying from client");
@ -441,11 +443,11 @@ double cConnection::GetRelativeTime(void)
bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer)
bool cConnection::SendData(SOCKET a_Socket, const ContiguousByteBufferView a_Data, const char * a_Peer)
{
DataLog(a_Data, a_Size, "Sending data to %s, %u bytes", a_Peer, static_cast<unsigned>(a_Size));
DataLog(a_Data.data(), a_Data.size(), "Sending data to %s, %zu bytes", a_Peer, a_Data.size());
int res = static_cast<int>(send(a_Socket, a_Data, a_Size, 0)); // Windows uses int for a_Size, Linux uses size_t; but Windows doesn't complain. Return type is int on Windows and ssize_t on Linux
int res = static_cast<int>(send(a_Socket, reinterpret_cast<const char *>(a_Data.data()), a_Data.size(), 0)); // Windows uses int for a_Size, Linux uses size_t; but Windows doesn't complain. Return type is int on Windows and ssize_t on Linux
if (res <= 0)
{
Log("%s closed the socket: %d, %d; aborting connection", a_Peer, res, SocketError);
@ -460,32 +462,30 @@ bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size,
bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer)
{
AString All;
ContiguousByteBuffer All;
a_Data.ReadAll(All);
a_Data.CommitRead();
return SendData(a_Socket, All.data(), All.size(), a_Peer);
return SendData(a_Socket, All, a_Peer);
}
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, ContiguousByteBufferView a_Data, const char * a_Peer)
{
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
const Byte * Data = reinterpret_cast<const Byte *>(a_Data);
while (a_Size > 0)
DataLog(a_Data.data(), a_Data.size(), "Encrypting %zu bytes to %s", a_Data.size(), a_Peer);
while (a_Data.size() > 0)
{
Byte Buffer[64 KiB];
size_t NumBytes = (a_Size > sizeof(Buffer)) ? sizeof(Buffer) : a_Size;
a_Encryptor.ProcessData(Buffer, Data, NumBytes);
bool res = SendData(a_Socket, reinterpret_cast<const char *>(Buffer), NumBytes, a_Peer);
std::byte Buffer[64 KiB];
size_t NumBytes = (a_Data.size() > sizeof(Buffer)) ? sizeof(Buffer) : a_Data.size();
a_Encryptor.ProcessData(Buffer, a_Data.data(), NumBytes);
bool res = SendData(a_Socket, { Buffer, NumBytes }, a_Peer);
if (!res)
{
return false;
}
Data += NumBytes;
a_Size -= NumBytes;
a_Data = a_Data.substr(NumBytes);
}
return true;
}
@ -496,10 +496,10 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Enc
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
{
AString All;
ContiguousByteBuffer All;
a_Data.ReadAll(All);
a_Data.CommitRead();
return SendEncryptedData(a_Socket, a_Encryptor, All.data(), All.size(), a_Peer);
return SendEncryptedData(a_Socket, a_Encryptor, All, a_Peer);
}
@ -647,7 +647,7 @@ bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
if (PacketLen == 0)
{
m_ServerBuffer.ResetRead();
AString All;
ContiguousByteBuffer All;
m_ServerBuffer.ReadAll(All);
DataLog(All.data(), All.size(), "====== Received a bad packet length? Inspect the contents below ======");
m_ServerBuffer.CommitRead(); // Try to recover by marking everything as read
@ -798,10 +798,11 @@ bool cConnection::HandleClientHandshake(void)
Packet.WriteVarUTF8String(ServerHost);
Packet.WriteBEUInt16(m_Server.GetConnectPort());
Packet.WriteVarInt32(NextState);
AString Pkt;
ContiguousByteBuffer Pkt;
Packet.ReadAll(Pkt);
cByteBuffer ToServer(512);
ToServer.WriteVarUTF8String(Pkt);
ToServer.WriteVarInt32(static_cast<UInt32>(Pkt.size()));
ToServer.Write(Pkt.data(), Pkt.size());
SERVERSEND(ToServer);
m_ClientProtocolState = static_cast<int>(NextState);
@ -1111,8 +1112,8 @@ bool cConnection::HandleClientPluginMessage(void)
{
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, Length);
AString Data;
if (!m_ClientBuffer.ReadString(Data, Length))
ContiguousByteBuffer Data;
if (!m_ClientBuffer.ReadSome(Data, Length))
{
return false;
}
@ -1253,8 +1254,8 @@ bool cConnection::HandleClientWindowClose(void)
bool cConnection::HandleClientUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar)
{
AString Data;
if (!m_ClientBuffer.ReadString(Data, a_PacketLen - a_PacketReadSoFar))
ContiguousByteBuffer Data;
if (!m_ClientBuffer.ReadSome(Data, a_PacketLen - a_PacketReadSoFar))
{
return false;
}
@ -1288,14 +1289,14 @@ bool cConnection::HandleServerLoginEncryptionKeyRequest(void)
// Read the packet from the server:
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ServerID);
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, PublicKeyLength);
AString PublicKey;
if (!m_ServerBuffer.ReadString(PublicKey, PublicKeyLength))
ContiguousByteBuffer PublicKey;
if (!m_ServerBuffer.ReadSome(PublicKey, PublicKeyLength))
{
return false;
}
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NonceLength);
AString Nonce;
if (!m_ServerBuffer.ReadString(Nonce, NonceLength))
ContiguousByteBuffer Nonce;
if (!m_ServerBuffer.ReadSome(Nonce, NonceLength))
{
return false;
}
@ -1304,7 +1305,7 @@ bool cConnection::HandleServerLoginEncryptionKeyRequest(void)
DataLog(PublicKey.data(), PublicKey.size(), " Public key (%u bytes)", static_cast<unsigned>(PublicKey.size()));
// Reply to the server:
SendEncryptionKeyResponse(PublicKey, Nonce);
SendEncryptionKeyResponse({ reinterpret_cast<const char *>(PublicKey.data()), PublicKey.size() }, { reinterpret_cast<const char *>(Nonce.data()), Nonce.size() });
// Do not send to client - we want the client connection open
return true;
@ -1330,7 +1331,7 @@ bool cConnection::HandleServerLoginSuccess(void)
Log("Server communication is now encrypted");
m_ServerState = csEncryptedUnderstood;
DataLog(m_ServerEncryptionBuffer.data(), m_ServerEncryptionBuffer.size(), "Sending the queued data to server (%u bytes):", m_ServerEncryptionBuffer.size());
SERVERENCRYPTSEND(m_ServerEncryptionBuffer.data(), m_ServerEncryptionBuffer.size());
SERVERENCRYPTSEND(m_ServerEncryptionBuffer);
m_ServerEncryptionBuffer.clear();
}
COPY_TO_CLIENT();
@ -1827,8 +1828,8 @@ bool cConnection::HandleServerKick(void)
AString PacketStart("\xff");
PacketStart.push_back(static_cast<char>(ReasonBE16.size() / 256));
PacketStart.push_back(static_cast<char>(ReasonBE16.size() % 256));
CLIENTSEND(PacketStart.data(), PacketStart.size());
CLIENTSEND(reinterpret_cast<const char *>(ReasonBE16.data()), ReasonBE16.size() * sizeof(char16_t));
CLIENTSEND({ reinterpret_cast<const std::byte *>(PacketStart.data()), PacketStart.size() });
CLIENTSEND({ reinterpret_cast<const std::byte *>(ReasonBE16.data()), ReasonBE16.size() * sizeof(char16_t) });
return true;
}
else
@ -1856,8 +1857,8 @@ bool cConnection::HandleServerMapChunk(void)
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, PrimaryBitmap);
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, AdditionalBitmap);
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize);
AString CompressedData;
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
ContiguousByteBuffer CompressedData;
if (!m_ServerBuffer.ReadSome(CompressedData, CompressedSize))
{
return false;
}
@ -1880,8 +1881,8 @@ bool cConnection::HandleServerMapChunkBulk(void)
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, ChunkCount);
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize);
HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsSkyLightSent);
AString CompressedData;
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
ContiguousByteBuffer CompressedData;
if (!m_ServerBuffer.ReadSome(CompressedData, CompressedSize))
{
return false;
}
@ -1930,8 +1931,8 @@ bool cConnection::HandleServerMultiBlockChange(void)
HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkZ);
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NumBlocks);
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, DataSize);
AString BlockChangeData;
if (!m_ServerBuffer.ReadString(BlockChangeData, DataSize))
ContiguousByteBuffer BlockChangeData;
if (!m_ServerBuffer.ReadSome(BlockChangeData, DataSize))
{
return false;
}
@ -2039,8 +2040,8 @@ bool cConnection::HandleServerPluginMessage(void)
{
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Length);
AString Data;
if (!m_ServerBuffer.ReadString(Data, Length))
ContiguousByteBuffer Data;
if (!m_ServerBuffer.ReadSome(Data, Length))
{
return false;
}
@ -2278,7 +2279,7 @@ bool cConnection::HandleServerSpawnObjectVehicle(void)
#ifdef _DEBUG
// DEBUG:
// This packet is still troublesome when DataIndicator != 0
AString Buffer;
ContiguousByteBuffer Buffer;
m_ServerBuffer.ResetRead();
m_ServerBuffer.ReadAll(Buffer);
m_ServerBuffer.ResetRead();
@ -2328,7 +2329,7 @@ bool cConnection::HandleServerSpawnObjectVehicle(void)
}
// TODO: Splash potions
}
if ((ExtraLen > 0) && !m_ServerBuffer.ReadString(ExtraData, ExtraLen))
if ((ExtraLen > 0) && !m_ServerBuffer.ReadSome(ExtraData, ExtraLen))
{
return false;
}
@ -2449,10 +2450,11 @@ bool cConnection::HandleServerStatusResponse(void)
cByteBuffer Packet(Response.size() + 50);
Packet.WriteVarInt32(0); // Packet type - status response
Packet.WriteVarUTF8String(Response);
AString Pkt;
ContiguousByteBuffer Pkt;
Packet.ReadAll(Pkt);
cByteBuffer ToClient(Response.size() + 50);
ToClient.WriteVarUTF8String(Pkt);
ToClient.WriteVarInt32(static_cast<UInt32>(Pkt.size()));
ToClient.Write(Pkt.data(), Pkt.size());
CLIENTSEND(ToClient);
return true;
}
@ -2545,8 +2547,8 @@ bool cConnection::HandleServerUpdateTileEntity(void)
HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Action);
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, DataLength);
AString Data;
if ((DataLength > 0) && !m_ServerBuffer.ReadString(Data, DataLength))
ContiguousByteBuffer Data;
if ((DataLength > 0) && !m_ServerBuffer.ReadSome(Data, DataLength))
{
return false;
}
@ -2662,9 +2664,9 @@ bool cConnection::HandleServerWindowOpen(void)
bool cConnection::HandleServerUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar)
{
AString Data;
ContiguousByteBuffer Data;
ASSERT(a_PacketLen >= a_PacketReadSoFar);
if (!m_ServerBuffer.ReadString(Data, a_PacketLen - a_PacketReadSoFar))
if (!m_ServerBuffer.ReadSome(Data, a_PacketLen - a_PacketReadSoFar))
{
return false;
}
@ -2764,9 +2766,9 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
rs = rs - static_cast<int>(a_Buffer.GetReadableSpace());
cByteBuffer LenBuf(8);
LenBuf.WriteVarInt32(Len);
AString VarLen;
ContiguousByteBuffer VarLen;
LenBuf.ReadAll(VarLen);
a_Metadata.append(VarLen);
a_Metadata += { reinterpret_cast<const char *>(VarLen.data()), VarLen.size() };
Length = Len;
break;
}
@ -2794,12 +2796,12 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
} // switch (Type)
// Read the data in this item:
AString data;
if (!a_Buffer.ReadString(data, Length))
ContiguousByteBuffer data;
if (!a_Buffer.ReadSome(data, Length))
{
return false;
}
a_Metadata.append(data);
a_Metadata += { reinterpret_cast<const char *>(data.data()), data.size() };
if (!a_Buffer.ReadBEUInt8(x))
{
return false;

View File

@ -13,6 +13,10 @@
#include "mbedTLS++/AesCfb128Decryptor.h"
#include "mbedTLS++/AesCfb128Encryptor.h"
#ifndef _WIN32
typedef int SOCKET;
#endif
@ -85,7 +89,7 @@ protected:
cAesCfb128Decryptor m_ServerDecryptor;
cAesCfb128Encryptor m_ServerEncryptor;
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
ContiguousByteBuffer m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
/** Set to true when PACKET_PING is received from the client; will cause special parsing for server kick */
bool m_HasClientPinged;
@ -119,13 +123,13 @@ protected:
double GetRelativeTime(void);
/** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */
bool SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer);
bool SendData(SOCKET a_Socket, ContiguousByteBufferView a_Data, const char * a_Peer);
/** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
/** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, ContiguousByteBufferView a_Data, const char * a_Peer);
/** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);

View File

@ -1,10 +0,0 @@
// Globals.cpp
// This file is used for precompiled header generation in MSVC environments
#include "Globals.h"

View File

@ -1,177 +0,0 @@
// Globals.h
// This file gets included from every module in the project, so that global symbols may be introduced easily
// Also used for precompiled header generation in MSVC environments
// Compiler-dependent stuff:
#if defined(_MSC_VER)
// MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
#pragma warning(disable:4100)
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
#define abstract
#else
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
#endif
// Integral types with predefined sizes:
typedef signed long long Int64;
typedef signed int Int32;
typedef signed short Int16;
typedef signed char Int8;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char UInt8;
typedef unsigned char Byte;
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
void operator=(const TypeName &)
// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
#define UNUSED(X) (void)(X)
// OS-dependent stuff:
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
#undef min
#undef max
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
#ifdef GetFreeSpace
#undef GetFreeSpace
#endif // GetFreeSpace
#define SocketError WSAGetLastError()
#else
#include <sys/types.h>
#include <sys/stat.h> // for mkdir
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <dirent.h>
#include <errno.h>
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
typedef int SOCKET;
enum
{
INVALID_SOCKET = -1,
};
#define closesocket close
#define SocketError errno
#endif
// CRT stuff:
#include <assert.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
// STL stuff:
#include <chrono>
#include <vector>
#include <list>
#include <deque>
#include <string>
#include <map>
#include <algorithm>
#include <memory>
#include <atomic>
#include <mutex>
#include <thread>
#include <condition_variable>
// Common headers (part 1, without macros):
#include "fmt.h"
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "LoggerSimple.h"