mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 09:02:29 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9dcc88f29 | |||
| 7fb1d2a1b5 | |||
| 82e247f77b | |||
| ebaa0bf90f | |||
| 54a7f73e50 | |||
| 84630ce228 | |||
| c09a48d58c | |||
| 5e7316edb9 | |||
| ac6291f80b | |||
| 21a39db1c6 |
+12
-1
@@ -23,7 +23,18 @@ CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
[Bb]uild*/
|
||||
Build/
|
||||
build/
|
||||
Build32/
|
||||
build32/
|
||||
Build64/
|
||||
build64/
|
||||
Build_32/
|
||||
build_32/
|
||||
Build_64/
|
||||
build_64/
|
||||
x64/
|
||||
x86/
|
||||
log/
|
||||
logs/
|
||||
vcpkg/
|
||||
|
||||
+7
-4
@@ -1,3 +1,6 @@
|
||||
[submodule "submodules/websocketpp"]
|
||||
path = submodules/websocketpp
|
||||
url = https://github.com/zaphoyd/websocketpp.git
|
||||
[submodule "submodules/glm"]
|
||||
path = submodules/glm
|
||||
url = https://github.com/g-truc/glm.git
|
||||
@@ -10,9 +13,9 @@
|
||||
[submodule "submodules/cereal"]
|
||||
path = submodules/cereal
|
||||
url = https://github.com/USCiLab/cereal.git
|
||||
[submodule "submodules/websocketpp"]
|
||||
path = submodules/websocketpp
|
||||
url = https://github.com/zaphoyd/websocketpp.git
|
||||
[submodule "submodules/recastnavigation"]
|
||||
path = submodules/recastnavigation
|
||||
url = https://github.com/EQEmu/recastnavigation.git
|
||||
url = https://github.com/recastnavigation/recastnavigation.git
|
||||
[submodule "submodules/concurrentqueue"]
|
||||
path = submodules/concurrentqueue
|
||||
url = https://github.com/cameron314/concurrentqueue.git
|
||||
|
||||
+27
-55
@@ -26,8 +26,6 @@
|
||||
#EQEMU_BUILD_CLIENT_FILES
|
||||
#EQEMU_USE_MAP_MMFS
|
||||
#EQEMU_MAP_DIR
|
||||
#EQEMU_ARCH
|
||||
#EQEMU_ARCH_ALT
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
IF(POLICY CMP0074)
|
||||
@@ -59,37 +57,33 @@ ENDIF(MSVC OR MINGW)
|
||||
|
||||
IF(MSVC)
|
||||
IF(CMAKE_CL_64)
|
||||
SET(EQEMU_ARCH "x64")
|
||||
SET(EQEMU_ARCH_ALT "x64")
|
||||
ELSE(CMAKE_CL_64)
|
||||
SET(EQEMU_ARCH "x86")
|
||||
SET(EQEMU_ARCH_ALT "Win32")
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_${EQEMU_ARCH}")
|
||||
|
||||
IF(VCPKG_TOOLCHAIN)
|
||||
IF(NOT MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF()
|
||||
ELSE(VCPKG_TOOLCHAIN)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_${EQEMU_ARCH}")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_${EQEMU_ARCH}")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_${EQEMU_ARCH}")
|
||||
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF(VCPKG_TOOLCHAIN)
|
||||
|
||||
IF(SODIUM_INCLUDE_HINTS)
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v140/dynamic")
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v120/dynamic")
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v110/dynamic")
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
ENDIF(SODIUM_INCLUDE_HINTS)
|
||||
|
||||
ELSE(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
||||
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
|
||||
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
|
||||
@@ -296,14 +290,14 @@ ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
|
||||
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
|
||||
|
||||
#Find everything we need
|
||||
FIND_PACKAGE(ZLIB)
|
||||
FIND_PACKAGE(ZLIB REQUIRED)
|
||||
FIND_PACKAGE(MySQL REQUIRED)
|
||||
IF(EQEMU_BUILD_PERL)
|
||||
FIND_PACKAGE(PerlLibs REQUIRED)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||
ENDIF(EQEMU_BUILD_PERL)
|
||||
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} uv_a fmt RecastNavigation::Detour)
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} uv_a fmt RecastNavigation::Detour)
|
||||
|
||||
FIND_PACKAGE(Sodium REQUIRED)
|
||||
IF(SODIUM_FOUND)
|
||||
@@ -315,23 +309,6 @@ IF(SODIUM_FOUND)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(ZLIB_FOUND)
|
||||
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF)
|
||||
|
||||
IF(EQEMU_BUILD_ZLIB)
|
||||
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ELSE()
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
||||
SET(EQEMU_BUILD_ZLIB ON)
|
||||
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ENDIF()
|
||||
|
||||
IF(WIN32)
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
|
||||
ENDIF()
|
||||
@@ -361,6 +338,7 @@ IF(EQEMU_BUILD_LUA)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
|
||||
@@ -371,24 +349,18 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/concurrentqueue")
|
||||
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(libs)
|
||||
ADD_SUBDIRECTORY(submodules/fmt)
|
||||
ADD_SUBDIRECTORY(submodules/libuv)
|
||||
|
||||
|
||||
SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo")
|
||||
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
|
||||
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
|
||||
ADD_SUBDIRECTORY(submodules/recastnavigation)
|
||||
|
||||
IF(EQEMU_BUILD_ZLIB)
|
||||
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
|
||||
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
|
||||
ADD_SUBDIRECTORY(libs/zlibng)
|
||||
ENDIF()
|
||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||
IF(EQEMU_BUILD_SERVER)
|
||||
ADD_SUBDIRECTORY(shared_memory)
|
||||
|
||||
@@ -70,9 +70,3 @@ forum, although pull requests will be much quicker and easier on all parties.
|
||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||
* CPPUnit - GLP StringUtilities - Apache
|
||||
* LUA - MIT
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||
</a>
|
||||
|
||||
@@ -1,56 +1,5 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 7/22/2019 ==
|
||||
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
|
||||
|
||||
== 7/10/2019 ==
|
||||
|
||||
Akkadius: Add #npcedit flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating]
|
||||
Akkadius: Added "flymode" to npc_types database table
|
||||
|
||||
== 7/3/2019 ==
|
||||
|
||||
Akkadius/KLS:
|
||||
- Optimizations to packet updates introduced back into the source post network code overhaul
|
||||
- Optimizations made to position update packets by sending updates far less frequently when not in line with zone:max_movement_update_range
|
||||
- Optimizations made to position updates in respect to the much higher resolution of navmesh path-finding that we were using. We have cut down
|
||||
on the resolution of path finding / updating so that we reduce the CPU overhead of path-finding and subsequent client update packets that
|
||||
get generated this action
|
||||
- Optimization made by adjusting ZLIB compression rate that was accidentally set to a compression level of 4 a long time ago
|
||||
- Added #netstats admin command to troubleshoot connection issues in detail
|
||||
- Websocket server is now available in zone and is bound to the same UDP port that the zoneserver listens on
|
||||
- Currently implemented websocket API calls at the zone level
|
||||
get_packet_statistics
|
||||
get_opcode_list
|
||||
get_npc_list_detail
|
||||
get_door_list_detail
|
||||
get_corpse_list_detail
|
||||
get_object_list_detail
|
||||
get_mob_list_detail
|
||||
get_client_list_detail
|
||||
get_zone_attributes
|
||||
get_logsys_categories
|
||||
set_logging_level
|
||||
- Example of a Typescript client: https://gist.github.com/Akkadius/52d12d0379f36cf81c51b3b7da13db37
|
||||
- Library Changes
|
||||
- We now use git submodules for libraries / dependencies versus manually downloading to the dependencies folder and/or storing
|
||||
said dependencies within our codebase itself
|
||||
- To update dependencies (Required for compiling)
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- Libraries now in submodules
|
||||
- [glm] https://github.com/g-truc/glm.git
|
||||
- [flm] https://github.com/fmtlib/fmt.git
|
||||
- [libuv] https://github.com/libuv/libuv.git
|
||||
- [cereal] https://github.com/USCiLab/cereal.git
|
||||
- [websocketpp] https://github.com/zaphoyd/websocketpp.git
|
||||
- [recastnavigation] https://github.com/EQEmu/recastnavigation.git
|
||||
|
||||
== 6/24/2019 ==
|
||||
Uleat: Reworked BotDatabase into a functional add-on for ZoneDatabase
|
||||
- Eliminated the database connection associated with class BotDatabase
|
||||
- All behaviors remain the same with the exception of the calling object
|
||||
-- To invoke a BotDatabase function, use database.botdb.<f> rather than botdb.<f>
|
||||
|
||||
== 3/1/2019 ==
|
||||
Noudess: Major faction conversion to use client data.
|
||||
|
||||
@@ -79,6 +79,7 @@ SET(common_sources
|
||||
net/crc32.cpp
|
||||
net/daybreak_connection.cpp
|
||||
net/eqstream.cpp
|
||||
net/eqstream_concurrent.cpp
|
||||
net/packet.cpp
|
||||
net/servertalk_client_connection.cpp
|
||||
net/servertalk_legacy_client_connection.cpp
|
||||
@@ -86,8 +87,6 @@ SET(common_sources
|
||||
net/servertalk_server_connection.cpp
|
||||
net/tcp_connection.cpp
|
||||
net/tcp_server.cpp
|
||||
net/websocket_server.cpp
|
||||
net/websocket_server_connection.cpp
|
||||
patches/patches.cpp
|
||||
patches/sod.cpp
|
||||
patches/sod_limits.cpp
|
||||
@@ -213,7 +212,6 @@ SET(common_headers
|
||||
zone_numbers.h
|
||||
event/event_loop.h
|
||||
event/task.h
|
||||
event/task_scheduler.h
|
||||
event/timer.h
|
||||
json/json.h
|
||||
json/json-forwards.h
|
||||
@@ -225,6 +223,8 @@ SET(common_headers
|
||||
net/dns.h
|
||||
net/endian.h
|
||||
net/eqstream.h
|
||||
net/eqstream_concurrent.h
|
||||
net/eqstream_concurrent_message.h
|
||||
net/packet.h
|
||||
net/servertalk_client_connection.h
|
||||
net/servertalk_legacy_client_connection.h
|
||||
@@ -233,8 +233,6 @@ SET(common_headers
|
||||
net/servertalk_server_connection.h
|
||||
net/tcp_connection.h
|
||||
net/tcp_server.h
|
||||
net/websocket_server.h
|
||||
net/websocket_server_connection.h
|
||||
patches/patches.h
|
||||
patches/sod.h
|
||||
patches/sod_limits.h
|
||||
@@ -299,6 +297,9 @@ SOURCE_GROUP(Net FILES
|
||||
net/eqmq.h
|
||||
net/eqstream.cpp
|
||||
net/eqstream.h
|
||||
net/eqstream_concurrent.cpp
|
||||
net/eqstream_concurrent.h
|
||||
net/eqstream_concurrent_message.h
|
||||
net/packet.cpp
|
||||
net/packet.h
|
||||
net/servertalk_client_connection.cpp
|
||||
@@ -314,10 +315,6 @@ SOURCE_GROUP(Net FILES
|
||||
net/tcp_connection.h
|
||||
net/tcp_server.cpp
|
||||
net/tcp_server.h
|
||||
net/websocket_server.cpp
|
||||
net/websocket_server.h
|
||||
net/websocket_server_connection.cpp
|
||||
net/websocket_server_connection.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Patches FILES
|
||||
|
||||
@@ -75,7 +75,6 @@ public:
|
||||
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
||||
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
||||
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
||||
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
|
||||
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
||||
|
||||
uint32 GetWritePosition() { return _wpos; }
|
||||
|
||||
+16
-13
@@ -171,27 +171,30 @@ void Database::LoginIP(uint32 AccountID, const char* LoginIP) {
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
int16 Database::CheckStatus(uint32 account_id)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = %i",
|
||||
account_id);
|
||||
int16 Database::CheckStatus(uint32 account_id) {
|
||||
std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`"
|
||||
" FROM `account` WHERE `id` = %i", account_id);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
int16 status = atoi(row[0]);
|
||||
int32 suspendeduntil = 0;
|
||||
|
||||
auto row = results.begin();
|
||||
int16 status = atoi(row[0]);
|
||||
int32 date_diff = 0;
|
||||
// MariaDB initalizes with NULL if unix_timestamp() is out of range
|
||||
if (row[1] != nullptr) {
|
||||
suspendeduntil = atoi(row[1]);
|
||||
}
|
||||
|
||||
if (row[1] != nullptr)
|
||||
date_diff = atoi(row[1]);
|
||||
int32 current = atoi(row[2]);
|
||||
|
||||
if (date_diff > 0)
|
||||
if(suspendeduntil > current)
|
||||
return -1;
|
||||
|
||||
return status;
|
||||
|
||||
@@ -307,12 +307,6 @@ namespace EQEmu
|
||||
|
||||
} // namespace bug
|
||||
|
||||
enum WaypointStatus : int {
|
||||
RoamBoxPauseInProgress = -3,
|
||||
QuestControlNoGrid = -2,
|
||||
QuestControlGrid = -1
|
||||
};
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
@@ -87,7 +87,6 @@ typedef enum {
|
||||
_eaMaxAppearance
|
||||
} EmuAppearance;
|
||||
|
||||
#define MT_NPCQuestSay 10
|
||||
// msg_type's for custom usercolors
|
||||
#define MT_Say 256
|
||||
#define MT_Tell 257
|
||||
@@ -524,25 +523,4 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang
|
||||
|
||||
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
|
||||
|
||||
enum ChatChannelNames : uint16
|
||||
{
|
||||
ChatChannel_Guild = 0,
|
||||
ChatChannel_Group = 2,
|
||||
ChatChannel_Shout = 3,
|
||||
ChatChannel_Auction = 4,
|
||||
ChatChannel_OOC = 5,
|
||||
ChatChannel_Broadcast = 6,
|
||||
ChatChannel_Tell = 7,
|
||||
ChatChannel_Say = 8,
|
||||
ChatChannel_Petition = 10,
|
||||
ChatChannel_GMSAY = 11,
|
||||
ChatChannel_TellEcho = 14,
|
||||
ChatChannel_Raid = 15,
|
||||
|
||||
ChatChannel_UNKNOWN_Guild = 17,
|
||||
ChatChannel_UNKNOWN_GMSAY = 18,
|
||||
ChatChannel_UCSRelay = 20,
|
||||
ChatChannel_Emotes = 22
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
@@ -1188,20 +1188,6 @@ struct SpecialMesg_Struct
|
||||
/*24*/ char message[1]; // What is being said?
|
||||
};
|
||||
|
||||
struct SpecialMesgHeader_Struct
|
||||
{
|
||||
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
|
||||
/*01*/ char JournalMode; // 1 and 2 go to journal
|
||||
/*02*/ char language;
|
||||
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
|
||||
/*07*/ uint32 target_spawn_id; // Who is it being said to?
|
||||
/*11*/ // speaker's name
|
||||
/*xx*/ // unknown, location, client doesn't care
|
||||
/*xx*/ // unknown
|
||||
/*xx*/ // unknown
|
||||
/*xx*/ // message
|
||||
};
|
||||
|
||||
/*
|
||||
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
||||
** Length: 19 Bytes
|
||||
|
||||
+16
-3
@@ -7,6 +7,7 @@
|
||||
#include "emu_versions.h"
|
||||
#include "eq_packet.h"
|
||||
#include "net/daybreak_connection.h"
|
||||
#include "event/event_loop.h"
|
||||
|
||||
typedef enum {
|
||||
ESTABLISHED,
|
||||
@@ -23,6 +24,7 @@ struct EQStreamManagerInterfaceOptions
|
||||
{
|
||||
EQStreamManagerInterfaceOptions() {
|
||||
opcode_size = 2;
|
||||
loop = &EQ::EventLoop::GetDefault();
|
||||
}
|
||||
|
||||
EQStreamManagerInterfaceOptions(int port, bool encoded, bool compressed) {
|
||||
@@ -40,22 +42,33 @@ struct EQStreamManagerInterfaceOptions
|
||||
}
|
||||
|
||||
daybreak_options.port = port;
|
||||
loop = &EQ::EventLoop::GetDefault();
|
||||
}
|
||||
|
||||
int opcode_size;
|
||||
bool track_opcode_stats;
|
||||
EQ::Net::DaybreakConnectionManagerOptions daybreak_options;
|
||||
EQ::EventLoop *loop;
|
||||
};
|
||||
|
||||
enum EQStreamPriority : int32_t {
|
||||
High,
|
||||
Normal,
|
||||
Low
|
||||
};
|
||||
|
||||
class EQStreamInterface;
|
||||
class EQStreamManagerInterface
|
||||
{
|
||||
public:
|
||||
EQStreamManagerInterface(const EQStreamManagerInterfaceOptions &options) { m_options = options; }
|
||||
virtual ~EQStreamManagerInterface() { };
|
||||
|
||||
EQStreamManagerInterfaceOptions GetOptions() { return m_options; }
|
||||
const EQStreamManagerInterfaceOptions& GetOptions() const { return m_options; }
|
||||
virtual void SetOptions(const EQStreamManagerInterfaceOptions& options) = 0;
|
||||
EQStreamManagerInterfaceOptions& MutateOptions() { return m_options; }
|
||||
|
||||
virtual void OnNewConnection(std::function<void(std::shared_ptr<EQStreamInterface>)> func) = 0;
|
||||
virtual void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStreamInterface>, EQ::Net::DbProtocolStatus, EQ::Net::DbProtocolStatus)> func) = 0;
|
||||
virtual void SetPriority(EQStreamPriority priority) = 0;
|
||||
protected:
|
||||
EQStreamManagerInterfaceOptions m_options;
|
||||
};
|
||||
|
||||
+47
-81
@@ -26,26 +26,24 @@
|
||||
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
||||
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
||||
|
||||
void EQEmuConfig::parse_config()
|
||||
{
|
||||
|
||||
ShortName = _root["server"]["world"].get("shortname", "").asString();
|
||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||
void EQEmuConfig::parse_config() {
|
||||
|
||||
ShortName = _root["server"]["world"].get("shortname", "").asString();
|
||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||
WorldAddress = _root["server"]["world"].get("address", "").asString();
|
||||
LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
|
||||
MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
|
||||
SharedKey = _root["server"]["world"].get("key", "").asString();
|
||||
LoginCount = 0;
|
||||
MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
|
||||
SharedKey = _root["server"]["world"].get("key", "").asString();
|
||||
LoginCount = 0;
|
||||
|
||||
if (_root["server"]["world"]["loginserver"].isObject()) {
|
||||
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
||||
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
||||
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
||||
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
||||
LoginLegacy = false;
|
||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") LoginLegacy = true;
|
||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
char str[32];
|
||||
loginlist.Clear();
|
||||
do {
|
||||
@@ -55,102 +53,74 @@ void EQEmuConfig::parse_config()
|
||||
}
|
||||
|
||||
auto loginconfig = new LoginConfig;
|
||||
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
|
||||
loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str());
|
||||
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
|
||||
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
|
||||
loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str());
|
||||
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
|
||||
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
||||
|
||||
loginconfig->LoginLegacy = false;
|
||||
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; }
|
||||
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") loginconfig->LoginLegacy = true;
|
||||
loginlist.Insert(loginconfig);
|
||||
} while (LoginCount < 100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//<locked> from xml converts to json as locked: "", so i default to "false".
|
||||
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
||||
Locked = false;
|
||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") Locked = true;
|
||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||
|
||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||
|
||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||
TelnetEnabled = false;
|
||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") TelnetEnabled = true;
|
||||
|
||||
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
||||
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
||||
WorldHTTPEnabled = false;
|
||||
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
||||
WorldHTTPEnabled = false;
|
||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") WorldHTTPEnabled = true;
|
||||
|
||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
||||
WorldHTTPEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* UCS
|
||||
*/
|
||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
||||
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
||||
|
||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
||||
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
||||
|
||||
/**
|
||||
* Database
|
||||
*/
|
||||
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
||||
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
||||
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
||||
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
|
||||
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
||||
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
||||
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
|
||||
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
||||
|
||||
/**
|
||||
* QS
|
||||
*/
|
||||
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
||||
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
||||
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
||||
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
||||
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
||||
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||
|
||||
/**
|
||||
* Zones
|
||||
*/
|
||||
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
||||
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||
|
||||
/**
|
||||
* Files
|
||||
*/
|
||||
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
|
||||
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
|
||||
MailOpCodesFile = _root["server"]["files"].get("mail_opcodes", "mail_opcodes.conf").asString();
|
||||
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
|
||||
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
|
||||
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
|
||||
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
|
||||
|
||||
/**
|
||||
* Directories
|
||||
*/
|
||||
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
|
||||
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
|
||||
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
|
||||
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
|
||||
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
|
||||
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
|
||||
LuaModuleDir = _root["server"]["directories"].get("lua_modules", "lua_modules/").asString();
|
||||
PatchDir = _root["server"]["directories"].get("patches", "./").asString();
|
||||
PatchDir = _root["server"]["directories"].get("patches", "./").asString();
|
||||
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
|
||||
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
||||
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
||||
|
||||
/**
|
||||
* Logs
|
||||
*/
|
||||
LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString();
|
||||
LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString();
|
||||
|
||||
/**
|
||||
* Launcher
|
||||
*/
|
||||
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||
ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
|
||||
#ifdef WIN32
|
||||
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
|
||||
@@ -260,9 +230,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "OpCodesFile") {
|
||||
return (OpCodesFile);
|
||||
}
|
||||
if (var_name == "MailOpCodesFile") {
|
||||
return (MailOpCodesFile);
|
||||
}
|
||||
if (var_name == "PluginPlFile") {
|
||||
return (PluginPlFile);
|
||||
}
|
||||
@@ -345,7 +312,6 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
|
||||
std::cout << "SpellsFile = " << SpellsFile << std::endl;
|
||||
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
|
||||
std::cout << "MailOpcodesFile = " << MailOpCodesFile << std::endl;
|
||||
std::cout << "PluginPlFile = " << PluginPlFile << std::endl;
|
||||
std::cout << "MapDir = " << MapDir << std::endl;
|
||||
std::cout << "QuestDir = " << QuestDir << std::endl;
|
||||
@@ -356,6 +322,6 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "LogDir = " << LogDir << std::endl;
|
||||
std::cout << "ZonePortLow = " << ZonePortLow << std::endl;
|
||||
std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl;
|
||||
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl;
|
||||
std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl;
|
||||
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ class EQEmuConfig
|
||||
// From <files/>
|
||||
std::string SpellsFile;
|
||||
std::string OpCodesFile;
|
||||
std::string MailOpCodesFile;
|
||||
std::string PluginPlFile;
|
||||
|
||||
// From <directories/>
|
||||
|
||||
@@ -95,7 +95,6 @@ enum GameChatColor {
|
||||
EQEmuLogSys::EQEmuLogSys()
|
||||
{
|
||||
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
|
||||
on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {};
|
||||
bool file_logs_enabled = false;
|
||||
int log_platform = 0;
|
||||
}
|
||||
@@ -347,8 +346,6 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
|
||||
#else
|
||||
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
|
||||
#endif
|
||||
|
||||
on_log_console_hook(debug_level, log_category, message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,4 +505,4 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
||||
std::ios_base::app | std::ios_base::out
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,8 +240,7 @@ public:
|
||||
*/
|
||||
uint16 GetGMSayColorFromCategory(uint16 log_category);
|
||||
|
||||
void SetGMSayHandler(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
|
||||
void SetConsoleHandler(std::function<void(uint16 debug_level, uint16 log_type, const std::string&)> f) { on_log_console_hook = f; }
|
||||
void OnLogHookCallBackZone(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -249,7 +248,6 @@ private:
|
||||
* Callback pointer to zone process for hooking logs to zone using GMSay
|
||||
*/
|
||||
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
|
||||
std::function<void(uint16 debug_level, uint16 log_category, const std::string&)> on_log_console_hook;
|
||||
|
||||
/**
|
||||
* Formats log messages like '[Category] This is a log message'
|
||||
|
||||
+10
-10
@@ -7,15 +7,20 @@ namespace EQ
|
||||
{
|
||||
class EventLoop
|
||||
{
|
||||
public:
|
||||
static EventLoop &Get() {
|
||||
static thread_local EventLoop inst;
|
||||
return inst;
|
||||
public:
|
||||
EventLoop() {
|
||||
memset(&m_loop, 0, sizeof(uv_loop_t));
|
||||
uv_loop_init(&m_loop);
|
||||
}
|
||||
|
||||
~EventLoop() {
|
||||
uv_loop_close(&m_loop);
|
||||
}
|
||||
|
||||
static EventLoop &GetDefault() {
|
||||
static EventLoop inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
void Process() {
|
||||
uv_run(&m_loop, UV_RUN_NOWAIT);
|
||||
@@ -23,12 +28,7 @@ namespace EQ
|
||||
|
||||
uv_loop_t* Handle() { return &m_loop; }
|
||||
|
||||
private:
|
||||
EventLoop() {
|
||||
memset(&m_loop, 0, sizeof(uv_loop_t));
|
||||
uv_loop_init(&m_loop);
|
||||
}
|
||||
|
||||
private:
|
||||
EventLoop(const EventLoop&);
|
||||
EventLoop& operator=(const EventLoop&);
|
||||
|
||||
|
||||
+8
-1
@@ -24,7 +24,13 @@ namespace EQ {
|
||||
std::exception error;
|
||||
};
|
||||
|
||||
Task(EQ::EventLoop *loop, TaskFn fn) {
|
||||
m_loop = loop;
|
||||
m_fn = fn;
|
||||
}
|
||||
|
||||
Task(TaskFn fn) {
|
||||
m_loop = &EQ::EventLoop::GetDefault();
|
||||
m_fn = fn;
|
||||
}
|
||||
|
||||
@@ -60,7 +66,7 @@ namespace EQ {
|
||||
|
||||
m_work->data = baton;
|
||||
|
||||
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
|
||||
uv_queue_work(m_loop->Handle(), m_work, [](uv_work_t* req) {
|
||||
TaskBaton *baton = (TaskBaton*)req->data;
|
||||
|
||||
baton->fn([baton](const EQEmu::Any& result) {
|
||||
@@ -92,6 +98,7 @@ namespace EQ {
|
||||
}
|
||||
|
||||
private:
|
||||
EQ::EventLoop *m_loop;
|
||||
TaskFn m_fn;
|
||||
ResolveFn m_then;
|
||||
RejectFn m_catch;
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <future>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Event
|
||||
{
|
||||
class TaskScheduler
|
||||
{
|
||||
public:
|
||||
static const int DefaultThreadCount = 4;
|
||||
|
||||
TaskScheduler() : _running(false)
|
||||
{
|
||||
Start(DefaultThreadCount);
|
||||
}
|
||||
|
||||
TaskScheduler(size_t threads) : _running(false)
|
||||
{
|
||||
Start(threads);
|
||||
}
|
||||
|
||||
~TaskScheduler() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void Start(size_t threads) {
|
||||
if (true == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
for (size_t i = 0; i < threads; ++i) {
|
||||
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||
}
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
if (false == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
_running = false;
|
||||
}
|
||||
|
||||
_cv.notify_all();
|
||||
|
||||
for (auto &t : _threads) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Fn, typename... Args>
|
||||
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
|
||||
using return_type = typename std::result_of<Fn(Args...)>::type;
|
||||
|
||||
auto task = std::make_shared<std::packaged_task<return_type()>>(
|
||||
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
|
||||
);
|
||||
|
||||
std::future<return_type> res = task->get_future();
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
|
||||
if (false == _running) {
|
||||
throw std::runtime_error("Enqueue on stopped scheduler.");
|
||||
}
|
||||
|
||||
_tasks.emplace([task]() { (*task)(); });
|
||||
}
|
||||
|
||||
_cv.notify_one();
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessWork() {
|
||||
for (;;) {
|
||||
std::function<void()> work;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
_cv.wait(lock, [this] { return !_running || !_tasks.empty(); });
|
||||
|
||||
if (false == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
work = std::move(_tasks.front());
|
||||
_tasks.pop();
|
||||
}
|
||||
|
||||
work();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool _running = true;
|
||||
std::vector<std::thread> _threads;
|
||||
std::mutex _lock;
|
||||
std::condition_variable _cv;
|
||||
std::queue<std::function<void()>> _tasks;
|
||||
};
|
||||
}
|
||||
}
|
||||
+20
-2
@@ -6,14 +6,31 @@ namespace EQ {
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer(std::function<void(Timer *)> cb)
|
||||
Timer(EQ::EventLoop *loop, std::function<void(Timer *)> cb)
|
||||
{
|
||||
m_loop = loop;
|
||||
m_timer = nullptr;
|
||||
m_cb = cb;
|
||||
}
|
||||
|
||||
Timer(std::function<void(Timer *)> cb)
|
||||
{
|
||||
m_loop = &EQ::EventLoop::GetDefault();
|
||||
m_timer = nullptr;
|
||||
m_cb = cb;
|
||||
}
|
||||
|
||||
Timer(EQ::EventLoop *loop, uint64_t duration_ms, bool repeats, std::function<void(Timer *)> cb)
|
||||
{
|
||||
m_loop = loop;
|
||||
m_timer = nullptr;
|
||||
m_cb = cb;
|
||||
Start(duration_ms, repeats);
|
||||
}
|
||||
|
||||
Timer(uint64_t duration_ms, bool repeats, std::function<void(Timer *)> cb)
|
||||
{
|
||||
m_loop = &EQ::EventLoop::GetDefault();
|
||||
m_timer = nullptr;
|
||||
m_cb = cb;
|
||||
Start(duration_ms, repeats);
|
||||
@@ -25,7 +42,7 @@ namespace EQ {
|
||||
}
|
||||
|
||||
void Start(uint64_t duration_ms, bool repeats) {
|
||||
auto loop = EventLoop::Get().Handle();
|
||||
auto loop = m_loop->Handle();
|
||||
if (!m_timer) {
|
||||
m_timer = new uv_timer_t;
|
||||
memset(m_timer, 0, sizeof(uv_timer_t));
|
||||
@@ -61,6 +78,7 @@ namespace EQ {
|
||||
m_cb(this);
|
||||
}
|
||||
|
||||
EQ::EventLoop *m_loop;
|
||||
uv_timer_t *m_timer;
|
||||
std::function<void(Timer*)> m_cb;
|
||||
};
|
||||
|
||||
+12
-10
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "faction.h"
|
||||
#include "races.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv)
|
||||
{
|
||||
@@ -60,31 +59,34 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
|
||||
if (fm) {
|
||||
character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, AllyFactionMinimum)) {
|
||||
if (character_value >= 1100) {
|
||||
return FACTION_ALLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, WarmlyFactionMinimum)) {
|
||||
if (character_value >= 750 && character_value <= 1099) {
|
||||
return FACTION_WARMLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, KindlyFactionMinimum)) {
|
||||
if (character_value >= 500 && character_value <= 749) {
|
||||
return FACTION_KINDLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
|
||||
if (character_value >= 100 && character_value <= 499) {
|
||||
return FACTION_AMIABLE;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
|
||||
if (character_value >= 0 && character_value <= 99) {
|
||||
return FACTION_INDIFFERENT;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
|
||||
if (character_value >= -100 && character_value <= -1) {
|
||||
return FACTION_APPREHENSIVE;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
|
||||
if (character_value >= -500 && character_value <= -101) {
|
||||
return FACTION_DUBIOUS;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
|
||||
if (character_value >= -750 && character_value <= -501) {
|
||||
return FACTION_THREATENLY;
|
||||
}
|
||||
return FACTION_SCOWLS;
|
||||
if (character_value <= -751) {
|
||||
return FACTION_SCOWLS;
|
||||
}
|
||||
return FACTION_INDIFFERENT;
|
||||
}
|
||||
|
||||
// this function should check if some races have more than one race define
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
//
|
||||
#define VARSTRUCT_DECODE_TYPE(Type, Buffer) *(Type *)Buffer; Buffer += sizeof(Type);
|
||||
#define VARSTRUCT_DECODE_STRING(String, Buffer) strcpy(String, Buffer); Buffer += strlen(String)+1;
|
||||
#define VARSTRUCT_ENCODE_STRING(Buffer, String) { int length = sprintf(Buffer, "%s", String); Buffer += length + 1; }
|
||||
#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { int length = sprintf(Buffer, "%i", Number); Buffer += length + 1; }
|
||||
#define VARSTRUCT_ENCODE_STRING(Buffer, String) { sprintf(Buffer, "%s", String); Buffer += strlen(String) + 1; }
|
||||
#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { sprintf(Buffer, "%i", Number); Buffer += strlen(Buffer) + 1; }
|
||||
#define VARSTRUCT_ENCODE_TYPE(Type, Buffer, Value) { *(Type *)Buffer = Value; Buffer += sizeof(Type); }
|
||||
#define VARSTRUCT_SKIP_TYPE(Type, Buffer) Buffer += sizeof(Type);
|
||||
|
||||
|
||||
@@ -10,20 +10,27 @@
|
||||
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager()
|
||||
{
|
||||
m_attached = nullptr;
|
||||
m_next_id = 1;
|
||||
memset(&m_timer, 0, sizeof(uv_timer_t));
|
||||
memset(&m_socket, 0, sizeof(uv_udp_t));
|
||||
|
||||
Attach(EQ::EventLoop::Get().Handle());
|
||||
Attach(EventLoop::GetDefault().Handle());
|
||||
}
|
||||
|
||||
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConnectionManagerOptions &opts)
|
||||
{
|
||||
m_attached = nullptr;
|
||||
m_options = opts;
|
||||
m_next_id = 1;
|
||||
memset(&m_timer, 0, sizeof(uv_timer_t));
|
||||
memset(&m_socket, 0, sizeof(uv_udp_t));
|
||||
|
||||
Attach(EQ::EventLoop::Get().Handle());
|
||||
if (opts.loop == nullptr) {
|
||||
Attach(EventLoop::GetDefault().Handle());
|
||||
}
|
||||
else {
|
||||
Attach(opts.loop->Handle());
|
||||
}
|
||||
}
|
||||
|
||||
EQ::Net::DaybreakConnectionManager::~DaybreakConnectionManager()
|
||||
@@ -89,7 +96,7 @@ void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int po
|
||||
{
|
||||
//todo dns resolution
|
||||
|
||||
auto connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, addr, port));
|
||||
auto connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, GetNextId(), addr, port));
|
||||
connection->m_self = connection;
|
||||
|
||||
if (m_on_new_connection) {
|
||||
@@ -227,7 +234,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi
|
||||
StaticPacket p((void*)data, size);
|
||||
auto request = p.GetSerialize<DaybreakConnect>(0);
|
||||
|
||||
connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, request, endpoint, port));
|
||||
connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, GetNextId(), request, endpoint, port));
|
||||
connection->m_self = connection;
|
||||
|
||||
if (m_on_new_connection) {
|
||||
@@ -285,10 +292,18 @@ void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr,
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t EQ::Net::DaybreakConnectionManager::GetNextId()
|
||||
{
|
||||
auto id = m_next_id;
|
||||
m_next_id++;
|
||||
return id;
|
||||
}
|
||||
|
||||
//new connection made as server
|
||||
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port)
|
||||
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, uint64_t id, const DaybreakConnect &connect, const std::string &endpoint, int port)
|
||||
{
|
||||
m_owner = owner;
|
||||
m_id = id;
|
||||
m_last_send = Clock::now();
|
||||
m_last_recv = Clock::now();
|
||||
m_status = StatusConnected;
|
||||
@@ -311,9 +326,10 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
|
||||
}
|
||||
|
||||
//new connection made as client
|
||||
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port)
|
||||
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, uint64_t id, const std::string &endpoint, int port)
|
||||
{
|
||||
m_owner = owner;
|
||||
m_id = id;
|
||||
m_last_send = Clock::now();
|
||||
m_last_recv = Clock::now();
|
||||
m_status = StatusConnecting;
|
||||
@@ -368,7 +384,6 @@ void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliab
|
||||
packet.PutUInt8(0, 0);
|
||||
packet.PutPacket(1, p);
|
||||
InternalQueuePacket(packet, stream, reliable);
|
||||
return;
|
||||
}
|
||||
|
||||
InternalQueuePacket(p, stream, reliable);
|
||||
@@ -385,7 +400,7 @@ EQ::Net::DaybreakConnectionStats EQ::Net::DaybreakConnection::GetStats()
|
||||
|
||||
void EQ::Net::DaybreakConnection::ResetStats()
|
||||
{
|
||||
m_stats.Reset();
|
||||
m_stats = DaybreakConnectionStats();
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::Process()
|
||||
@@ -418,7 +433,6 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
|
||||
auto opcode = p.GetInt8(1);
|
||||
if (p.GetInt8(0) == 0 && (opcode == OP_KeepAlive || opcode == OP_OutboundPing)) {
|
||||
m_stats.bytes_after_decode += p.Length();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,8 +441,6 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
if (m_owner->m_on_error_message) {
|
||||
m_owner->m_on_error_message(fmt::format("Tossed packet that failed CRC of type {0:#x}", p.Length() >= 2 ? p.GetInt8(1) : 0));
|
||||
}
|
||||
|
||||
m_stats.bytes_after_decode += p.Length();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -457,7 +469,6 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
}
|
||||
}
|
||||
|
||||
m_stats.bytes_after_decode += temp.Length();
|
||||
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
||||
}
|
||||
else {
|
||||
@@ -476,12 +487,10 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
}
|
||||
}
|
||||
|
||||
m_stats.bytes_after_decode += temp.Length();
|
||||
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_stats.bytes_after_decode += p.Length();
|
||||
ProcessDecodedPacket(p);
|
||||
}
|
||||
}
|
||||
@@ -1000,7 +1009,7 @@ uint32_t Deflate(const uint8_t* in, uint32_t in_len, uint8_t* out, uint32_t out_
|
||||
zstream.avail_in = in_len;
|
||||
zstream.opaque = Z_NULL;
|
||||
|
||||
deflateInit(&zstream, Z_BEST_SPEED);
|
||||
deflateInit(&zstream, Z_FINISH);
|
||||
zstream.next_out = out;
|
||||
zstream.avail_out = out_len;
|
||||
|
||||
@@ -1096,6 +1105,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
}
|
||||
m_stats.resent_packets++;
|
||||
|
||||
m_stats.resent_time_min = std::min(m_stats.resent_time_min, (uint64_t)time_since_last_send.count());
|
||||
m_stats.resent_time_max = std::max(m_stats.resent_time_max, (uint64_t)time_since_last_send.count());
|
||||
m_stats.resent_time_average = (m_stats.resent_time_average / 2) + (time_since_last_send.count() / 2);
|
||||
|
||||
InternalBufferedSend(p);
|
||||
entry.second.last_sent = now;
|
||||
entry.second.times_resent++;
|
||||
@@ -1125,6 +1138,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
||||
}
|
||||
m_stats.resent_packets++;
|
||||
|
||||
m_stats.resent_time_min = std::min(m_stats.resent_time_min, (uint64_t)time_since_last_send.count());
|
||||
m_stats.resent_time_max = std::max(m_stats.resent_time_max, (uint64_t)time_since_last_send.count());
|
||||
m_stats.resent_time_average = (m_stats.resent_time_average / 2) + (time_since_last_send.count() / 2);
|
||||
|
||||
InternalBufferedSend(p);
|
||||
entry.second.last_sent = now;
|
||||
entry.second.times_resent++;
|
||||
@@ -1292,9 +1309,6 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
||||
};
|
||||
|
||||
if (PacketCanBeEncoded(p)) {
|
||||
|
||||
m_stats.bytes_before_encode += p.Length();
|
||||
|
||||
DynamicPacket out;
|
||||
out.PutPacket(0, p);
|
||||
|
||||
@@ -1342,8 +1356,6 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
m_stats.bytes_before_encode += p.Length();
|
||||
|
||||
uv_udp_send_t *send_req = new uv_udp_send_t;
|
||||
sockaddr_in send_addr;
|
||||
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
class EventLoop;
|
||||
namespace Net
|
||||
{
|
||||
enum DaybreakProtocolOpcode
|
||||
@@ -90,25 +91,10 @@ namespace EQ
|
||||
resent_packets = 0;
|
||||
resent_fragments = 0;
|
||||
resent_full = 0;
|
||||
resent_time_min = 0;
|
||||
resent_time_max = 0;
|
||||
resent_time_average = 0;
|
||||
datarate_remaining = 0.0;
|
||||
bytes_after_decode = 0;
|
||||
bytes_before_encode = 0;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
recv_bytes = 0;
|
||||
sent_bytes = 0;
|
||||
min_ping = 0xFFFFFFFFFFFFFFFFUL;
|
||||
max_ping = 0;
|
||||
avg_ping = 0;
|
||||
created = Clock::now();
|
||||
dropped_datarate_packets = 0;
|
||||
resent_packets = 0;
|
||||
resent_fragments = 0;
|
||||
resent_full = 0;
|
||||
datarate_remaining = 0.0;
|
||||
bytes_after_decode = 0;
|
||||
bytes_before_encode = 0;
|
||||
}
|
||||
|
||||
uint64_t recv_bytes;
|
||||
@@ -128,9 +114,10 @@ namespace EQ
|
||||
uint64_t resent_packets;
|
||||
uint64_t resent_fragments;
|
||||
uint64_t resent_full;
|
||||
uint64_t resent_time_min;
|
||||
uint64_t resent_time_max;
|
||||
uint64_t resent_time_average;
|
||||
double datarate_remaining;
|
||||
uint64_t bytes_after_decode;
|
||||
uint64_t bytes_before_encode;
|
||||
};
|
||||
|
||||
class DaybreakConnectionManager;
|
||||
@@ -138,8 +125,8 @@ namespace EQ
|
||||
class DaybreakConnection
|
||||
{
|
||||
public:
|
||||
DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port);
|
||||
DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port);
|
||||
DaybreakConnection(DaybreakConnectionManager *owner, uint64_t id, const DaybreakConnect &connect, const std::string &endpoint, int port);
|
||||
DaybreakConnection(DaybreakConnectionManager *owner, uint64_t id, const std::string &endpoint, int port);
|
||||
~DaybreakConnection();
|
||||
|
||||
const std::string& RemoteEndpoint() const { return m_endpoint; }
|
||||
@@ -158,6 +145,7 @@ namespace EQ
|
||||
const DaybreakEncodeType* GetEncodePasses() const { return m_encode_passes; }
|
||||
const DaybreakConnectionManager* GetManager() const { return m_owner; }
|
||||
DaybreakConnectionManager* GetManager() { return m_owner; }
|
||||
uint64_t GetId() const { return m_id; }
|
||||
private:
|
||||
DaybreakConnectionManager *m_owner;
|
||||
std::string m_endpoint;
|
||||
@@ -180,6 +168,7 @@ namespace EQ
|
||||
size_t m_rolling_ping;
|
||||
Timestamp m_close_time;
|
||||
double m_outgoing_budget;
|
||||
uint64_t m_id;
|
||||
|
||||
struct DaybreakSentPacket
|
||||
{
|
||||
@@ -257,7 +246,7 @@ namespace EQ
|
||||
resend_delay_min = 150;
|
||||
resend_delay_max = 5000;
|
||||
connect_delay_ms = 500;
|
||||
stale_connection_ms = 30000;
|
||||
stale_connection_ms = 90000;
|
||||
connect_stale_ms = 5000;
|
||||
crc_length = 2;
|
||||
max_packet_size = 512;
|
||||
@@ -269,9 +258,10 @@ namespace EQ
|
||||
simulated_in_packet_loss = 0;
|
||||
simulated_out_packet_loss = 0;
|
||||
tic_rate_hertz = 60.0;
|
||||
resend_timeout = 30000;
|
||||
resend_timeout = 90000;
|
||||
connection_close_time = 2000;
|
||||
outgoing_data_rate = 0.0;
|
||||
loop = nullptr;
|
||||
}
|
||||
|
||||
size_t max_packet_size;
|
||||
@@ -295,6 +285,7 @@ namespace EQ
|
||||
DaybreakEncodeType encode_passes[2];
|
||||
int port;
|
||||
double outgoing_data_rate;
|
||||
EQ::EventLoop *loop;
|
||||
};
|
||||
|
||||
class DaybreakConnectionManager
|
||||
@@ -323,6 +314,7 @@ namespace EQ
|
||||
uv_udp_t m_socket;
|
||||
uv_loop_t *m_attached;
|
||||
DaybreakConnectionManagerOptions m_options;
|
||||
uint64_t m_next_id;
|
||||
std::function<void(std::shared_ptr<DaybreakConnection>)> m_on_new_connection;
|
||||
std::function<void(std::shared_ptr<DaybreakConnection>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
|
||||
std::function<void(std::shared_ptr<DaybreakConnection>, const Packet&)> m_on_packet_recv;
|
||||
@@ -332,6 +324,7 @@ namespace EQ
|
||||
void ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size);
|
||||
std::shared_ptr<DaybreakConnection> FindConnectionByEndpoint(std::string addr, int port);
|
||||
void SendDisconnect(const std::string &addr, int port);
|
||||
uint64_t GetNextId();
|
||||
|
||||
friend class DaybreakConnection;
|
||||
};
|
||||
|
||||
+6
-2
@@ -8,7 +8,7 @@ namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
static void DNSLookup(const std::string &addr, int port, bool ipv6, std::function<void(const std::string&)> cb) {
|
||||
static void DNSLookup(EQ::EventLoop *eloop, const std::string &addr, int port, bool ipv6, std::function<void(const std::string&)> cb) {
|
||||
struct DNSBaton
|
||||
{
|
||||
std::function<void(const std::string&)> cb;
|
||||
@@ -21,7 +21,7 @@ namespace EQ
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
auto loop = EQ::EventLoop::Get().Handle();
|
||||
auto loop = eloop->Handle();
|
||||
uv_getaddrinfo_t *resolver = new uv_getaddrinfo_t();
|
||||
memset(resolver, 0, sizeof(uv_getaddrinfo_t));
|
||||
auto port_str = std::to_string(port);
|
||||
@@ -57,5 +57,9 @@ namespace EQ
|
||||
cb(addr);
|
||||
}, addr.c_str(), port_str.c_str(), &hints);
|
||||
}
|
||||
|
||||
static void DNSLookup(const std::string &addr, int port, bool ipv6, std::function<void(const std::string&)> cb) {
|
||||
DNSLookup(&EQ::EventLoop::GetDefault(), addr, port, ipv6, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,6 @@ EQ::Net::EQStreamManager::~EQStreamManager()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::EQStreamManager::SetOptions(const EQStreamManagerInterfaceOptions &options)
|
||||
{
|
||||
m_options = options;
|
||||
auto &opts = m_daybreak.GetOptions();
|
||||
opts = options.daybreak_options;
|
||||
}
|
||||
|
||||
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
||||
{
|
||||
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
|
||||
@@ -72,7 +65,7 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
||||
opcode = p->GetOpcodeBypass();
|
||||
}
|
||||
else {
|
||||
m_packet_sent_count[static_cast<int>(p->GetOpcode())]++; //Wont bother with bypass tracking of these since those are rare for testing anyway
|
||||
m_packet_sent_count[p->GetOpcode()]++; //Wont bother with bypass tracking of these since those are rare for testing anyway
|
||||
opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode());
|
||||
}
|
||||
|
||||
@@ -122,7 +115,7 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() {
|
||||
}
|
||||
|
||||
EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode);
|
||||
m_packet_recv_count[static_cast<int>(emu_op)]++;
|
||||
m_packet_recv_count[emu_op]++;
|
||||
|
||||
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->GetOptions().opcode_size, p->Length() - m_owner->GetOptions().opcode_size);
|
||||
ret->SetProtocolOpcode(opcode);
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace EQ
|
||||
EQStreamManager(const EQStreamManagerInterfaceOptions &options);
|
||||
~EQStreamManager();
|
||||
|
||||
virtual void SetOptions(const EQStreamManagerInterfaceOptions& options);
|
||||
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
|
||||
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
|
||||
virtual void OnNewConnection(std::function<void(std::shared_ptr<EQStreamInterface>)> func) { m_on_new_connection = func; }
|
||||
virtual void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStreamInterface>, EQ::Net::DbProtocolStatus, EQ::Net::DbProtocolStatus)> func) { m_on_connection_state_change = func; }
|
||||
virtual void SetPriority(EQStreamPriority priority) { }
|
||||
private:
|
||||
DaybreakConnectionManager m_daybreak;
|
||||
std::function<void(std::shared_ptr<EQStream>)> m_on_new_connection;
|
||||
std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
|
||||
std::function<void(std::shared_ptr<EQStreamInterface>)> m_on_new_connection;
|
||||
std::function<void(std::shared_ptr<EQStreamInterface>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
|
||||
std::map<std::shared_ptr<DaybreakConnection>, std::shared_ptr<EQStream>> m_streams;
|
||||
|
||||
void DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection);
|
||||
@@ -66,8 +66,8 @@ namespace EQ
|
||||
std::shared_ptr<DaybreakConnection> m_connection;
|
||||
OpcodeManager **m_opcode_manager;
|
||||
std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue;
|
||||
std::unordered_map<int, int> m_packet_recv_count;
|
||||
std::unordered_map<int, int> m_packet_sent_count;
|
||||
std::unordered_map<EmuOpcode, int> m_packet_recv_count;
|
||||
std::unordered_map<EmuOpcode, int> m_packet_sent_count;
|
||||
friend class EQStreamManager;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,685 @@
|
||||
#include "eqstream_concurrent.h"
|
||||
#include "eqstream_concurrent_message.h"
|
||||
#include "../event/event_loop.h"
|
||||
#include "../event/timer.h"
|
||||
#include "../string_util.h"
|
||||
#include "../opcodemgr.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../eqemu_logsys_fmt.h"
|
||||
#include "daybreak_connection.h"
|
||||
#include <thread>
|
||||
#include <concurrentqueue.h>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
|
||||
struct EQ::Net::ConcurrentEQStreamManager::Impl
|
||||
{
|
||||
std::thread background;
|
||||
bool background_running;
|
||||
moodycamel::ConcurrentQueue<ceqs_msg_t> foreground_queue;
|
||||
moodycamel::ConcurrentQueue<ceqs_msg_t> background_queue;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<DaybreakConnection>> connections;
|
||||
std::unique_ptr<EQ::Timer> foreground_loop_timer;
|
||||
std::unique_ptr<EQ::Timer> background_loop_timer;
|
||||
std::unique_ptr<EQ::Timer> background_update_stats_timer;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<ConcurrentEQStream>> streams;
|
||||
std::function<void(std::shared_ptr<EQStreamInterface>)> on_new_connection;
|
||||
std::function<void(std::shared_ptr<EQStreamInterface>, EQ::Net::DbProtocolStatus, EQ::Net::DbProtocolStatus)> on_connection_state_change;
|
||||
EQStreamPriority priority;
|
||||
};
|
||||
|
||||
EQ::Net::ConcurrentEQStreamManager::ConcurrentEQStreamManager(const EQStreamManagerInterfaceOptions &options)
|
||||
: EQStreamManagerInterface(options)
|
||||
{
|
||||
_impl.reset(new Impl());
|
||||
_impl->background = std::thread(std::bind(&ConcurrentEQStreamManager::_BackgroundThread, this));
|
||||
_impl->foreground_loop_timer.reset(new EQ::Timer(options.loop, 16, true,
|
||||
std::bind(&ConcurrentEQStreamManager::_ForegroundTimer, this, std::placeholders::_1)));
|
||||
_impl->priority = EQStreamPriority::High;
|
||||
}
|
||||
|
||||
EQ::Net::ConcurrentEQStreamManager::~ConcurrentEQStreamManager()
|
||||
{
|
||||
for (auto &s : _impl->streams) {
|
||||
s.second->_Invalidate();
|
||||
}
|
||||
|
||||
_impl->foreground_loop_timer.release();
|
||||
|
||||
//Tell the background to shutdown and wait for it to actually do so
|
||||
ceqs_terminate_msg_t msg;
|
||||
msg.type = ceqs_msg_type::TerminateBackground;
|
||||
|
||||
_PushToBackgroundQueue((ceqs_msg_t*)&msg);
|
||||
_impl->background.join();
|
||||
|
||||
//Go through our incoming messages to make sure we clean up any packets in that need to be freed
|
||||
ceqs_msg_t eqs_msg;
|
||||
|
||||
while (_impl->foreground_queue.try_dequeue(eqs_msg)) {
|
||||
if (eqs_msg.type == ceqs_msg_type::PacketRecv) {
|
||||
ceqs_packet_recv_msg_t *eqs_msg_in = (ceqs_packet_recv_msg_t*)&eqs_msg;
|
||||
|
||||
delete eqs_msg_in->packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConcurrentEQStreamManager::_BackgroundThread() {
|
||||
_impl->background_running = true;
|
||||
EQ::EventLoop loop;
|
||||
auto &eqs_opts = GetOptions();
|
||||
auto opts = eqs_opts.daybreak_options;
|
||||
opts.loop = &loop;
|
||||
|
||||
std::unique_ptr<DaybreakConnectionManager> dbcm(new DaybreakConnectionManager(opts));
|
||||
dbcm->OnNewConnection(std::bind(&ConcurrentEQStreamManager::DaybreakNewConnection, this, std::placeholders::_1));
|
||||
dbcm->OnConnectionStateChange(std::bind(&ConcurrentEQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
dbcm->OnPacketRecv(std::bind(&ConcurrentEQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
_impl->background_loop_timer.reset(new EQ::Timer(&loop, 16, true,
|
||||
std::bind(&ConcurrentEQStreamManager::_BackgroundTimer, this, std::placeholders::_1)));
|
||||
|
||||
_impl->background_update_stats_timer.reset(new EQ::Timer(&loop, 500, true,
|
||||
std::bind(&ConcurrentEQStreamManager::_BackgroundUpdateStatsTimer, this, std::placeholders::_1)));
|
||||
|
||||
while (true == _impl->background_running) {
|
||||
loop.Process();
|
||||
|
||||
switch (_impl->priority) {
|
||||
case EQStreamPriority::Low:
|
||||
Sleep(10);
|
||||
break;
|
||||
case EQStreamPriority::Normal:
|
||||
Sleep(5);
|
||||
break;
|
||||
case EQStreamPriority::High:
|
||||
Sleep(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_impl->background_loop_timer.release();
|
||||
_impl->background_update_stats_timer.release();
|
||||
dbcm.release();
|
||||
|
||||
ceqs_msg_t eqs_msg;
|
||||
while (_impl->background_queue.try_dequeue(eqs_msg)) {
|
||||
if (eqs_msg.type == ceqs_msg_type::QueuePacket) {
|
||||
ceqs_queue_packet_msg_t *eqs_msg_in = (ceqs_queue_packet_msg_t*)&eqs_msg;
|
||||
delete eqs_msg_in->packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Called by background
|
||||
void EQ::Net::ConcurrentEQStreamManager::_BackgroundTimer(EQ::Timer * t)
|
||||
{
|
||||
ceqs_msg_t msg_queue[16];
|
||||
size_t count = 0;
|
||||
while ((count = _impl->background_queue.try_dequeue_bulk(msg_queue, 16)) != 0) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
_ProcessBackgroundMessage(msg_queue[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConcurrentEQStreamManager::_BackgroundUpdateStatsTimer(EQ::Timer *t)
|
||||
{
|
||||
ceqs_msg_t msgs[16];
|
||||
int i = 0;
|
||||
|
||||
for (auto &c : _impl->connections) {
|
||||
auto &connection = c.second;
|
||||
auto msg = (ceqs_update_stats_msg_t*)&msgs[i];
|
||||
|
||||
msg->type = ceqs_msg_type::UpdateStats;
|
||||
msg->stream_id = connection->GetId();
|
||||
msg->stats = connection->GetStats();
|
||||
i++;
|
||||
|
||||
if (i >= 16) {
|
||||
_impl->foreground_queue.enqueue_bulk(msgs, 16);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
_impl->foreground_queue.enqueue_bulk(msgs, i);
|
||||
}
|
||||
}
|
||||
|
||||
//Called by background
|
||||
void EQ::Net::ConcurrentEQStreamManager::_ProcessBackgroundMessage(const ceqs_msg_t &msg)
|
||||
{
|
||||
switch (msg.type) {
|
||||
case ceqs_msg_type::QueuePacket:
|
||||
{
|
||||
ceqs_queue_packet_msg_t *msg_in = (ceqs_queue_packet_msg_t*)&msg;
|
||||
|
||||
auto iter = _impl->connections.find(msg_in->stream_id);
|
||||
if (iter != _impl->connections.end()) {
|
||||
iter->second->QueuePacket(*msg_in->packet, 0, msg_in->ack_req);
|
||||
}
|
||||
|
||||
delete msg_in->packet;
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::TerminateBackground:
|
||||
{
|
||||
_impl->background_running = false;
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::CloseConnection:
|
||||
{
|
||||
ceqs_close_connection_msg_t *msg_in = (ceqs_close_connection_msg_t*)&msg;
|
||||
auto iter = _impl->connections.find(msg_in->stream_id);
|
||||
if (iter != _impl->connections.end()) {
|
||||
iter->second->Close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::ResetStats:
|
||||
{
|
||||
ceqs_reset_stats_msg_t *msg_in = (ceqs_reset_stats_msg_t*)&msg;
|
||||
auto iter = _impl->connections.find(msg_in->stream_id);
|
||||
if (iter != _impl->connections.end()) {
|
||||
iter->second->ResetStats();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::SetPriority:
|
||||
{
|
||||
ceqs_set_priority_msg_t *msg_in = (ceqs_set_priority_msg_t*)&msg;
|
||||
_impl->priority = msg_in->priority;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStreamManager::_ForegroundTimer(EQ::Timer *t)
|
||||
{
|
||||
ceqs_msg_t msg_queue[16];
|
||||
size_t count = 0;
|
||||
while ((count = _impl->foreground_queue.try_dequeue_bulk(msg_queue, 16)) != 0) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
_ProcessForegroundMessage(msg_queue[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStreamManager::_ProcessForegroundMessage(const ceqs_msg_t &msg)
|
||||
{
|
||||
switch (msg.type) {
|
||||
case ceqs_msg_type::NewConnection:
|
||||
{
|
||||
ceqs_new_connection_msg_t *msg_in = (ceqs_new_connection_msg_t*)&msg;
|
||||
|
||||
std::shared_ptr<ConcurrentEQStream> stream(new ConcurrentEQStream(this,
|
||||
msg_in->stream_id,
|
||||
msg_in->endpoint,
|
||||
msg_in->remote_port,
|
||||
(DbProtocolStatus)msg_in->state));
|
||||
|
||||
_impl->streams.insert(std::make_pair(msg_in->stream_id, stream));
|
||||
if (_impl->on_new_connection) {
|
||||
_impl->on_new_connection(stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::ConnectionStateChange:
|
||||
{
|
||||
ceqs_connection_state_change_msg_t *msg_in = (ceqs_connection_state_change_msg_t*)&msg;
|
||||
|
||||
auto iter = _impl->streams.find(msg_in->stream_id);
|
||||
if (iter != _impl->streams.end()) {
|
||||
iter->second->_SetState((DbProtocolStatus)msg_in->to);
|
||||
|
||||
if ((DbProtocolStatus)msg_in->to == DbProtocolStatus::StatusDisconnected || (DbProtocolStatus)msg_in->to == DbProtocolStatus::StatusDisconnecting) {
|
||||
_impl->streams.erase(iter);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::PacketRecv:
|
||||
{
|
||||
ceqs_packet_recv_msg_t *msg_in = (ceqs_packet_recv_msg_t*)&msg;
|
||||
std::unique_ptr<EQ::Net::Packet> p(msg_in->packet);
|
||||
|
||||
auto iter = _impl->streams.find(msg_in->stream_id);
|
||||
if (iter != _impl->streams.end()) {
|
||||
iter->second->_RecvPacket(std::move(p));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ceqs_msg_type::UpdateStats:
|
||||
{
|
||||
ceqs_update_stats_msg_t *msg_in = (ceqs_update_stats_msg_t*)&msg;
|
||||
auto iter = _impl->streams.find(msg_in->stream_id);
|
||||
if (iter != _impl->streams.end()) {
|
||||
iter->second->_UpdateStats(msg_in->stats);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConcurrentEQStreamManager::_PushToBackgroundQueue(ceqs_msg_t *msg)
|
||||
{
|
||||
_impl->background_queue.enqueue(*msg);
|
||||
}
|
||||
|
||||
void EQ::Net::ConcurrentEQStreamManager::_PushToForegroundQueue(ceqs_msg_t *msg)
|
||||
{
|
||||
_impl->foreground_queue.enqueue(*msg);
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStreamManager::OnNewConnection(std::function<void(std::shared_ptr<EQStreamInterface>)> func)
|
||||
{
|
||||
_impl->on_new_connection = func;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStreamManager::OnConnectionStateChange(std::function<void(std::shared_ptr<EQStreamInterface>, DbProtocolStatus, DbProtocolStatus)> func)
|
||||
{
|
||||
_impl->on_connection_state_change = func;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStreamManager::SetPriority(EQStreamPriority priority)
|
||||
{
|
||||
ceqs_set_priority_msg_t msg;
|
||||
msg.type = ceqs_msg_type::SetPriority;
|
||||
msg.priority = priority;
|
||||
_PushToBackgroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
//Called by background
|
||||
void EQ::Net::ConcurrentEQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
||||
{
|
||||
_impl->connections.insert(std::make_pair(connection->GetId(), connection));
|
||||
ceqs_new_connection_msg_t msg;
|
||||
msg.type = ceqs_msg_type::NewConnection;
|
||||
msg.stream_id = connection->GetId();
|
||||
msg.remote_port = connection->RemotePort();
|
||||
msg.state = connection->GetStatus();
|
||||
strcpy(msg.endpoint, connection->RemoteEndpoint().c_str());
|
||||
msg.endpoint[connection->RemoteEndpoint().length()] = 0;
|
||||
|
||||
//Make sure the foreground gets this message
|
||||
_PushToForegroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
//Called by background
|
||||
void EQ::Net::ConcurrentEQStreamManager::DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to)
|
||||
{
|
||||
if (to == DbProtocolStatus::StatusDisconnecting || to == DbProtocolStatus::StatusDisconnected) {
|
||||
auto iter = _impl->connections.find(connection->GetId());
|
||||
if (iter != _impl->connections.end()) {
|
||||
_impl->connections.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
ceqs_connection_state_change_msg_t msg;
|
||||
msg.type = ceqs_msg_type::ConnectionStateChange;
|
||||
msg.stream_id = connection->GetId();
|
||||
msg.from = (int)from;
|
||||
msg.to = (int)to;
|
||||
|
||||
//Make sure the foreground gets this message
|
||||
_PushToForegroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
//Called by background
|
||||
void EQ::Net::ConcurrentEQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, const Packet &p)
|
||||
{
|
||||
ceqs_packet_recv_msg_t msg;
|
||||
msg.type = ceqs_msg_type::PacketRecv;
|
||||
msg.stream_id = connection->GetId();
|
||||
msg.packet = new DynamicPacket();
|
||||
msg.packet->PutPacket(0, p);
|
||||
|
||||
//Make sure the foreground gets this message
|
||||
_PushToForegroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
struct EQ::Net::ConcurrentEQStream::Impl
|
||||
{
|
||||
ConcurrentEQStreamManager *parent;
|
||||
uint64_t id;
|
||||
std::string remote_endpoint;
|
||||
int remote_port;
|
||||
uint32_t remote_ip;
|
||||
DbProtocolStatus state;
|
||||
std::deque<std::unique_ptr<EQ::Net::Packet>> packet_queue;
|
||||
OpcodeManager **opcode_manager;
|
||||
DaybreakConnectionStats stats;
|
||||
std::unordered_map<EmuOpcode, int> packet_recv_count;
|
||||
std::unordered_map<EmuOpcode, int> packet_sent_count;
|
||||
};
|
||||
|
||||
//Called by foreground
|
||||
EQ::Net::ConcurrentEQStream::ConcurrentEQStream(ConcurrentEQStreamManager *parent, uint64_t id, const std::string &remote_endpoint, int remote_port, DbProtocolStatus state)
|
||||
{
|
||||
_impl.reset(new Impl());
|
||||
_impl->parent = parent;
|
||||
_impl->id = id;
|
||||
_impl->remote_endpoint = remote_endpoint;
|
||||
_impl->remote_port = remote_port;
|
||||
_impl->remote_ip = inet_addr(remote_endpoint.c_str());
|
||||
_impl->state = state;
|
||||
_impl->opcode_manager = nullptr;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQ::Net::ConcurrentEQStream::~ConcurrentEQStream()
|
||||
{
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
||||
{
|
||||
if (!_impl->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_impl->opcode_manager && *_impl->opcode_manager) {
|
||||
auto &options = _impl->parent->GetOptions();
|
||||
uint16 opcode = 0;
|
||||
if (p->GetOpcodeBypass() != 0) {
|
||||
opcode = p->GetOpcodeBypass();
|
||||
}
|
||||
else {
|
||||
_impl->packet_sent_count[p->GetOpcode()]++;
|
||||
opcode = (*_impl->opcode_manager)->EmuToEQ(p->GetOpcode());
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket *out = new EQ::Net::DynamicPacket();
|
||||
switch (options.opcode_size) {
|
||||
case 1:
|
||||
out->PutUInt8(0, opcode);
|
||||
out->PutData(1, p->pBuffer, p->size);
|
||||
break;
|
||||
case 2:
|
||||
out->PutUInt16(0, opcode);
|
||||
out->PutData(2, p->pBuffer, p->size);
|
||||
break;
|
||||
}
|
||||
|
||||
ceqs_queue_packet_msg_t msg;
|
||||
msg.type = ceqs_msg_type::QueuePacket;
|
||||
msg.stream_id = _impl->id;
|
||||
msg.packet = out;
|
||||
msg.ack_req = ack_req;
|
||||
|
||||
//Make sure the background gets this message
|
||||
_impl->parent->_PushToBackgroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
{
|
||||
QueuePacket(*p, ack_req);
|
||||
delete *p;
|
||||
*p = nullptr;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQApplicationPacket *EQ::Net::ConcurrentEQStream::PopPacket()
|
||||
{
|
||||
if (!_impl->parent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (_impl->packet_queue.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (_impl->opcode_manager != nullptr && *_impl->opcode_manager != nullptr) {
|
||||
auto &options = _impl->parent->GetOptions();
|
||||
auto &p = _impl->packet_queue.front();
|
||||
|
||||
uint16 opcode = 0;
|
||||
switch (options.opcode_size) {
|
||||
case 1:
|
||||
opcode = p->GetUInt8(0);
|
||||
break;
|
||||
case 2:
|
||||
opcode = p->GetUInt16(0);
|
||||
break;
|
||||
}
|
||||
|
||||
EmuOpcode emu_op = (*_impl->opcode_manager)->EQToEmu(opcode);
|
||||
_impl->packet_recv_count[emu_op]++;
|
||||
|
||||
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + options.opcode_size, p->Length() - options.opcode_size);
|
||||
ret->SetProtocolOpcode(opcode);
|
||||
_impl->packet_queue.pop_front();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::Close()
|
||||
{
|
||||
if (!_impl->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
ceqs_close_connection_msg_t msg;
|
||||
msg.type = ceqs_msg_type::CloseConnection;
|
||||
msg.stream_id = _impl->id;
|
||||
|
||||
_impl->parent->_PushToBackgroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::ReleaseFromUse()
|
||||
{
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::RemoveData()
|
||||
{
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
std::string EQ::Net::ConcurrentEQStream::GetRemoteAddr() const
|
||||
{
|
||||
return _impl->remote_endpoint;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
uint32 EQ::Net::ConcurrentEQStream::GetRemoteIP() const
|
||||
{
|
||||
return _impl->remote_ip;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
uint16 EQ::Net::ConcurrentEQStream::GetRemotePort() const
|
||||
{
|
||||
return _impl->remote_port;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
bool EQ::Net::ConcurrentEQStream::CheckState(EQStreamState state)
|
||||
{
|
||||
return GetState() == state;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
std::string EQ::Net::ConcurrentEQStream::Describe() const
|
||||
{
|
||||
return "Concurrent EQStream";
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::SetActive(bool val)
|
||||
{
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQStreamInterface::MatchState EQ::Net::ConcurrentEQStream::CheckSignature(const Signature *sig)
|
||||
{
|
||||
if (!_impl->parent) {
|
||||
return MatchFailed;
|
||||
}
|
||||
|
||||
if (!_impl->packet_queue.empty()) {
|
||||
auto& options = _impl->parent->GetOptions();
|
||||
auto p = _impl->packet_queue.front().get();
|
||||
uint16 opcode = 0;
|
||||
size_t length = p->Length() - options.opcode_size;
|
||||
switch (options.opcode_size) {
|
||||
case 1:
|
||||
opcode = p->GetUInt8(0);
|
||||
break;
|
||||
case 2:
|
||||
opcode = p->GetUInt16(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sig->ignore_eq_opcode != 0 && opcode == sig->ignore_eq_opcode) {
|
||||
if (_impl->packet_queue.size() > 1) {
|
||||
p = _impl->packet_queue[1].get();
|
||||
opcode = 0;
|
||||
length = p->Length() - options.opcode_size;
|
||||
switch (options.opcode_size) {
|
||||
case 1:
|
||||
opcode = p->GetUInt8(0);
|
||||
break;
|
||||
case 2:
|
||||
opcode = p->GetUInt16(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return MatchNotReady;
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == sig->first_eq_opcode) {
|
||||
if (length == sig->first_length) {
|
||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length matched {3}",
|
||||
GetRemoteAddr(), GetRemotePort(), sig->first_eq_opcode, length);
|
||||
return MatchSuccessful;
|
||||
}
|
||||
else if (length == 0) {
|
||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length is ignored.",
|
||||
GetRemoteAddr(), GetRemotePort(), sig->first_eq_opcode);
|
||||
return MatchSuccessful;
|
||||
}
|
||||
else {
|
||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} but length {3} did not match expected {4}",
|
||||
GetRemoteAddr(), GetRemotePort(), sig->first_eq_opcode, length, sig->first_length);
|
||||
return MatchFailed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode {1:#x} did not match expected {2:#x}",
|
||||
GetRemoteAddr(), GetRemotePort(), opcode, sig->first_eq_opcode);
|
||||
return MatchFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return MatchNotReady;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQStreamState EQ::Net::ConcurrentEQStream::GetState()
|
||||
{
|
||||
switch (_impl->state) {
|
||||
case StatusConnecting:
|
||||
return UNESTABLISHED;
|
||||
case StatusConnected:
|
||||
return ESTABLISHED;
|
||||
case StatusDisconnecting:
|
||||
return DISCONNECTING;
|
||||
default:
|
||||
return CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::SetOpcodeManager(OpcodeManager **opm)
|
||||
{
|
||||
_impl->opcode_manager = opm;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQStreamInterface::Stats EQ::Net::ConcurrentEQStream::GetStats() const
|
||||
{
|
||||
EQStreamInterface::Stats ret;
|
||||
ret.DaybreakStats = _impl->stats;
|
||||
|
||||
for (int i = 0; i < _maxEmuOpcode; ++i) {
|
||||
ret.RecvCount[i] = 0;
|
||||
ret.SentCount[i] = 0;
|
||||
}
|
||||
|
||||
for (auto &s : _impl->packet_sent_count) {
|
||||
ret.SentCount[s.first] = s.second;
|
||||
}
|
||||
|
||||
for (auto &r : _impl->packet_recv_count) {
|
||||
ret.RecvCount[r.first] = r.second;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::ResetStats()
|
||||
{
|
||||
if (!_impl->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
ceqs_reset_stats_msg_t msg;
|
||||
msg.type = ceqs_msg_type::ResetStats;
|
||||
msg.stream_id = _impl->id;
|
||||
|
||||
_impl->parent->_PushToBackgroundQueue((ceqs_msg_t*)&msg);
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
EQStreamManagerInterface *EQ::Net::ConcurrentEQStream::GetManager() const
|
||||
{
|
||||
return _impl->parent;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::_SetState(DbProtocolStatus state)
|
||||
{
|
||||
_impl->state = state;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::_RecvPacket(std::unique_ptr<EQ::Net::Packet> p)
|
||||
{
|
||||
_impl->packet_queue.push_back(std::move(p));
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::_UpdateStats(const DaybreakConnectionStats &stats)
|
||||
{
|
||||
_impl->stats = stats;
|
||||
}
|
||||
|
||||
//Called by foreground
|
||||
void EQ::Net::ConcurrentEQStream::_Invalidate()
|
||||
{
|
||||
_impl->parent = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include "../eq_stream_intf.h"
|
||||
#include "eqstream_concurrent_message.h"
|
||||
#include <memory>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
class Timer;
|
||||
namespace Net
|
||||
{
|
||||
class ConcurrentEQStream;
|
||||
class ConcurrentEQStreamManager : public EQStreamManagerInterface
|
||||
{
|
||||
public:
|
||||
ConcurrentEQStreamManager(const EQStreamManagerInterfaceOptions &options);
|
||||
~ConcurrentEQStreamManager();
|
||||
|
||||
virtual void OnNewConnection(std::function<void(std::shared_ptr<EQStreamInterface>)> func);
|
||||
virtual void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStreamInterface>, EQ::Net::DbProtocolStatus, EQ::Net::DbProtocolStatus)> func);
|
||||
virtual void SetPriority(EQStreamPriority priority);
|
||||
|
||||
void _PushToBackgroundQueue(ceqs_msg_t* msg);
|
||||
void _PushToForegroundQueue(ceqs_msg_t* msg);
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> _impl;
|
||||
void _BackgroundThread();
|
||||
void _BackgroundTimer(EQ::Timer *t);
|
||||
void _BackgroundUpdateStatsTimer(EQ::Timer *t);
|
||||
void _ProcessBackgroundMessage(const ceqs_msg_t &msg);
|
||||
void _ForegroundTimer(EQ::Timer *t);
|
||||
void _ProcessForegroundMessage(const ceqs_msg_t &msg);
|
||||
|
||||
void DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection);
|
||||
void DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to);
|
||||
void DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, const Packet &p);
|
||||
};
|
||||
|
||||
class ConcurrentEQStream : public EQStreamInterface
|
||||
{
|
||||
public:
|
||||
ConcurrentEQStream(ConcurrentEQStreamManager *parent, uint64_t id, const std::string &remote_endpoint, int remote_port, DbProtocolStatus state);
|
||||
~ConcurrentEQStream();
|
||||
|
||||
virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req = true);
|
||||
virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req = true);
|
||||
virtual EQApplicationPacket *PopPacket();
|
||||
virtual void Close();
|
||||
virtual void ReleaseFromUse();
|
||||
virtual void RemoveData();
|
||||
virtual std::string GetRemoteAddr() const;
|
||||
virtual uint32 GetRemoteIP() const;
|
||||
virtual uint16 GetRemotePort() const;
|
||||
virtual bool CheckState(EQStreamState state);
|
||||
virtual std::string Describe() const;
|
||||
virtual void SetActive(bool val);
|
||||
virtual MatchState CheckSignature(const Signature *sig);
|
||||
virtual EQStreamState GetState();
|
||||
virtual void SetOpcodeManager(OpcodeManager **opm);
|
||||
virtual Stats GetStats() const;
|
||||
virtual void ResetStats();
|
||||
virtual EQStreamManagerInterface* GetManager() const;
|
||||
|
||||
void _SetState(DbProtocolStatus state);
|
||||
void _RecvPacket(std::unique_ptr<EQ::Net::Packet> p);
|
||||
void _UpdateStats(const DaybreakConnectionStats &stats);
|
||||
void _Invalidate();
|
||||
private:
|
||||
struct Impl;
|
||||
|
||||
std::unique_ptr<Impl> _impl;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#define EQSM_PAD_LEN 252
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
class DynamicPacket;
|
||||
enum ceqs_msg_type : uint32_t
|
||||
{
|
||||
//Sent by background
|
||||
NewConnection,
|
||||
ConnectionStateChange,
|
||||
PacketRecv,
|
||||
UpdateStats,
|
||||
//Sent by foreground
|
||||
QueuePacket,
|
||||
TerminateBackground,
|
||||
CloseConnection,
|
||||
ResetStats,
|
||||
SetPriority
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
char padding[EQSM_PAD_LEN];
|
||||
} ceqs_msg_t;
|
||||
|
||||
//Sent by background
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
int remote_port;
|
||||
int state;
|
||||
char endpoint[64];
|
||||
} ceqs_new_connection_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
int from;
|
||||
int to;
|
||||
} ceqs_connection_state_change_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
EQ::Net::DynamicPacket *packet;
|
||||
} ceqs_packet_recv_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
DaybreakConnectionStats stats;
|
||||
} ceqs_update_stats_msg_t;
|
||||
|
||||
//Sent by foreground
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
EQ::Net::DynamicPacket *packet;
|
||||
bool ack_req;
|
||||
} ceqs_queue_packet_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
} ceqs_close_connection_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
uint64_t stream_id;
|
||||
} ceqs_reset_stats_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
} ceqs_terminate_msg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ceqs_msg_type type;
|
||||
EQStreamPriority priority;
|
||||
} ceqs_set_priority_msg_t;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ EQ::Net::TCPConnection::~TCPConnection() {
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::Connect(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
|
||||
void EQ::Net::TCPConnection::Connect(EQ::EventLoop *loop, const std::string & addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
|
||||
{
|
||||
struct EQTCPConnectBaton
|
||||
{
|
||||
@@ -23,10 +23,9 @@ void EQ::Net::TCPConnection::Connect(const std::string &addr, int port, bool ipv
|
||||
std::function<void(std::shared_ptr<EQ::Net::TCPConnection>)> cb;
|
||||
};
|
||||
|
||||
auto loop = EQ::EventLoop::Get().Handle();
|
||||
uv_tcp_t *socket = new uv_tcp_t;
|
||||
memset(socket, 0, sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, socket);
|
||||
uv_tcp_init(loop->Handle(), socket);
|
||||
|
||||
sockaddr_storage iaddr;
|
||||
if (ipv6) {
|
||||
@@ -64,6 +63,11 @@ void EQ::Net::TCPConnection::Connect(const std::string &addr, int port, bool ipv
|
||||
});
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::Connect(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
|
||||
{
|
||||
Connect(&EventLoop::GetDefault(), addr, port, ipv6, cb);
|
||||
}
|
||||
|
||||
void EQ::Net::TCPConnection::Start() {
|
||||
uv_read_start((uv_stream_t*)m_socket, [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||
buf->base = new char[suggested_size];
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
class EventLoop;
|
||||
namespace Net
|
||||
{
|
||||
class TCPConnection
|
||||
@@ -15,6 +16,7 @@ namespace EQ
|
||||
TCPConnection(uv_tcp_t *socket);
|
||||
~TCPConnection();
|
||||
|
||||
static void Connect(EQ::EventLoop *loop, const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
static void Connect(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
|
||||
void Start();
|
||||
|
||||
@@ -7,6 +7,13 @@ void on_close_tcp_server_handle(uv_handle_t* handle) {
|
||||
|
||||
EQ::Net::TCPServer::TCPServer()
|
||||
{
|
||||
m_loop = &EventLoop::GetDefault();
|
||||
m_socket = nullptr;
|
||||
}
|
||||
|
||||
EQ::Net::TCPServer::TCPServer(EQ::EventLoop *loop)
|
||||
{
|
||||
m_loop = loop;
|
||||
m_socket = nullptr;
|
||||
}
|
||||
|
||||
@@ -32,7 +39,7 @@ void EQ::Net::TCPServer::Listen(const std::string &addr, int port, bool ipv6, st
|
||||
|
||||
m_on_new_connection = cb;
|
||||
|
||||
auto loop = EQ::EventLoop::Get().Handle();
|
||||
auto loop = m_loop->Handle();
|
||||
m_socket = new uv_tcp_t;
|
||||
memset(m_socket, 0, sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, m_socket);
|
||||
@@ -53,7 +60,7 @@ void EQ::Net::TCPServer::Listen(const std::string &addr, int port, bool ipv6, st
|
||||
return;
|
||||
}
|
||||
|
||||
auto loop = EQ::EventLoop::Get().Handle();
|
||||
auto loop = server->loop;
|
||||
uv_tcp_t *client = new uv_tcp_t;
|
||||
memset(client, 0, sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, client);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_connection.h"
|
||||
#include "../event/event_loop.h"
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
@@ -10,6 +11,7 @@ namespace EQ
|
||||
{
|
||||
public:
|
||||
TCPServer();
|
||||
TCPServer(EQ::EventLoop *loop);
|
||||
~TCPServer();
|
||||
|
||||
void Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
@@ -19,7 +21,8 @@ namespace EQ
|
||||
|
||||
private:
|
||||
std::function<void(std::shared_ptr<TCPConnection>)> m_on_new_connection;
|
||||
EQ::EventLoop *m_loop;
|
||||
uv_tcp_t *m_socket;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
#include "websocket_server.h"
|
||||
#include "../event/event_loop.h"
|
||||
#include "../event/timer.h"
|
||||
#include <fmt/format.h>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
|
||||
struct MethodHandlerEntry
|
||||
{
|
||||
MethodHandlerEntry() {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
MethodHandlerEntry(EQ::Net::WebsocketServer::MethodHandler h, int s) {
|
||||
handler = h;
|
||||
status = s;
|
||||
}
|
||||
|
||||
EQ::Net::WebsocketServer::MethodHandler handler;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct EQ::Net::WebsocketServer::Impl
|
||||
{
|
||||
std::unique_ptr<TCPServer> server;
|
||||
std::unique_ptr<EQ::Timer> ping_timer;
|
||||
std::map<std::shared_ptr<websocket_connection>, std::unique_ptr<WebsocketServerConnection>> connections;
|
||||
std::map<std::string, MethodHandlerEntry> methods;
|
||||
websocket_server ws_server;
|
||||
LoginHandler login_handler;
|
||||
std::array<std::unordered_set<WebsocketServerConnection*>, SubscriptionEventMax> subscriptions;
|
||||
};
|
||||
|
||||
EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||
{
|
||||
_impl.reset(new Impl());
|
||||
_impl->server.reset(new EQ::Net::TCPServer());
|
||||
_impl->server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
auto wsc = _impl->ws_server.get_connection();
|
||||
WebsocketServerConnection *c = new WebsocketServerConnection(this, connection, wsc);
|
||||
_impl->connections.insert(std::make_pair(wsc, std::unique_ptr<WebsocketServerConnection>(c)));
|
||||
});
|
||||
|
||||
_impl->ws_server.set_write_handler(
|
||||
[this](websocketpp::connection_hdl hdl, char const *data, size_t size) -> websocketpp::lib::error_code {
|
||||
auto c = _impl->ws_server.get_con_from_hdl(hdl);
|
||||
auto iter = _impl->connections.find(c);
|
||||
if (iter != _impl->connections.end()) {
|
||||
iter->second->GetTCPConnection()->Write(data, size);
|
||||
}
|
||||
|
||||
return websocketpp::lib::error_code();
|
||||
});
|
||||
|
||||
_impl->ping_timer.reset(new EQ::Timer(5000, true, [this](EQ::Timer *t) {
|
||||
auto iter = _impl->connections.begin();
|
||||
|
||||
while (iter != _impl->connections.end()) {
|
||||
try {
|
||||
auto &connection = iter->second;
|
||||
connection->GetWebsocketConnection()->ping("keepalive");
|
||||
}
|
||||
catch (std::exception) {
|
||||
iter->second->GetTCPConnection()->Disconnect();
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
}));
|
||||
|
||||
_impl->methods.insert(std::make_pair("login", MethodHandlerEntry(std::bind(&WebsocketServer::Login, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||
_impl->methods.insert(std::make_pair("subscribe", MethodHandlerEntry(std::bind(&WebsocketServer::Subscribe, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||
_impl->methods.insert(std::make_pair("unsubscribe", MethodHandlerEntry(std::bind(&WebsocketServer::Unsubscribe, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||
_impl->login_handler = [](const WebsocketServerConnection* connection, const std::string& user, const std::string& pass) {
|
||||
WebsocketLoginStatus ret;
|
||||
ret.account_name = "admin";
|
||||
|
||||
if (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::") {
|
||||
ret.logged_in = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.logged_in = false;
|
||||
return ret;
|
||||
};
|
||||
|
||||
_impl->ws_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||
}
|
||||
|
||||
EQ::Net::WebsocketServer::~WebsocketServer()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::ReleaseConnection(WebsocketServerConnection *connection)
|
||||
{
|
||||
UnsubscribeAll(connection);
|
||||
|
||||
_impl->connections.erase(connection->GetWebsocketConnection());
|
||||
}
|
||||
|
||||
Json::Value EQ::Net::WebsocketServer::HandleRequest(WebsocketServerConnection *connection, const std::string &method, const Json::Value ¶ms)
|
||||
{
|
||||
Json::Value err;
|
||||
if (method != "login") {
|
||||
if (!connection->IsAuthorized()) {
|
||||
throw WebsocketException("Not logged in");
|
||||
}
|
||||
}
|
||||
|
||||
auto iter = _impl->methods.find(method);
|
||||
if (iter != _impl->methods.end()) {
|
||||
auto &s = iter->second;
|
||||
if (s.status > connection->GetStatus()) {
|
||||
throw WebsocketException("Status too low");
|
||||
}
|
||||
|
||||
return s.handler(connection, params);
|
||||
}
|
||||
|
||||
throw WebsocketException("Unknown Method");
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::SetMethodHandler(const std::string &method, MethodHandler handler, int required_status)
|
||||
{
|
||||
//Reserved method names
|
||||
if (method == "subscribe" ||
|
||||
method == "unsubscribe" ||
|
||||
method == "login") {
|
||||
return;
|
||||
}
|
||||
|
||||
_impl->methods[method] = MethodHandlerEntry(handler, required_status);
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::SetLoginHandler(LoginHandler handler)
|
||||
{
|
||||
_impl->login_handler = handler;
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::DispatchEvent(WebsocketSubscriptionEvent evt, Json::Value data, int required_status)
|
||||
{
|
||||
try {
|
||||
Json::Value event_obj;
|
||||
event_obj["type"] = "event";
|
||||
event_obj["event"] = (int)evt;
|
||||
event_obj["data"] = data;
|
||||
|
||||
std::stringstream payload;
|
||||
payload << event_obj;
|
||||
|
||||
for (auto &iter : _impl->connections) {
|
||||
auto &c = iter.second;
|
||||
|
||||
if (c->GetStatus() >= required_status && IsSubscribed(c.get(), evt)) {
|
||||
c->GetWebsocketConnection()->send(payload.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||
{
|
||||
Json::Value ret;
|
||||
|
||||
try {
|
||||
Json::Value ret;
|
||||
|
||||
auto user = params[0].asString();
|
||||
auto pass = params[1].asString();
|
||||
|
||||
auto r = _impl->login_handler(connection, user, pass);
|
||||
|
||||
if (r.logged_in) {
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) {
|
||||
r.logged_in = true;
|
||||
r.account_id = 0;
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else {
|
||||
connection->SetAuthorized(false, "", 0, 0);
|
||||
ret["status"] = "Not Authorized";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception) {
|
||||
throw WebsocketException("Unable to process login request");
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value EQ::Net::WebsocketServer::Subscribe(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||
{
|
||||
Json::Value ret;
|
||||
|
||||
try {
|
||||
auto evt = params[0].asInt();
|
||||
if (evt < 0 || evt >= SubscriptionEventMax) {
|
||||
throw WebsocketException("Not a valid subscription");
|
||||
}
|
||||
|
||||
DoSubscribe(connection, (WebsocketSubscriptionEvent)evt);
|
||||
ret["status"] = "Ok";
|
||||
return ret;
|
||||
}
|
||||
catch (WebsocketException &ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (std::exception) {
|
||||
throw WebsocketException("Unable to process unsubscribe request");
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value EQ::Net::WebsocketServer::Unsubscribe(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||
{
|
||||
Json::Value ret;
|
||||
|
||||
try {
|
||||
auto evt = params[0].asInt();
|
||||
if (evt < 0 || evt >= SubscriptionEventMax) {
|
||||
throw WebsocketException("Not a valid subscription");
|
||||
}
|
||||
|
||||
DoUnsubscribe(connection, (WebsocketSubscriptionEvent)evt);
|
||||
ret["status"] = "Ok";
|
||||
return ret;
|
||||
}
|
||||
catch (WebsocketException &ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (std::exception) {
|
||||
throw WebsocketException("Unable to process unsubscribe request");
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::DoSubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||
auto &s = _impl->subscriptions[sub];
|
||||
|
||||
auto iter = s.find(connection);
|
||||
if (iter == s.end()) {
|
||||
s.insert(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::DoUnsubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||
auto &s = _impl->subscriptions[sub];
|
||||
s.erase(connection);
|
||||
}
|
||||
|
||||
bool EQ::Net::WebsocketServer::IsSubscribed(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||
auto &s = _impl->subscriptions[sub];
|
||||
return s.count(connection) == 1;
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServer::UnsubscribeAll(WebsocketServerConnection *connection) {
|
||||
for (auto i = 0; i < SubscriptionEventMax; ++i) {
|
||||
DoUnsubscribe(connection, (WebsocketSubscriptionEvent)i);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "websocket_server_connection.h"
|
||||
|
||||
#include "../json/json.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
enum WebsocketSubscriptionEvent : int
|
||||
{
|
||||
SubscriptionEventNone,
|
||||
SubscriptionEventLog,
|
||||
SubscriptionEventMax
|
||||
};
|
||||
|
||||
struct WebsocketLoginStatus
|
||||
{
|
||||
bool logged_in;
|
||||
std::string account_name;
|
||||
uint32 account_id;
|
||||
int status;
|
||||
};
|
||||
|
||||
class WebsocketException : public std::exception
|
||||
{
|
||||
public:
|
||||
WebsocketException(const std::string &msg)
|
||||
: _msg(msg.empty() ? "Unknown Error" : msg) { }
|
||||
|
||||
~WebsocketException() throw() {}
|
||||
|
||||
virtual char const *what() const throw() {
|
||||
return _msg.c_str();
|
||||
}
|
||||
private:
|
||||
const std::string _msg;
|
||||
};
|
||||
|
||||
class WebsocketServer
|
||||
{
|
||||
public:
|
||||
typedef std::function<Json::Value(WebsocketServerConnection*, const Json::Value&)> MethodHandler;
|
||||
typedef std::function<WebsocketLoginStatus(WebsocketServerConnection*, const std::string&, const std::string&)> LoginHandler;
|
||||
|
||||
WebsocketServer(const std::string &addr, int port);
|
||||
~WebsocketServer();
|
||||
|
||||
void SetMethodHandler(const std::string& method, MethodHandler handler, int required_status);
|
||||
void SetLoginHandler(LoginHandler handler);
|
||||
void DispatchEvent(WebsocketSubscriptionEvent evt, Json::Value data = Json::Value(), int required_status = 0);
|
||||
private:
|
||||
void ReleaseConnection(WebsocketServerConnection *connection);
|
||||
Json::Value HandleRequest(WebsocketServerConnection *connection, const std::string& method, const Json::Value ¶ms);
|
||||
|
||||
Json::Value Login(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||
Json::Value Subscribe(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||
Json::Value Unsubscribe(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||
void DoSubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||
void DoUnsubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||
bool IsSubscribed(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||
void UnsubscribeAll(WebsocketServerConnection *connection);
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> _impl;
|
||||
|
||||
friend class WebsocketServerConnection;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
#include "websocket_server_connection.h"
|
||||
#include "websocket_server.h"
|
||||
#include "../timer.h"
|
||||
#include "../util/uuid.h"
|
||||
#include <sstream>
|
||||
#include <fmt/format.h>
|
||||
|
||||
struct EQ::Net::WebsocketServerConnection::Impl {
|
||||
WebsocketServer *parent;
|
||||
std::shared_ptr<TCPConnection> connection;
|
||||
std::shared_ptr<websocket_connection> ws_connection;
|
||||
std::string id;
|
||||
bool authorized;
|
||||
std::string account_name;
|
||||
uint32 account_id;
|
||||
int status;
|
||||
};
|
||||
|
||||
EQ::Net::WebsocketServerConnection::WebsocketServerConnection(WebsocketServer *parent,
|
||||
std::shared_ptr<TCPConnection> connection,
|
||||
std::shared_ptr<websocket_connection> ws_connection)
|
||||
{
|
||||
_impl.reset(new Impl());
|
||||
_impl->parent = parent;
|
||||
_impl->connection = connection;
|
||||
_impl->id = EQ::Util::UUID::Generate().ToString();
|
||||
_impl->authorized = false;
|
||||
_impl->account_id = 0;
|
||||
_impl->status = 0;
|
||||
_impl->ws_connection = ws_connection;
|
||||
_impl->ws_connection->set_message_handler(std::bind(&WebsocketServerConnection::OnMessage, this, std::placeholders::_1, std::placeholders::_2));
|
||||
_impl->ws_connection->start();
|
||||
|
||||
connection->OnDisconnect([this](EQ::Net::TCPConnection *connection) {
|
||||
_impl->parent->ReleaseConnection(this);
|
||||
});
|
||||
|
||||
connection->OnRead([this](EQ::Net::TCPConnection *c, const unsigned char *buffer, size_t buffer_size) {
|
||||
_impl->ws_connection->read_all((const char*)buffer, buffer_size);
|
||||
});
|
||||
|
||||
connection->Start();
|
||||
}
|
||||
|
||||
EQ::Net::WebsocketServerConnection::~WebsocketServerConnection()
|
||||
{
|
||||
}
|
||||
|
||||
std::string EQ::Net::WebsocketServerConnection::GetID() const
|
||||
{
|
||||
return _impl->id;
|
||||
}
|
||||
|
||||
bool EQ::Net::WebsocketServerConnection::IsAuthorized() const
|
||||
{
|
||||
return _impl->authorized;
|
||||
}
|
||||
|
||||
std::string EQ::Net::WebsocketServerConnection::GetAccountName() const
|
||||
{
|
||||
return _impl->account_name;
|
||||
}
|
||||
|
||||
uint32 EQ::Net::WebsocketServerConnection::GetAccountID() const
|
||||
{
|
||||
return _impl->account_id;
|
||||
}
|
||||
|
||||
int EQ::Net::WebsocketServerConnection::GetStatus() const
|
||||
{
|
||||
return _impl->status;
|
||||
}
|
||||
|
||||
std::string EQ::Net::WebsocketServerConnection::RemoteIP() const
|
||||
{
|
||||
return _impl->connection->RemoteIP();
|
||||
}
|
||||
|
||||
int EQ::Net::WebsocketServerConnection::RemotePort() const
|
||||
{
|
||||
return _impl->connection->RemotePort();
|
||||
}
|
||||
|
||||
std::shared_ptr<EQ::Net::websocket_connection> EQ::Net::WebsocketServerConnection::GetWebsocketConnection()
|
||||
{
|
||||
return _impl->ws_connection;
|
||||
}
|
||||
|
||||
std::shared_ptr<EQ::Net::TCPConnection> EQ::Net::WebsocketServerConnection::GetTCPConnection()
|
||||
{
|
||||
return _impl->connection;
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServerConnection::OnMessage(websocketpp::connection_hdl hdl, websocket_message_ptr msg)
|
||||
{
|
||||
BenchTimer timer;
|
||||
timer.reset();
|
||||
|
||||
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
|
||||
try {
|
||||
auto &payload = msg->get_payload();
|
||||
|
||||
std::stringstream ss(payload);
|
||||
Json::Value root;
|
||||
|
||||
ss >> root;
|
||||
|
||||
auto method = root["method"].asString();
|
||||
auto params = root["params"];
|
||||
std::string id = "";
|
||||
|
||||
auto idNode = root["id"];
|
||||
if (!idNode.isNull() && idNode.isString()) {
|
||||
id = idNode.asString();
|
||||
}
|
||||
|
||||
Json::Value response;
|
||||
response["type"] = "method";
|
||||
response["data"] = _impl->parent->HandleRequest(this, method, params);
|
||||
response["method"] = method;
|
||||
if(id != "") {
|
||||
response["id"] = id;
|
||||
}
|
||||
|
||||
SendResponse(response, timer.elapsed());
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
Json::Value error;
|
||||
error["type"] = "method";
|
||||
error["error"] = fmt::format("{0}", ex.what());
|
||||
SendResponse(error, timer.elapsed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServerConnection::SendResponse(const Json::Value &response, double time_elapsed)
|
||||
{
|
||||
Json::Value root = response;
|
||||
root["execution_time"] = std::to_string(time_elapsed);
|
||||
|
||||
std::stringstream payload;
|
||||
payload << root;
|
||||
|
||||
_impl->ws_connection->send(payload.str());
|
||||
}
|
||||
|
||||
void EQ::Net::WebsocketServerConnection::SetAuthorized(bool v, const std::string account_name, uint32 account_id, int status)
|
||||
{
|
||||
_impl->authorized = v;
|
||||
_impl->account_name = account_name;
|
||||
_impl->account_id = account_id;
|
||||
_impl->status = status;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "../types.h"
|
||||
#include "../json/json-forwards.h"
|
||||
#include <websocketpp/config/core.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
typedef websocketpp::server<websocketpp::config::core> websocket_server;
|
||||
typedef websocketpp::connection<websocketpp::config::core> websocket_connection;
|
||||
typedef websocket_server::message_ptr websocket_message_ptr;
|
||||
|
||||
class WebsocketServer;
|
||||
class WebsocketServerConnection
|
||||
{
|
||||
public:
|
||||
WebsocketServerConnection(WebsocketServer *parent,
|
||||
std::shared_ptr<TCPConnection> connection,
|
||||
std::shared_ptr<websocket_connection> ws_connection);
|
||||
~WebsocketServerConnection();
|
||||
|
||||
std::string GetID() const;
|
||||
bool IsAuthorized() const;
|
||||
std::string GetAccountName() const;
|
||||
uint32 GetAccountID() const;
|
||||
int GetStatus() const;
|
||||
std::string RemoteIP() const;
|
||||
int RemotePort() const;
|
||||
private:
|
||||
std::shared_ptr<websocket_connection> GetWebsocketConnection();
|
||||
std::shared_ptr<TCPConnection> GetTCPConnection();
|
||||
void OnMessage(websocketpp::connection_hdl hdl, websocket_message_ptr msg);
|
||||
void SendResponse(const Json::Value &response, double time_elapsed);
|
||||
void SetAuthorized(bool v, const std::string account_name, uint32 account_id, int status);
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> _impl;
|
||||
|
||||
friend class WebsocketServer;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "eqemu_logsys.h"
|
||||
#include "emu_opcodes.h"
|
||||
#include "opcodemgr.h"
|
||||
|
||||
@@ -32,7 +31,7 @@ OpcodeManager::OpcodeManager() {
|
||||
bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors) {
|
||||
FILE *opf = fopen(filename, "r");
|
||||
if(opf == nullptr) {
|
||||
Log(Logs::General, Logs::Error, "Unable to open opcodes file '%s'", filename);
|
||||
fprintf(stderr, "Unable to open opcodes file '%s'. Thats bad.\n", filename);
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
+33
-21
@@ -3199,35 +3199,47 @@ namespace RoF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToRoFSayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+33
-21
@@ -3266,35 +3266,47 @@ namespace RoF2
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToRoF2SayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+33
-21
@@ -2069,35 +2069,47 @@ namespace SoD
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToSoDSayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+33
-21
@@ -1720,35 +1720,47 @@ namespace SoF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name);
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToSoFSayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+33
-21
@@ -1420,35 +1420,47 @@ namespace Titanium
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToTitaniumSayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
|
||||
+33
-21
@@ -2369,35 +2369,47 @@ namespace UF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_message);
|
||||
|
||||
ServerToUFSayLink(new_message, old_message);
|
||||
|
||||
buf.WriteString(new_message);
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+5
-16
@@ -205,7 +205,6 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(GM)
|
||||
RULE_INT(GM, MinStatusToSummonItem, 250)
|
||||
RULE_INT(GM, MinStatusToZoneAnywhere, 250)
|
||||
RULE_INT(GM, MinStatusToLevelTarget, 100)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(World)
|
||||
@@ -226,6 +225,8 @@ RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be s
|
||||
RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP)
|
||||
RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots.
|
||||
RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks.
|
||||
RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled)
|
||||
RULE_INT(World, ExemptAccountLimitStatus, -1) //Min status required to be exempt from multi-session per account limiting (-1 is disabled)
|
||||
RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts.
|
||||
RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list
|
||||
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
|
||||
@@ -240,11 +241,10 @@ RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||
RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules.
|
||||
RULE_INT (World, TellQueueSize, 20)
|
||||
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind?
|
||||
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
RULE_INT(Zone, ClientLinkdeadMS, 90000) //the time a client remains link dead on the server after a sudden disconnection
|
||||
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
|
||||
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
|
||||
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
|
||||
RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses.
|
||||
@@ -683,10 +683,10 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(Network)
|
||||
RULE_INT(Network, ResendDelayBaseMS, 100)
|
||||
RULE_REAL(Network, ResendDelayFactor, 1.5)
|
||||
RULE_INT(Network, ResendDelayMinMS, 300)
|
||||
RULE_INT(Network, ResendDelayMinMS, 100)
|
||||
RULE_INT(Network, ResendDelayMaxMS, 5000)
|
||||
RULE_REAL(Network, ClientDataRate, 0.0) // KB / sec, 0.0 disabled
|
||||
RULE_BOOL(Network, CompressZoneStream, true)
|
||||
RULE_BOOL(Network, TrackOpcodeStats, false)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(QueryServ)
|
||||
@@ -735,17 +735,6 @@ RULE_BOOL(Bugs, UseOldReportingMethod, true) // Forces the use of the old bug re
|
||||
RULE_BOOL(Bugs, DumpTargetEntity, false) // Dumps the target entity, if one is provided
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Faction)
|
||||
RULE_INT(Faction, AllyFactionMinimum, 1100)
|
||||
RULE_INT(Faction, WarmlyFactionMinimum, 750)
|
||||
RULE_INT(Faction, KindlyFactionMinimum, 500)
|
||||
RULE_INT(Faction, AmiablyFactionMinimum, 100)
|
||||
RULE_INT(Faction, IndifferentlyFactionMinimum, 0)
|
||||
RULE_INT(Faction, ApprehensivelyFactionMinimum, -100)
|
||||
RULE_INT(Faction, DubiouslyFactionMinimum, -500)
|
||||
RULE_INT(Faction, ThreateninglyFactionMinimum, -750)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
#undef RULE_CATEGORY
|
||||
#undef RULE_INT
|
||||
#undef RULE_REAL
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
void WriteString(const char *str)
|
||||
{
|
||||
assert(str != nullptr);
|
||||
auto len = std::char_traits<char>::length(str) + 1;
|
||||
auto len = strlen(str) + 1;
|
||||
if (m_pos + len > m_capacity)
|
||||
Grow(m_capacity + len);
|
||||
memcpy(m_buffer + m_pos, str, len);
|
||||
|
||||
+94
-65
@@ -15,80 +15,109 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
// Serverinfo.cpp - Server information gathering functions, used in #serverinfo - Windows specific
|
||||
// I'm not sure quite how to get this exact information in *nix, hopefully someone can fill that in
|
||||
// -T7g
|
||||
// Implement preliminary support for *nix variants
|
||||
// misanthropicfiend
|
||||
|
||||
#include "serverinfo.h"
|
||||
#include <uv.h>
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
|
||||
size_t EQ::GetRSS()
|
||||
{
|
||||
size_t rss = 0;
|
||||
char Ver_name[100];
|
||||
DWORD Ver_build, Ver_min, Ver_maj, Ver_pid;
|
||||
|
||||
if (0 != uv_resident_set_memory(&rss)) {
|
||||
return 0;
|
||||
int GetOS() {
|
||||
|
||||
strcpy(Ver_name, "Unknown operating system");
|
||||
|
||||
OSVERSIONINFO Ver_os;
|
||||
Ver_os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
|
||||
if(!(GetVersionEx(&Ver_os))) return 1;
|
||||
|
||||
Ver_build = Ver_os.dwBuildNumber & 0xFFFF;
|
||||
Ver_min = Ver_os.dwMinorVersion;
|
||||
Ver_maj = Ver_os.dwMajorVersion;
|
||||
Ver_pid = Ver_os.dwPlatformId;
|
||||
|
||||
if ((Ver_pid == 1) && (Ver_maj == 4))
|
||||
{
|
||||
if ((Ver_min < 10) && (Ver_build == 950))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 95");
|
||||
}
|
||||
else if ((Ver_min < 10) &&
|
||||
((Ver_build > 950) && (Ver_build <= 1080)))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 95 SP1");
|
||||
}
|
||||
else if ((Ver_min < 10) && (Ver_build > 1080))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 95 OSR2");
|
||||
}
|
||||
else if ((Ver_min == 10) && (Ver_build == 1998))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 98");
|
||||
}
|
||||
else if ((Ver_min == 10) &&
|
||||
((Ver_build > 1998) && (Ver_build < 2183)))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 98, Service Pack 1");
|
||||
}
|
||||
else if ((Ver_min == 10) && (Ver_build >= 2183))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 98 Second Edition");
|
||||
}
|
||||
else if (Ver_min == 90)
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows ME");
|
||||
}
|
||||
}
|
||||
else if (Ver_pid == 2)
|
||||
{
|
||||
if ((Ver_maj == 3) && (Ver_min == 51))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows NT 3.51");
|
||||
}
|
||||
else if ((Ver_maj == 4) && (Ver_min == 0))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows NT 4");
|
||||
}
|
||||
else if ((Ver_maj == 5) && (Ver_min == 0))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 2000");
|
||||
}
|
||||
else if ((Ver_maj == 5) && (Ver_min == 1))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows XP");
|
||||
}
|
||||
else if ((Ver_maj == 5) && (Ver_min == 2))
|
||||
{
|
||||
strcpy(Ver_name, "Microsoft Windows 2003");
|
||||
}
|
||||
}
|
||||
|
||||
return rss;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double EQ::GetUptime()
|
||||
{
|
||||
double uptime = 0.0;
|
||||
#else
|
||||
|
||||
if (0 != uv_uptime(&uptime)) {
|
||||
return 0.0;
|
||||
#include <sys/utsname.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char* GetOS(char* os_string) {
|
||||
utsname info;
|
||||
|
||||
if(uname(&info)==0) {
|
||||
snprintf(os_string, 99, "%s %s %s %s %s", info.sysname, info.nodename, info.release, info.version, info.machine);
|
||||
} else {
|
||||
strncpy(os_string, "Error determining OS & version!", 25);
|
||||
}
|
||||
|
||||
return uptime;
|
||||
return os_string;
|
||||
|
||||
}
|
||||
|
||||
size_t EQ::GetPID()
|
||||
{
|
||||
return uv_os_getpid();
|
||||
}
|
||||
|
||||
std::vector<eq_cpu_info_t> EQ::GetCPUs()
|
||||
{
|
||||
std::vector<eq_cpu_info_t> ret;
|
||||
uv_cpu_info_t *cpu_info = nullptr;
|
||||
int count = 0;
|
||||
|
||||
if (0 != uv_cpu_info(&cpu_info, &count)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.reserve(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
eq_cpu_info_t r;
|
||||
auto &entry = cpu_info[i];
|
||||
|
||||
r.model = entry.model;
|
||||
r.speed = entry.speed / 1000.0;
|
||||
r.time_user = entry.cpu_times.user;
|
||||
r.time_sys = entry.cpu_times.sys;
|
||||
r.time_idle = entry.cpu_times.idle;
|
||||
r.time_nice = entry.cpu_times.nice;
|
||||
r.time_irq = entry.cpu_times.irq;
|
||||
|
||||
ret.push_back(r);
|
||||
}
|
||||
|
||||
uv_free_cpu_info(cpu_info, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
eq_utsname_t EQ::GetOS()
|
||||
{
|
||||
eq_utsname_t ret;
|
||||
uv_utsname_t name;
|
||||
|
||||
if (0 != uv_os_uname(&name)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.machine = name.machine;
|
||||
ret.release = name.release;
|
||||
ret.sysname = name.sysname;
|
||||
ret.version = name.version;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
+10
-28
@@ -15,33 +15,15 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef SERVERINFO_H
|
||||
#define SERVERINFO_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#ifdef _WINDOWS
|
||||
extern char Ver_name[36];
|
||||
extern DWORD Ver_build, Ver_min, Ver_maj, Ver_pid;
|
||||
int GetOS();
|
||||
#else
|
||||
char* GetOS(char* os_string);
|
||||
#endif
|
||||
|
||||
typedef struct eq_cpu_info_s {
|
||||
std::string model;
|
||||
double speed;
|
||||
uint64_t time_user;
|
||||
uint64_t time_nice;
|
||||
uint64_t time_sys;
|
||||
uint64_t time_idle;
|
||||
uint64_t time_irq;
|
||||
} eq_cpu_info_t;
|
||||
|
||||
typedef struct eq_utsname_s {
|
||||
std::string sysname;
|
||||
std::string release;
|
||||
std::string version;
|
||||
std::string machine;
|
||||
} eq_utsname_t;
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
size_t GetRSS();
|
||||
double GetUptime();
|
||||
size_t GetPID();
|
||||
std::vector<eq_cpu_info_t> GetCPUs();
|
||||
eq_utsname_t GetOS();
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-20
@@ -80,7 +80,6 @@
|
||||
#define ServerOP_GroupJoin 0x003e //for joining ooz folks
|
||||
#define ServerOP_UpdateSpawn 0x003f
|
||||
#define ServerOP_SpawnStatusChange 0x0040
|
||||
#define ServerOP_DropClient 0x0041 // DropClient
|
||||
#define ServerOP_ReloadTasks 0x0060
|
||||
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
||||
#define ServerOP_ReloadTitles 0x0062
|
||||
@@ -214,15 +213,6 @@ enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_
|
||||
|
||||
#define ServerOP_Speech 0x4513
|
||||
|
||||
enum {
|
||||
UserToWorldStatusWorldUnavail = 0,
|
||||
UserToWorldStatusSuccess = 1,
|
||||
UserToWorldStatusSuspended = -1,
|
||||
UserToWorldStatusBanned = -2,
|
||||
UserToWorldStatusWorldAtCapacity = -3,
|
||||
UserToWorldStatusAlreadyOnline = -4
|
||||
};
|
||||
|
||||
/************ PACKET RELATED STRUCT ************/
|
||||
class ServerPacket
|
||||
{
|
||||
@@ -318,17 +308,11 @@ struct ServerZoneIncomingClient_Struct {
|
||||
uint32 accid;
|
||||
int16 admin;
|
||||
uint32 charid;
|
||||
uint32 lsid;
|
||||
bool tellsoff;
|
||||
char charname[64];
|
||||
char lskey[30];
|
||||
};
|
||||
|
||||
struct ServerZoneDropClient_Struct
|
||||
{
|
||||
uint32 lsid;
|
||||
};
|
||||
|
||||
struct ServerChangeWID_Struct {
|
||||
uint32 charid;
|
||||
uint32 newwid;
|
||||
@@ -359,8 +343,7 @@ struct ServerChannelMessage_Struct {
|
||||
bool noreply;
|
||||
uint16 chan_num;
|
||||
uint32 guilddbid;
|
||||
uint8 language;
|
||||
uint8 lang_skill;
|
||||
uint16 language;
|
||||
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
||||
char message[0];
|
||||
};
|
||||
@@ -873,8 +856,6 @@ struct ServerRaidGroupAction_Struct { //add / remove depends on opcode.
|
||||
struct ServerRaidMessage_Struct {
|
||||
uint32 rid;
|
||||
uint32 gid;
|
||||
uint8 language;
|
||||
uint8 lang_skill;
|
||||
char from[64];
|
||||
char message[0];
|
||||
};
|
||||
|
||||
+1
-1
@@ -590,7 +590,7 @@ typedef enum {
|
||||
#define SE_CorruptionCounter 369 // implemented
|
||||
#define SE_ResistCorruption 370 // implemented
|
||||
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
|
||||
#define SE_ForageSkill 372 // implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
|
||||
#define SE_ApplyEffect 374 // implemented
|
||||
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
|
||||
|
||||
+2
-2
@@ -31,10 +31,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9141
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9138
|
||||
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9024
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9022
|
||||
#else
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||
#endif
|
||||
|
||||
@@ -136,7 +136,7 @@ int main(int argc, char *argv[]) {
|
||||
zones.erase(rem);
|
||||
}
|
||||
|
||||
EQ::EventLoop::Get().Process();
|
||||
EQ::EventLoop::GetDefault().Process();
|
||||
Sleep(5);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
* text=auto
|
||||
*.c text
|
||||
*.h text
|
||||
Makefile text
|
||||
@@ -1,76 +0,0 @@
|
||||
*.diff
|
||||
*.patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
*~
|
||||
*.a
|
||||
*.lo
|
||||
*.o
|
||||
*.dylib
|
||||
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
|
||||
/example
|
||||
/example64
|
||||
/examplesh
|
||||
/libz.so*
|
||||
/libz-ng.so*
|
||||
/minigzip
|
||||
/minigzip64
|
||||
/minigzipsh
|
||||
/zlib.pc
|
||||
/zlib-ng.pc
|
||||
/CVE-2003-0107
|
||||
|
||||
.DS_Store
|
||||
*_fuzzer
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.exp
|
||||
*.lib
|
||||
*.dll
|
||||
*.res
|
||||
foo.gz
|
||||
*.manifest
|
||||
*.opensdf
|
||||
*.sln
|
||||
*.sdf
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
.vs
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Testing
|
||||
*.cmake
|
||||
*.stackdump
|
||||
zconf.h
|
||||
zconf.h.cmakein
|
||||
zconf.h.included
|
||||
zconf-ng.h
|
||||
zconf-ng.h.cmakein
|
||||
ztest*
|
||||
|
||||
configure.log
|
||||
a.out
|
||||
|
||||
/Makefile
|
||||
/arch/arm/Makefile
|
||||
/arch/generic/Makefile
|
||||
/arch/x86/Makefile
|
||||
.kdev4
|
||||
*.kdev4
|
||||
|
||||
/Debug
|
||||
/example.dir
|
||||
/minigzip.dir
|
||||
/zlib.dir
|
||||
/zlibstatic.dir
|
||||
/win32/Debug
|
||||
|
||||
/.idea
|
||||
/cmake-build-debug
|
||||
@@ -1,283 +0,0 @@
|
||||
language: c
|
||||
cache: ccache
|
||||
dist: xenial
|
||||
|
||||
env:
|
||||
global:
|
||||
- BUILDDIR=.
|
||||
- MAKER="make -j2"
|
||||
- TESTER="make test"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: windows
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake . "
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: windows
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ..\\zlib-ng -DZLIB_COMPAT=ON"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- BUILDDIR=..\\build
|
||||
- os: windows
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ."
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake . -DZLIB_COMPAT=OFF -DWITH_GZFILEOP=ON -DWITH_NEW_STRATEGIES=YES -DWITH_OPTIM=ON"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||
- BUILDDIR=../build
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn --zlib-compat --without-optimizations --without-new-strategies"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="scan-build -v --status-bugs cmake ../zlib-ng"
|
||||
- MAKER="scan-build -v --status-bugs make"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||
- BUILDDIR=../build
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
# compiling for linux-ppc64le variants
|
||||
- os: linux-ppc64le
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
- os: linux-ppc64le
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: linux-ppc64le
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: linux-ppc64le
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
# Cross compiling for arm variants
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=aarch64-linux-gnu
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake . -DZLIB_COMPAT=ON"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=aarch64-linux-gnu
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake ."
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
# Hard-float subsets
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat --without-neon"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DWITH_NEON=OFF -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
# Soft-float subset
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="./configure"
|
||||
- CHOST=arm-linux-gnueabi
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="./configure --zlib-compat"
|
||||
- CHOST=arm-linux-gnueabi
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
|
||||
script:
|
||||
- mkdir -p $BUILDDIR
|
||||
- cd $BUILDDIR
|
||||
- $GENERATOR
|
||||
- $MAKER
|
||||
- $TESTER
|
||||
@@ -1,865 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
cmake_policy(VERSION ${CMAKE_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.5.1...3.13.2)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
|
||||
# If not specified on the command line, enable C99 as the default
|
||||
# Configuration items that affect the global compiler envirionment standards
|
||||
# should be issued before the "project" command.
|
||||
if(NOT CMAKE_C_STANDARD)
|
||||
set (CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target
|
||||
endif()
|
||||
if(NOT CMAKE_C_STANDARD_REQUIRED)
|
||||
set (CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement
|
||||
endif()
|
||||
if(NOT CMAKE_C_EXTENSIONS)
|
||||
set (CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested
|
||||
endif()
|
||||
set(VALID_C_STANDARDS "99" "11")
|
||||
if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS )
|
||||
MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}")
|
||||
endif()
|
||||
|
||||
# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*"
|
||||
"\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents})
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||
"\\1" ZLIBNG_HEADER_VERSION ${_zlib_h_contents})
|
||||
message(STATUS "ZLIB_HEADER_VERSION: ${ZLIB_HEADER_VERSION}")
|
||||
message(STATUS "ZLIBNG_HEADER_VERSION: ${ZLIBNG_HEADER_VERSION}")
|
||||
|
||||
project(zlib
|
||||
VERSION ${ZLIB_HEADER_VERSION}
|
||||
LANGUAGES C)
|
||||
|
||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
|
||||
include(CheckTypeSize)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
include(CMakeDependentOption)
|
||||
include(FeatureSummary)
|
||||
|
||||
# Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact
|
||||
# this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang)
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||
"Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)")
|
||||
else()
|
||||
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)")
|
||||
endif()
|
||||
|
||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file(stdint.h HAVE_STDINT_H)
|
||||
check_include_file(stddef.h HAVE_STDDEF_H)
|
||||
check_include_file(sys/sdt.h HAVE_SYS_SDT_H)
|
||||
|
||||
if(CMAKE_OSX_ARCHITECTURES)
|
||||
# If multiple architectures are requested (universal build), pick only the first
|
||||
list(GET CMAKE_OSX_ARCHITECTURES 0 ARCH)
|
||||
else()
|
||||
set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
message(STATUS "Architecture: ${ARCH}")
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS "Using cmake toolchain: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Options parsing
|
||||
#
|
||||
option(WITH_GZFILEOP "Compile with support for gzFile related functions" OFF)
|
||||
option(ZLIB_COMPAT "Compile with zlib compatible API" OFF)
|
||||
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||
option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
|
||||
option(WITH_MSAN "Build with memory sanitizer" OFF)
|
||||
option(WITH_FUZZERS "Build test/fuzz" OFF)
|
||||
option(WITH_OPTIM "Build with optimisation" ON)
|
||||
option(WITH_NEW_STRATEGIES "Use new strategies" ON)
|
||||
option(WITH_NATIVE_INSTRUCTIONS
|
||||
"Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF)
|
||||
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
option(WITH_ACLE "Build with ACLE CRC" ON)
|
||||
option(WITH_NEON "Build with NEON intrinsics" ON)
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
option(WITH_DFLTCC_DEFLATE "Use DEFLATE CONVERSION CALL instruction for compression on IBM Z" OFF)
|
||||
option(WITH_DFLTCC_INFLATE "Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z" OFF)
|
||||
endif()
|
||||
|
||||
add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Provide a zlib-compatible API")
|
||||
add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile-related functions")
|
||||
add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
|
||||
add_feature_info(WITH_SANITIZERS WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer")
|
||||
add_feature_info(WITH_MSAN WITH_MSAN "Build with memory sanitizer")
|
||||
add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
|
||||
add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
|
||||
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE CRC")
|
||||
add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics")
|
||||
endif()
|
||||
|
||||
if (ZLIB_COMPAT)
|
||||
add_definitions(-DZLIB_COMPAT)
|
||||
set(WITH_GZFILEOP ON)
|
||||
set(LIBNAME1 libz)
|
||||
set(LIBNAME2 zlib)
|
||||
set(SUFFIX "")
|
||||
else()
|
||||
set(LIBNAME1 libz-ng)
|
||||
set(LIBNAME2 zlib-ng)
|
||||
set(SUFFIX "-ng")
|
||||
endif()
|
||||
|
||||
if(WITH_GZFILEOP)
|
||||
add_definitions(-DWITH_GZFILEOP)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_C_COMPILER} MATCHES "icc" OR ${CMAKE_C_COMPILER} MATCHES "icpc" OR ${CMAKE_C_COMPILER} MATCHES "icl")
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
||||
endif()
|
||||
if(CMAKE_HOST_UNIX)
|
||||
if(NOT SSE2FLAG)
|
||||
set(SSE2FLAG "-msse2")
|
||||
endif()
|
||||
if(NOT SSE4FLAG)
|
||||
set(SSE4FLAG "-msse4.2")
|
||||
endif()
|
||||
else()
|
||||
if(NOT SSE2FLAG)
|
||||
set(SSE2FLAG "/arch:SSE2")
|
||||
endif()
|
||||
if(NOT SSE4FLAG)
|
||||
set(SSE4FLAG "/arch:SSE4.2")
|
||||
endif()
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
# TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination
|
||||
# (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should
|
||||
# avoid mistakes.
|
||||
# /Oi ?
|
||||
if(NOT ${ARCH} MATCHES "AMD64")
|
||||
set(SSE2FLAG "/arch:SSE2")
|
||||
endif()
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
add_definitions("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1")
|
||||
set(NEONFLAG "/arch:VFPv4")
|
||||
endif()
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
||||
endif()
|
||||
else()
|
||||
# catch all GNU C compilers as well as Clang and AppleClang
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(__GNUC__ ON)
|
||||
endif()
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
if(__GNUC__)
|
||||
set(NATIVEFLAG "-march=native")
|
||||
else()
|
||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration")
|
||||
endif()
|
||||
endif()
|
||||
if(__GNUC__ AND "${ARCH}" MATCHES "arm")
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} "-dumpmachine"
|
||||
OUTPUT_VARIABLE GCC_MACHINE)
|
||||
if ("${GCC_MACHINE}" MATCHES "eabihf")
|
||||
set(FLOATABI "-mfloat-abi=hard")
|
||||
else()
|
||||
set(FLOATABI "-mfloat-abi=softfp")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT NATIVEFLAG)
|
||||
if(NOT SSE2FLAG)
|
||||
if(__GNUC__)
|
||||
set(SSE2FLAG "-msse2")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT SSE4FLAG)
|
||||
if(__GNUC__)
|
||||
set(SSE4FLAG "-msse4")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT PCLMULFLAG)
|
||||
if(__GNUC__)
|
||||
set(PCLMULFLAG "-mpclmul")
|
||||
endif()
|
||||
endif()
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
set(ACLEFLAG "-march=armv8-a+crc")
|
||||
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
set(ACLEFLAG "-march=armv8-a+crc")
|
||||
set(NEONFLAG "-march=armv8-a+crc+simd")
|
||||
endif()
|
||||
else()
|
||||
set(SSE2FLAG ${NATIVEFLAG})
|
||||
set(SSE4FLAG ${NATIVEFLAG})
|
||||
set(PCLMULFLAG ${NATIVEFLAG})
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
set(ACLEFLAG "${NATIVEFLAG}")
|
||||
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
set(ACLEFLAG "${NATIVEFLAG}")
|
||||
set(NEONFLAG "${NATIVEFLAG}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check to see if we have large file support
|
||||
#
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||
# We add these other definitions here because CheckTypeSize.cmake
|
||||
# in CMake 2.4.x does not automatically do so and we want
|
||||
# compatibility with CMake 2.4.x.
|
||||
if(HAVE_SYS_TYPES_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
|
||||
endif()
|
||||
if(HAVE_STDINT_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
|
||||
endif()
|
||||
if(HAVE_STDDEF_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
||||
endif()
|
||||
check_type_size(off64_t OFF64_T)
|
||||
if(HAVE_OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||
else()
|
||||
check_type_size(_off64_t _OFF64_T)
|
||||
if(HAVE__OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||
else()
|
||||
check_type_size(__off64_t __OFF64_T)
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
|
||||
|
||||
#
|
||||
# Check for fseeko and other optional functions
|
||||
#
|
||||
check_function_exists(fseeko HAVE_FSEEKO)
|
||||
if(NOT HAVE_FSEEKO)
|
||||
add_definitions(-DNO_FSEEKO)
|
||||
endif()
|
||||
check_function_exists(strerror HAVE_STRERROR)
|
||||
if(NOT HAVE_STRERROR)
|
||||
add_definitions(-DNO_STRERROR)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check for unistd.h and stdarg.h
|
||||
#
|
||||
check_include_file(unistd.h Z_HAVE_UNISTD_H)
|
||||
|
||||
if(WITH_SANITIZERS AND WITH_MSAN)
|
||||
message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
|
||||
endif()
|
||||
|
||||
if(WITH_MSAN)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
|
||||
check_c_source_compiles("int main() { return 0; }" HAS_MSAN FAIL_REGEX "not supported")
|
||||
if(${HAS_MSAN})
|
||||
set(SANITIZERS_FLAGS "-fsanitize=memory")
|
||||
message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_SANITIZERS)
|
||||
set(_sanitize_flags
|
||||
bool
|
||||
address
|
||||
array-bounds
|
||||
float-divide-by-zero
|
||||
function
|
||||
integer-divide-by-zero
|
||||
return
|
||||
shift
|
||||
signed-integer-overflow
|
||||
undefined
|
||||
unsigned-integer-overflow
|
||||
vla-bound
|
||||
vptr
|
||||
)
|
||||
set(SANITIZERS_FLAGS "")
|
||||
foreach(_flag ${_sanitize_flags})
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=${_flag}")
|
||||
check_c_source_compiles("int main() { return 0; }"
|
||||
HAS_SANITIZER_${_flag} FAIL_REGEX "not supported")
|
||||
if(${HAS_SANITIZER_${_flag}})
|
||||
if("${SANITIZERS_FLAGS}" STREQUAL "")
|
||||
set(SANITIZERS_FLAGS "-fsanitize=${_flag}")
|
||||
else()
|
||||
set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
endforeach()
|
||||
message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check if we can hide zlib internal symbols that are linked between separate source files using hidden
|
||||
#
|
||||
check_c_source_compiles(
|
||||
"#define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))
|
||||
int ZLIB_INTERNAL foo;
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}"
|
||||
HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported")
|
||||
if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN)
|
||||
add_definitions(-DHAVE_HIDDEN)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check if we can hide zlib internal symbols that are linked between separate source files using internal
|
||||
#
|
||||
check_c_source_compiles(
|
||||
"#define ZLIB_INTERNAL __attribute__((visibility (\"internal\")))
|
||||
int ZLIB_INTERNAL foo;
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}"
|
||||
HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported")
|
||||
if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL)
|
||||
add_definitions(-DHAVE_INTERNAL)
|
||||
endif()
|
||||
|
||||
#
|
||||
# check for __builtin_ctzl() support in the compiler
|
||||
#
|
||||
check_c_source_compiles(
|
||||
"int main(void)
|
||||
{
|
||||
unsigned int zero = 0;
|
||||
long test = __builtin_ctzl(zero);
|
||||
(void)test;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_BUILTIN_CTZL
|
||||
)
|
||||
if(HAVE_BUILTIN_CTZL)
|
||||
add_definitions(-DHAVE_BUILTIN_CTZL)
|
||||
endif()
|
||||
|
||||
#
|
||||
# check for ptrdiff_t support
|
||||
#
|
||||
check_c_source_compiles(
|
||||
"#include <stddef.h>
|
||||
int main() { ptrdiff_t *a; return 0; }"
|
||||
HAVE_PTRDIFF_T
|
||||
)
|
||||
if(NOT HAVE_PTRDIFF_T)
|
||||
set(NEED_PTRDIFF_T 1)
|
||||
|
||||
check_type_size("void *" SIZEOF_DATA_PTR)
|
||||
message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes")
|
||||
|
||||
if(${SIZEOF_DATA_PTR} MATCHES "4")
|
||||
set(PTRDIFF_TYPE "uint32_t")
|
||||
elseif(${SIZEOF_DATA_PTR} MATCHES "8")
|
||||
set(PTRDIFF_TYPE "uint64_t")
|
||||
else()
|
||||
message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Macro to check if source compiles when cross-compiling
|
||||
# or runs when compiling natively
|
||||
macro(check_c_source_compile_or_run source flag)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
check_c_source_compiles("${source}" ${flag})
|
||||
else()
|
||||
check_c_source_runs("${source}" ${flag})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG")
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
else()
|
||||
#
|
||||
# Not MSVC, so we need to check if we have the MS-style SSE etc. intrinsics
|
||||
#
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||
else()
|
||||
set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}")
|
||||
endif()
|
||||
check_c_source_compile_or_run(
|
||||
"#include <immintrin.h>
|
||||
int main(void)
|
||||
{
|
||||
__m128i zero = _mm_setzero_si128();
|
||||
(void)zero;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_SSE2_INTRIN
|
||||
)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||
else()
|
||||
# Use the generic SSE4 enabler option to check for the SSE4.2 instruction we require:
|
||||
set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}")
|
||||
endif()
|
||||
check_c_source_compile_or_run(
|
||||
"int main(void)
|
||||
{
|
||||
unsigned val = 0, h = 0;
|
||||
__asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) );
|
||||
return (int) h;
|
||||
}"
|
||||
HAVE_SSE42_INTRIN
|
||||
)
|
||||
check_c_source_compile_or_run(
|
||||
"int main(void)
|
||||
{
|
||||
unsigned crc = 0;
|
||||
char c = 'c';
|
||||
crc = __builtin_ia32_crc32qi(crc, c);
|
||||
(void)crc;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_SSE42CRC_INTRIN
|
||||
)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||
else()
|
||||
set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}")
|
||||
endif()
|
||||
if(NOT (APPLE AND ${ARCH} MATCHES "i386"))
|
||||
# The pclmul code currently crashes on Mac in 32bit mode. Avoid for now.
|
||||
check_c_source_compile_or_run(
|
||||
"#include <immintrin.h>
|
||||
#include <wmmintrin.h>
|
||||
int main(void)
|
||||
{
|
||||
__m128i a = _mm_setzero_si128();
|
||||
__m128i b = _mm_setzero_si128();
|
||||
__m128i c = _mm_clmulepi64_si128(a, b, 0x10);
|
||||
(void)c;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_PCLMULQDQ_INTRIN
|
||||
)
|
||||
else()
|
||||
set(HAVE_PCLMULQDQ_INTRIN NO)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
endif()
|
||||
|
||||
# Check whether -mfpu=neon is available
|
||||
set(CMAKE_REQUIRED_FLAGS "-mfpu=neon")
|
||||
check_c_source_compiles(
|
||||
"int main()
|
||||
{
|
||||
return 0;
|
||||
}"
|
||||
MFPU_NEON_AVAILABLE FAIL_REGEX "not supported")
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
# FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true
|
||||
if("${ARCH}" MATCHES "i[3-6]86")
|
||||
cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Enable deflate_medium at level 4-6
|
||||
#
|
||||
if(NOT WITH_NEW_STRATEGIES)
|
||||
add_definitions(-DNO_MEDIUM_STRATEGY)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Macro to add either the given intrinsics option to the global compiler options,
|
||||
# or ${NATIVEFLAG} (-march=native) if that is appropriate and possible.
|
||||
# An alternative version of this macro would take a file argument, and set ${flag}
|
||||
# only for that file as opposed to ${NATIVEFLAG} globally, to limit side-effect of
|
||||
# using ${flag} globally.
|
||||
#
|
||||
macro(add_intrinsics_option flag)
|
||||
if(WITH_NATIVE_INSTRUCTIONS AND NATIVEFLAG)
|
||||
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${NATIVEFLAG} .*")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}")
|
||||
endif()
|
||||
else()
|
||||
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${flag} .*")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(ZLIB_ARCH_SRCS)
|
||||
set(ARCHDIR "arch/generic")
|
||||
if("${ARCH}" MATCHES "x86_64" OR "${ARCH}" MATCHES "AMD64" OR "${ARCH}" MATCHES "i[3-6]86")
|
||||
set(ARCHDIR "arch/x86")
|
||||
add_definitions(-DUNALIGNED_OK)
|
||||
add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"")
|
||||
elseif("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
set(ARCHDIR "arch/arm")
|
||||
add_definitions(-DUNALIGNED_OK)
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
set(ARCHDIR "arch/s390")
|
||||
else()
|
||||
message(STATUS "No optimized architecture: using ${ARCHDIR}")
|
||||
endif()
|
||||
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/armfeature.c ${ARCHDIR}/fill_window_arm.c)
|
||||
endif()
|
||||
if(WITH_OPTIM)
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
if(WITH_ACLE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||
endif()
|
||||
if(WITH_NEON)
|
||||
if(MFPU_NEON_AVAILABLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||
endif()
|
||||
add_definitions("-DARM_NEON_ADLER32")
|
||||
if(MSVC)
|
||||
add_definitions("-D__ARM_NEON__=1")
|
||||
endif(MSVC)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||
endif()
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
if(WITH_ACLE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||
endif()
|
||||
# We need to check WITH_NEON first
|
||||
if(WITH_NEON)
|
||||
add_definitions("-DARM_NEON_ADLER32")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||
elseif(WITH_ACLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||
endif()
|
||||
elseif("${ARCHDIR}" MATCHES "arch/x86")
|
||||
add_definitions("-DX86_CPUID")
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/x86.c)
|
||||
if(HAVE_SSE42_INTRIN)
|
||||
add_definitions(-DX86_SSE4_2_CRC_HASH)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/insert_string_sse.c)
|
||||
add_feature_info(SSE4_CRC 1 "Support CRC hash generation using the SSE4.2 instruction set, using \"${SSE4FLAG}\"")
|
||||
add_intrinsics_option("${SSE4FLAG}")
|
||||
if(HAVE_SSE42CRC_INTRIN)
|
||||
add_definitions(-DX86_SSE4_2_CRC_INTRIN)
|
||||
endif()
|
||||
if(WITH_NEW_STRATEGIES)
|
||||
add_definitions(-DX86_QUICK_STRATEGY)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/deflate_quick.c)
|
||||
add_feature_info(SSE4DEFLATE 1 "Support SSE4.2-accelerated quick compression")
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_SSE2_INTRIN)
|
||||
add_definitions(-DX86_SSE2)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/fill_window_sse.c)
|
||||
if(NOT ${ARCH} MATCHES "x86_64")
|
||||
add_intrinsics_option("${SSE2FLAG}")
|
||||
add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable")
|
||||
if(FORCE_SSE2)
|
||||
add_definitions(-DX86_NOCHECK_SSE2)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_PCLMULQDQ_INTRIN)
|
||||
add_definitions(-DX86_PCLMULQDQ_CRC)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc_folding.c)
|
||||
add_intrinsics_option("${PCLMULFLAG}")
|
||||
if(HAVE_SSE42_INTRIN)
|
||||
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG}\"")
|
||||
else()
|
||||
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG} ${SSE4FLAG}\"")
|
||||
endif()
|
||||
endif()
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_common.c)
|
||||
endif()
|
||||
if(WITH_DFLTCC_DEFLATE)
|
||||
add_definitions(-DS390_DFLTCC_DEFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_deflate.c)
|
||||
endif()
|
||||
if(WITH_DFLTCC_INFLATE)
|
||||
add_definitions(-DS390_DFLTCC_INFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_inflate.c)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}")
|
||||
|
||||
#============================================================================
|
||||
# zconf.h
|
||||
#============================================================================
|
||||
|
||||
macro(generate_cmakein input output)
|
||||
file(REMOVE ${output})
|
||||
file(STRINGS ${input} _lines)
|
||||
foreach(_line IN LISTS _lines)
|
||||
file(APPEND ${output} "${_line}\n")
|
||||
|
||||
if (_line STREQUAL "#define ZCONF_H" OR _line STREQUAL "#define ZCONFNG_H")
|
||||
file(APPEND ${output} "#cmakedefine Z_HAVE_UNISTD_H\n")
|
||||
if(NOT HAVE_PTRDIFF_T)
|
||||
file(APPEND ${output} "#cmakedefine NEED_PTRDIFF_T\n")
|
||||
file(APPEND ${output} "#cmakedefine PTRDIFF_TYPE ${PTRDIFF_TYPE}\n")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro(generate_cmakein)
|
||||
|
||||
generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein )
|
||||
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
# If we're doing an out of source build and the user has a zconf.h
|
||||
# in their source tree...
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h")
|
||||
message(STATUS "to 'zconf${SUFFIX}.h.included' because this file is included with zlib")
|
||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.included)
|
||||
endif()
|
||||
|
||||
# If we're doing an out of source build and the user has a zconf.h.cmakein
|
||||
# in their source tree...
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein")
|
||||
message(STATUS "to 'zconf${SUFFIX}.h.cmakeincluded' because this file is included with zlib")
|
||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakeincluded)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME2}.pc)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||
${ZLIB_PC} @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY)
|
||||
|
||||
|
||||
#============================================================================
|
||||
# zlib
|
||||
#============================================================================
|
||||
|
||||
set(ZLIB_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h
|
||||
zlib${SUFFIX}.h
|
||||
)
|
||||
set(ZLIB_PRIVATE_HDRS
|
||||
crc32.h
|
||||
deflate.h
|
||||
functable.h
|
||||
gzguts.h
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.h
|
||||
inftrees.h
|
||||
trees.h
|
||||
zutil.h
|
||||
)
|
||||
set(ZLIB_SRCS
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
deflate.c
|
||||
deflate_fast.c
|
||||
deflate_medium.c
|
||||
deflate_slow.c
|
||||
functable.c
|
||||
inflate.c
|
||||
infback.c
|
||||
inftrees.c
|
||||
inffast.c
|
||||
trees.c
|
||||
uncompr.c
|
||||
zutil.c
|
||||
)
|
||||
|
||||
set(ZLIB_GZFILE_SRCS
|
||||
gzclose.c
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
)
|
||||
|
||||
if(NOT MINGW AND NOT MSYS)
|
||||
set(ZLIB_DLL_SRCS
|
||||
win32/zlib${SUFFIX}1.rc # If present will override custom build rule below.
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MINGW OR MSYS)
|
||||
# This gets us DLL resource information when compiling on MinGW.
|
||||
if(NOT CMAKE_RC_COMPILER)
|
||||
set(CMAKE_RC_COMPILER windres.exe)
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
COMMAND ${CMAKE_RC_COMPILER}
|
||||
-D GCC_WINDRES
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc)
|
||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||
endif()
|
||||
|
||||
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(WITH_GZFILEOP)
|
||||
target_sources(zlib PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
target_sources(zlibstatic PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
endif()
|
||||
|
||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
|
||||
if (ZLIB_COMPAT)
|
||||
set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION})
|
||||
else()
|
||||
set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION})
|
||||
endif()
|
||||
if(NOT CYGWIN)
|
||||
# This property causes shared libraries on Linux to have the full version
|
||||
# encoded into their final filename. We disable this on Cygwin because
|
||||
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
||||
# seems to be the default.
|
||||
#
|
||||
# This has no effect with MSVC, on that platform the version info for
|
||||
# the DLL comes from the resource file win32/zlib1.rc
|
||||
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||
endif()
|
||||
|
||||
|
||||
if(UNIX)
|
||||
# On unix-like platforms the library is almost always called libz
|
||||
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z${SUFFIX})
|
||||
if(NOT APPLE)
|
||||
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME2}.map\"")
|
||||
endif()
|
||||
elseif(MSYS)
|
||||
# Suppress version number from shared library name
|
||||
set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0)
|
||||
elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||
# Creates zlib1.dll when building shared library version
|
||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
||||
install(TARGETS zlib zlibstatic
|
||||
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
||||
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES zlib${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zlib${SUFFIX}.h)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zconf${SUFFIX}.h)
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3" RENAME zlib${SUFFIX}.3)
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
||||
|
||||
#============================================================================
|
||||
# Example binaries
|
||||
#============================================================================
|
||||
|
||||
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||
if (ZLIB_ENABLE_TESTS)
|
||||
enable_testing()
|
||||
macro(configure_test_executable target)
|
||||
target_link_libraries(${target} zlib)
|
||||
if(NOT WITH_GZFILEOP)
|
||||
target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP)
|
||||
target_sources(${target} PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
add_executable(example test/example.c)
|
||||
configure_test_executable(example)
|
||||
add_test(NAME example COMMAND example${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
add_executable(minigzip test/minigzip.c)
|
||||
configure_test_executable(minigzip)
|
||||
|
||||
if(HAVE_OFF64_T)
|
||||
add_executable(example64 test/example.c)
|
||||
configure_test_executable(example64)
|
||||
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
add_test(NAME example64 COMMAND example64${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
add_executable(minigzip64 test/minigzip.c)
|
||||
configure_test_executable(minigzip64)
|
||||
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
endif()
|
||||
|
||||
if(WITH_FUZZERS)
|
||||
set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip)
|
||||
file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||
foreach(FUZZER ${FUZZERS})
|
||||
add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
|
||||
configure_test_executable(${FUZZER}_fuzzer)
|
||||
add_test(${FUZZER}_fuzzer ${FUZZER}_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096)
|
||||
foreach(CVE ${CVES})
|
||||
set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:minigzip> -d)
|
||||
add_test(NAME ${CVE}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-DCOMMAND=${CVE_COMMAND}"
|
||||
-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz
|
||||
"-DSUCCESS_EXIT=0;1"
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake)
|
||||
endforeach()
|
||||
|
||||
if(NOT WIN32 AND ZLIB_COMPAT)
|
||||
add_executable(CVE-2003-0107 test/CVE-2003-0107.c)
|
||||
target_link_libraries(CVE-2003-0107 zlib)
|
||||
add_test(NAME CVE-2003-0107 COMMAND CVE-2003-0107)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,374 +0,0 @@
|
||||
##
|
||||
# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.11
|
||||
##
|
||||
|
||||
|
||||
|
||||
|
||||
Frequently Asked Questions about zlib
|
||||
|
||||
|
||||
If your question is not there, please check the zlib home page
|
||||
http://zlib.net/ which may have more recent information.
|
||||
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
|
||||
|
||||
|
||||
1. Is zlib Y2K-compliant?
|
||||
|
||||
Yes. zlib doesn't handle dates.
|
||||
|
||||
2. Where can I get a Windows DLL version?
|
||||
|
||||
The zlib sources can be compiled without change to produce a DLL. See the
|
||||
file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
|
||||
precompiled DLL are found in the zlib web site at http://zlib.net/ .
|
||||
|
||||
3. Where can I get a Visual Basic interface to zlib?
|
||||
|
||||
See
|
||||
* http://marknelson.us/1997/01/01/zlib-engine/
|
||||
* win32/DLL_FAQ.txt in the zlib distribution
|
||||
|
||||
4. compress() returns Z_BUF_ERROR.
|
||||
|
||||
Make sure that before the call of compress(), the length of the compressed
|
||||
buffer is equal to the available size of the compressed buffer and not
|
||||
zero. For Visual Basic, check that this parameter is passed by reference
|
||||
("as any"), not by value ("as long").
|
||||
|
||||
5. deflate() or inflate() returns Z_BUF_ERROR.
|
||||
|
||||
Before making the call, make sure that avail_in and avail_out are not zero.
|
||||
When setting the parameter flush equal to Z_FINISH, also make sure that
|
||||
avail_out is big enough to allow processing all pending input. Note that a
|
||||
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
|
||||
made with more input or output space. A Z_BUF_ERROR may in fact be
|
||||
unavoidable depending on how the functions are used, since it is not
|
||||
possible to tell whether or not there is more output pending when
|
||||
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
|
||||
heavily annotated example.
|
||||
|
||||
6. Where's the zlib documentation (man pages, etc.)?
|
||||
|
||||
It's in zlib.h . Examples of zlib usage are in the files test/example.c
|
||||
and test/minigzip.c, with more in examples/ .
|
||||
|
||||
7. Why don't you use GNU autoconf or libtool or ...?
|
||||
|
||||
Because we would like to keep zlib as a very small and simple package.
|
||||
zlib is rather portable and doesn't need much configuration.
|
||||
|
||||
8. I found a bug in zlib.
|
||||
|
||||
Most of the time, such problems are due to an incorrect usage of zlib.
|
||||
Please try to reproduce the problem with a small program and send the
|
||||
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
|
||||
data files without prior agreement.
|
||||
|
||||
9. Why do I get "undefined reference to gzputc"?
|
||||
|
||||
If "make test" produces something like
|
||||
|
||||
example.o(.text+0x154): undefined reference to `gzputc'
|
||||
|
||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||
|
||||
10. I need a Delphi interface to zlib.
|
||||
|
||||
See the contrib/delphi directory in the zlib distribution.
|
||||
|
||||
11. Can zlib handle .zip archives?
|
||||
|
||||
Not by itself, no. See the directory contrib/minizip in the zlib
|
||||
distribution.
|
||||
|
||||
12. Can zlib handle .Z files?
|
||||
|
||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||
the code of uncompress on your own.
|
||||
|
||||
13. How can I make a Unix shared library?
|
||||
|
||||
By default a shared (and a static) library is built for Unix. So:
|
||||
|
||||
make distclean
|
||||
./configure
|
||||
make
|
||||
|
||||
14. How do I install a shared zlib library on Unix?
|
||||
|
||||
After the above, then:
|
||||
|
||||
make install
|
||||
|
||||
However, many flavors of Unix come with a shared zlib already installed.
|
||||
Before going to the trouble of compiling a shared version of zlib and
|
||||
trying to install it, you may want to check if it's already there! If you
|
||||
can #include <zlib.h>, it's there. The -lz option will probably link to
|
||||
it. You can check the version at the top of zlib.h or with the
|
||||
ZLIB_VERSION symbol defined in zlib.h .
|
||||
|
||||
15. I have a question about OttoPDF.
|
||||
|
||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||
site: Joel Hainley, jhainley@myndkryme.com.
|
||||
|
||||
16. Can zlib decode Flate data in an Adobe PDF file?
|
||||
|
||||
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
|
||||
http://sourceforge.net/projects/acroformtool/ .
|
||||
|
||||
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
||||
|
||||
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
||||
generates an error such as:
|
||||
|
||||
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
||||
symbol __register_frame_info: referenced symbol not found
|
||||
|
||||
The symbol __register_frame_info is not part of zlib, it is generated by
|
||||
the C compiler (cc or gcc). You must recompile applications using zlib
|
||||
which have this problem. This problem is specific to Solaris. See
|
||||
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
||||
using zlib.
|
||||
|
||||
18. Why does gzip give an error on a file I make with compress/deflate?
|
||||
|
||||
The compress and deflate functions produce data in the zlib format, which
|
||||
is different and incompatible with the gzip format. The gz* functions in
|
||||
zlib on the other hand use the gzip format. Both the zlib and gzip formats
|
||||
use the same compressed data format internally, but have different headers
|
||||
and trailers around the compressed data.
|
||||
|
||||
19. Ok, so why are there two different formats?
|
||||
|
||||
The gzip format was designed to retain the directory information about a
|
||||
single file, such as the name and last modification date. The zlib format
|
||||
on the other hand was designed for in-memory and communication channel
|
||||
applications, and has a much more compact header and trailer and uses a
|
||||
faster integrity check than gzip.
|
||||
|
||||
20. Well that's nice, but how do I make a gzip file in memory?
|
||||
|
||||
You can request that deflate write the gzip format instead of the zlib
|
||||
format using deflateInit2(). You can also request that inflate decode the
|
||||
gzip format using inflateInit2(). Read zlib.h for more details.
|
||||
|
||||
21. Is zlib thread-safe?
|
||||
|
||||
Yes. However any library routines that zlib uses and any application-
|
||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||
functions use stdio library routines, and most of zlib's functions use the
|
||||
library memory allocation routines by default. zlib's *Init* functions
|
||||
allow for the application to provide custom memory allocation routines.
|
||||
|
||||
Of course, you should only operate on any given zlib or gzip stream from a
|
||||
single thread at a time.
|
||||
|
||||
22. Can I use zlib in my commercial application?
|
||||
|
||||
Yes. Please read the license in zlib.h.
|
||||
|
||||
23. Is zlib under the GNU license?
|
||||
|
||||
No. Please read the license in zlib.h.
|
||||
|
||||
24. The license says that altered source versions must be "plainly marked". So
|
||||
what exactly do I need to do to meet that requirement?
|
||||
|
||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||
particular, the final version number needs to be changed to "f", and an
|
||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||
maintainers. For example, if the version of the base zlib you are altering
|
||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||
update the version strings in deflate.c and inftrees.c.
|
||||
|
||||
For altered source distributions, you should also note the origin and
|
||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||
with the dates of the alterations. The origin should include at least your
|
||||
name (or your company's name), and an email address to contact for help or
|
||||
issues with the library.
|
||||
|
||||
Note that distributing a compiled zlib library along with zlib.h and
|
||||
zconf.h is also a source distribution, and so you should change
|
||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||
in zlib.h as you would for a full source distribution.
|
||||
|
||||
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||
exchange compressed data between them?
|
||||
|
||||
Yes and yes.
|
||||
|
||||
26. Will zlib work on a 64-bit machine?
|
||||
|
||||
Yes. It has been tested on 64-bit machines, and has no dependence on any
|
||||
data types being limited to 32-bits in length. If you have any
|
||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||
|
||||
27. Will zlib decompress data from the PKWare Data Compression Library?
|
||||
|
||||
No. The PKWare DCL uses a completely different compressed data format than
|
||||
does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||
directory for a possible solution to your problem.
|
||||
|
||||
28. Can I access data randomly in a compressed stream?
|
||||
|
||||
No, not without some preparation. If when compressing you periodically use
|
||||
Z_FULL_FLUSH, carefully write all the pending data at those points, and
|
||||
keep an index of those locations, then you can start decompression at those
|
||||
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
|
||||
can significantly degrade compression. Alternatively, you can scan a
|
||||
deflate stream once to generate an index, and then use that index for
|
||||
random access. See examples/zran.c .
|
||||
|
||||
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||
|
||||
It has in the past, but we have not heard of any recent evidence. There
|
||||
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
|
||||
If you know of recent, successful applications of zlib on these operating
|
||||
systems, please let us know. Thanks.
|
||||
|
||||
30. Is there some simpler, easier to read version of inflate I can look at to
|
||||
understand the deflate format?
|
||||
|
||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||
contrib/puff directory.
|
||||
|
||||
31. Does zlib infringe on any patents?
|
||||
|
||||
As far as we know, no. In fact, that was originally the whole point behind
|
||||
zlib. Look here for some more information:
|
||||
|
||||
http://www.gzip.org/#faq11
|
||||
|
||||
32. Can zlib work with greater than 4 GB of data?
|
||||
|
||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||
Each call of inflate() or deflate() is limited to input and output chunks
|
||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||
type, but there is no limit to the number of chunks. Note however that the
|
||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||
counters are provided as a convenience and are not used internally by
|
||||
inflate() or deflate(). The application can easily set up its own counters
|
||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||
|
||||
The word "may" appears several times above since there is a 4 GB limit only
|
||||
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
|
||||
64 bits, then the limit is 16 exabytes.
|
||||
|
||||
33. Does zlib have any security vulnerabilities?
|
||||
|
||||
The only one that we are aware of is potentially in gzprintf(). If zlib is
|
||||
compiled to use sprintf() or vsprintf(), then there is no protection
|
||||
against a buffer overflow of an 8K string space (or other value as set by
|
||||
gzbuffer()), other than the caller of gzprintf() assuring that the output
|
||||
will not exceed 8K. On the other hand, if zlib is compiled to use
|
||||
snprintf() or vsnprintf(), which should normally be the case, then there is
|
||||
no vulnerability. The ./configure script will display warnings if an
|
||||
insecure variation of sprintf() will be used by gzprintf(). Also the
|
||||
zlibCompileFlags() function will return information on what variant of
|
||||
sprintf() is used by gzprintf().
|
||||
|
||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||
find a portable implementation here:
|
||||
|
||||
http://www.ijs.si/software/snprintf/
|
||||
|
||||
Note that you should be using the most recent version of zlib. Versions
|
||||
1.1.3 and before were subject to a double-free vulnerability, and versions
|
||||
1.2.1 and 1.2.2 were subject to an access exception when decompressing
|
||||
invalid compressed data.
|
||||
|
||||
34. Is there a Java version of zlib?
|
||||
|
||||
Probably what you want is to use zlib in Java. zlib is already included
|
||||
as part of the Java SDK in the java.util.zip package. If you really want
|
||||
a version of zlib written in the Java language, look on the zlib home
|
||||
page for links: http://zlib.net/ .
|
||||
|
||||
35. I get this or that compiler or source-code scanner warning when I crank it
|
||||
up to maximally-pedantic. Can't you guys write proper code?
|
||||
|
||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||
in the universe. It just got to be a waste of time, and some compilers
|
||||
were downright silly as well as contradicted each other. So now, we simply
|
||||
make sure that the code always works.
|
||||
|
||||
36. Valgrind (or some similar memory access checker) says that deflate is
|
||||
performing a conditional jump that depends on an uninitialized value.
|
||||
Isn't that a bug?
|
||||
|
||||
No. That is intentional for performance reasons, and the output of deflate
|
||||
is not affected. This only started showing up recently since zlib 1.2.x
|
||||
uses malloc() by default for allocations, whereas earlier versions used
|
||||
calloc(), which zeros out the allocated memory. Even though the code was
|
||||
correct, versions 1.2.4 and later was changed to not stimulate these
|
||||
checkers.
|
||||
|
||||
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||
data format?
|
||||
|
||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||
formats and associated software.
|
||||
|
||||
38. How can I encrypt/decrypt zip files with zlib?
|
||||
|
||||
zlib doesn't support encryption. The original PKZIP encryption is very
|
||||
weak and can be broken with freely available programs. To get strong
|
||||
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
|
||||
compression. For PKZIP compatible "encryption", look at
|
||||
http://www.info-zip.org/
|
||||
|
||||
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||
|
||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||
probably have called the second one "zlib" instead to avoid confusion with
|
||||
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||
transfer encoding, there have been reports of servers and browsers that
|
||||
incorrectly produce or expect raw deflate data per the deflate
|
||||
specification in RFC 1951, most notably Microsoft. So even though the
|
||||
"deflate" transfer encoding using the zlib format would be the more
|
||||
efficient approach (and in fact exactly what the zlib format was designed
|
||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||
|
||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||
|
||||
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||
|
||||
No. PKWare has apparently decided to keep that format proprietary, since
|
||||
they have not documented it as they have previous compression formats. In
|
||||
any case, the compression improvements are so modest compared to other more
|
||||
modern approaches, that it's not worth the effort to implement.
|
||||
|
||||
41. I'm having a problem with the zip functions in zlib, can you help?
|
||||
|
||||
There are no zip functions in zlib. You are probably using minizip by
|
||||
Giles Vollant, which is found in the contrib directory of zlib. It is not
|
||||
part of zlib. In fact none of the stuff in contrib is part of zlib. The
|
||||
files in there are not supported by the zlib authors. You need to contact
|
||||
the authors of the respective contribution for help.
|
||||
|
||||
42. The match.asm code in contrib is under the GNU General Public License.
|
||||
Since it's part of zlib, doesn't that mean that all of zlib falls under the
|
||||
GNU GPL?
|
||||
|
||||
No. The files in contrib are not part of zlib. They were contributed by
|
||||
other authors and are provided as a convenience to the user within the zlib
|
||||
distribution. Each item in contrib has its own license.
|
||||
|
||||
43. Is zlib subject to export controls? What is its ECCN?
|
||||
|
||||
zlib is not subject to export controls, and so is classified as EAR99.
|
||||
|
||||
44. Can you please sign these lengthy legal documents and fax them back to us
|
||||
so that we can use your software in our product?
|
||||
|
||||
No. Go away. Shoo.
|
||||
@@ -1,55 +0,0 @@
|
||||
CMakeLists.txt cmake build file
|
||||
ChangeLog.zlib history of changes up to the fork from zlib 1.2.11
|
||||
FAQ.zlib Frequently Asked Questions about zlib, as distributed in zlib 1.2.11
|
||||
INDEX this file
|
||||
Makefile dummy Makefile that tells you to ./configure
|
||||
Makefile.in template for Unix Makefile
|
||||
README guess what
|
||||
README.zlib Copy of the original README file distributed in zlib 1.2.11
|
||||
configure configure script for Unix
|
||||
test/example.c zlib usages examples for build testing
|
||||
test/minigzip.c minimal gzip-like functionality for build testing
|
||||
test/infcover.c inf*.c code coverage for build coverage testing
|
||||
treebuild.xml XML description of source file dependencies
|
||||
zconf.h.cmakein zconf.h template for cmake
|
||||
zconf.h.in zconf.h template for configure
|
||||
zlib.3 Man page for zlib
|
||||
zlib.3.pdf Man page in PDF format
|
||||
zlib.map Linux symbol information
|
||||
zlib.pc.in Template for pkg-config descriptor
|
||||
zlib.pc.cmakein zlib.pc template for cmake
|
||||
zlib2ansi perl script to convert source files for C++ compilation
|
||||
|
||||
arch/ architecture-specific code
|
||||
doc/ documentation for formats and algorithms
|
||||
win32/ makefiles for Windows
|
||||
|
||||
zlib public header files (required for library use):
|
||||
zconf.h
|
||||
zlib.h
|
||||
|
||||
private source files used to build the zlib library:
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
crc32.h
|
||||
deflate.c
|
||||
deflate.h
|
||||
gzclose.c
|
||||
gzguts.h
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
infback.c
|
||||
inffast.c
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.c
|
||||
inflate.h
|
||||
inftrees.c
|
||||
inftrees.h
|
||||
trees.c
|
||||
trees.h
|
||||
uncompr.c
|
||||
zutil.c
|
||||
zutil.h
|
||||
@@ -1,64 +0,0 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
There are several methods for compiling and installing zlib-ng, depending
|
||||
on your favorite operating system and development toolkits.
|
||||
This document will attempt to give a general overview of some of them.
|
||||
|
||||
PS: We do not recommend running 'make install' unless you know what you
|
||||
are doing, as this can override the system default zlib library, and
|
||||
any wrong configuration or incompatability of zlib-ng can make the
|
||||
whole system unusable.
|
||||
|
||||
On linux distros, an alternative way to use zlib-ng instead of zlib
|
||||
for specific programs exist, use LD_PRELOAD.
|
||||
If the program is dynamically linked with zlib, then zlib-ng can take
|
||||
its place without risking system-wide instability. Ex:
|
||||
LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.11.zlib-ng /usr/bin/program
|
||||
|
||||
|
||||
Configure
|
||||
=========
|
||||
|
||||
Using the configure script is currently the main method of setting up the
|
||||
makefiles and preparing for compilation. Configure will attempt to detect
|
||||
the specifics of your system, and enable some of the relevant options for you.
|
||||
|
||||
Configure accepts several command-line options, some of the most important
|
||||
ones are detailed below.
|
||||
|
||||
--zlib-compat
|
||||
This enables options that will ensure that zlib-ng is compiled with all the
|
||||
functions that a standard zlib library contains, you will need to use this
|
||||
if you are going to be using zlib-ng as a drop-in replacement for zlib.
|
||||
|
||||
--without-optimizations
|
||||
This will disable zlib-ng specific optimizations (does not disable strategies).
|
||||
|
||||
--without-new-strategies
|
||||
This will disable specially optimized strategies, such as deflate_quick and
|
||||
deflate_medium.
|
||||
|
||||
Run configure like this:
|
||||
./configure --zlib-compat
|
||||
|
||||
Then you can compile using make:
|
||||
make
|
||||
make test
|
||||
|
||||
|
||||
Cmake
|
||||
=====
|
||||
|
||||
Cmake is an alternative to configure, basically letting you do the same thing,
|
||||
but with different tools and user interfaces.
|
||||
|
||||
Start by initializing cmake:
|
||||
cmake .
|
||||
|
||||
Then you can start the configuration tui to set the wanted options
|
||||
ccmake .
|
||||
|
||||
You can now compile using make:
|
||||
make
|
||||
make test
|
||||
@@ -1,19 +0,0 @@
|
||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
@@ -1,365 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
# ./configure; make test
|
||||
# Normally configure builds both a static and a shared library.
|
||||
# If you want to build just a static library, use: ./configure --static
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DZLIB_DEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
SFLAGS=-O
|
||||
LDFLAGS=-L.
|
||||
LIBNAME1=libz-ng
|
||||
LIBNAME2=zlib-ng
|
||||
SUFFIX=-ng
|
||||
TEST_LIBS=$(LIBNAME1).a
|
||||
LDSHARED=$(CC)
|
||||
LDSHAREDFLAGS=-shared
|
||||
|
||||
VER=1.9.9
|
||||
VER1=1
|
||||
|
||||
STATICLIB=$(LIBNAME1).a
|
||||
SHAREDLIB=$(LIBNAME1).so
|
||||
SHAREDLIBV=$(LIBNAME1).so.$(VER)
|
||||
SHAREDLIBM=$(LIBNAME1).so.$(VER1)
|
||||
IMPORTLIB=
|
||||
SHAREDTARGET=$(LIBNAME1).so.$(VER)
|
||||
PKGFILE=$(LIBNAME2).pc
|
||||
|
||||
LIBS=$(STATICLIB) $(SHAREDTARGET)
|
||||
|
||||
AR=ar
|
||||
ARFLAGS=rc
|
||||
DEFFILE=
|
||||
RC=
|
||||
RCFLAGS=
|
||||
RCOBJS=
|
||||
STRIP=
|
||||
RANLIB=ranlib
|
||||
LDCONFIG=ldconfig
|
||||
LDSHAREDLIBC=-lc
|
||||
EXE=
|
||||
|
||||
SRCDIR=.
|
||||
INCLUDES=-I$(SRCDIR)
|
||||
|
||||
ARCHDIR=arch/generic
|
||||
ARCH_STATIC_OBJS=
|
||||
ARCH_SHARED_OBJS=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
libdir = ${exec_prefix}/lib
|
||||
sharedlibdir = ${libdir}
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
|
||||
OBJZ = adler32.o compress.o crc32.o deflate.o deflate_fast.o deflate_medium.o deflate_slow.o functable.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o $(ARCH_STATIC_OBJS)
|
||||
OBJG = gzclose.o gzlib.o gzread.o gzwrite.o
|
||||
OBJC = $(OBJZ) $(OBJG)
|
||||
|
||||
PIC_OBJZ = adler32.lo compress.lo crc32.lo deflate.lo deflate_fast.lo deflate_medium.lo deflate_slow.lo functable.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo uncompr.lo zutil.lo $(ARCH_SHARED_OBJS)
|
||||
PIC_OBJG = gzclose.lo gzlib.lo gzread.lo gzwrite.lo
|
||||
PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
|
||||
|
||||
OBJS = $(OBJC)
|
||||
|
||||
PIC_OBJS = $(PIC_OBJC)
|
||||
|
||||
all: static shared
|
||||
|
||||
static: example$(EXE) minigzip$(EXE) fuzzers
|
||||
|
||||
shared: examplesh$(EXE) minigzipsh$(EXE)
|
||||
|
||||
all64: example64$(EXE) minigzip64$(EXE)
|
||||
|
||||
check: test
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
$(ARCHDIR)/%.o: $(SRCDIR)/$(ARCHDIR)/%.c
|
||||
$(MAKE) -C $(ARCHDIR) $(notdir $@)
|
||||
|
||||
$(ARCHDIR)/%.lo: $(SRCDIR)/$(ARCHDIR)/%.c
|
||||
$(MAKE) -C $(ARCHDIR) $(notdir $@)
|
||||
|
||||
%.o: $(ARCHDIR)/%.o
|
||||
-cp $< $@
|
||||
|
||||
%.lo: $(ARCHDIR)/%.lo
|
||||
-cp $< $@
|
||||
|
||||
test: all
|
||||
$(MAKE) -C test
|
||||
|
||||
# This variable is set by configure.
|
||||
WITH_FUZZERS=
|
||||
|
||||
# By default, use our own standalone_fuzz_target_runner.
|
||||
# This runner does no fuzzing, but simply executes the inputs
|
||||
# provided via parameters.
|
||||
# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
|
||||
# to link the fuzzer(s) against a real fuzzing engine.
|
||||
ifeq (,$(LIB_FUZZING_ENGINE))
|
||||
LIB_FUZZING_ENGINE = standalone_fuzz_target_runner.o
|
||||
else
|
||||
# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
|
||||
WITH_FUZZERS=1
|
||||
endif
|
||||
|
||||
ifeq (1,$(WITH_FUZZERS))
|
||||
fuzzers: checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE)
|
||||
else
|
||||
fuzzers:
|
||||
endif
|
||||
|
||||
# The standalone fuzz target runner.
|
||||
standalone_fuzz_target_runner.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
checksum_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
compress_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_small_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_large_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_flush_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_dict_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
minigzip_fuzzer.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $<
|
||||
checksum_fuzzer$(EXE): checksum_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) checksum_fuzzer.o $(STATICLIB) -lpthread
|
||||
compress_fuzzer$(EXE): compress_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) compress_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_small_fuzzer$(EXE): example_small_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_small_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_large_fuzzer$(EXE): example_large_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_large_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_flush_fuzzer$(EXE): example_flush_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_flush_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_dict_fuzzer.o $(STATICLIB) -lpthread
|
||||
minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(OBJG) $(STATICLIB) -lpthread
|
||||
|
||||
infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib$(SUFFIX).h zconf$(SUFFIX).h
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c
|
||||
|
||||
infcover$(EXE): infcover.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ infcover.o $(STATICLIB)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
cover: infcover$(EXE)
|
||||
rm -f *.gcda
|
||||
./infcover
|
||||
gcov inf*.c
|
||||
|
||||
$(STATICLIB): $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
example.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c
|
||||
|
||||
minigzip.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c
|
||||
|
||||
example64.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP -D_FILE_OFFSET_BITS=64 $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c
|
||||
|
||||
minigzip64.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP -D_FILE_OFFSET_BITS=64 $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c
|
||||
|
||||
zlibrc.o: win32/zlib$(SUFFIX)1.rc
|
||||
$(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc
|
||||
|
||||
.SUFFIXES: .lo
|
||||
|
||||
%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.lo: $(SRCDIR)/%.c
|
||||
$(CC) $(SFLAGS) -DPIC $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(OBJG): %.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(SHAREDTARGET): $(PIC_OBJS) $(DEFFILE) $(RCOBJS)
|
||||
ifneq ($(SHAREDTARGET),)
|
||||
$(LDSHARED) $(LDSHAREDFLAGS) $(LDFLAGS) -o $@ $(DEFFILE) $(PIC_OBJS) $(RCOBJS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
ifneq ($(SHAREDLIB),$(SHAREDTARGET))
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
endif
|
||||
endif
|
||||
|
||||
example$(EXE): example.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzip$(EXE): minigzip.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
examplesh$(EXE): example.o $(OBJG) $(SHAREDTARGET)
|
||||
$(CC) $(LDFLAGS) -o $@ example.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
example64$(EXE): example64.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ example64.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzip64$(EXE): minigzip64.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip64.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
install-shared: $(SHAREDTARGET)
|
||||
ifneq ($(SHAREDTARGET),)
|
||||
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET)
|
||||
cp $(SHAREDTARGET) $(DESTDIR)$(sharedlibdir)
|
||||
chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET)
|
||||
ifneq ($(SHAREDLIB),$(SHAREDTARGET))
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM)
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB)
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM)
|
||||
($(LDCONFIG) || true) >/dev/null 2>&1
|
||||
# ldconfig is for Linux
|
||||
endif
|
||||
ifneq ($(IMPORTLIB),)
|
||||
cp $(IMPORTLIB) $(DESTDIR)$(sharedlibdir)
|
||||
chmod 644 $(DESTDIR)$(sharedlibdir)/$(IMPORTLIB)
|
||||
endif
|
||||
endif
|
||||
|
||||
install-static: $(STATICLIB)
|
||||
-@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
|
||||
rm -f $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
cp $(STATICLIB) $(DESTDIR)$(libdir)
|
||||
chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
-@($(RANLIB) $(DESTDIR)$(libdir)/$(STATICLIB) || true) >/dev/null 2>&1
|
||||
# The ranlib in install-static is needed on NeXTSTEP which checks file times
|
||||
|
||||
install-libs: install-shared install-static
|
||||
-@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
|
||||
rm -f $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
cp $(SRCDIR)/zlib.3 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
chmod 644 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
rm -f $(DESTDIR)$(pkgconfigdir)/$(PKGFILE)
|
||||
cp $(PKGFILE) $(DESTDIR)$(pkgconfigdir)
|
||||
chmod 644 $(DESTDIR)$(pkgconfigdir)/$(PKGFILE)
|
||||
|
||||
install: install-libs
|
||||
-@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
|
||||
rm -f $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h
|
||||
cp $(SRCDIR)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zlib$(SUFFIX).h
|
||||
cp zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h
|
||||
chmod 644 $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h
|
||||
|
||||
uninstall-static:
|
||||
cd $(DESTDIR)$(libdir) && rm -f $(STATICLIB)
|
||||
|
||||
uninstall-shared:
|
||||
ifneq ($(SHAREDLIB),)
|
||||
cd $(DESTDIR)$(sharedlibdir) && rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM)
|
||||
endif
|
||||
ifneq ($(IMPORTLIB),)
|
||||
cd $(DESTDIR)$(sharedlibdir) && rm -f $(IMPORTLIB)
|
||||
endif
|
||||
|
||||
uninstall: uninstall-static uninstall-shared
|
||||
cd $(DESTDIR)$(includedir) && rm -f zlib$(SUFFIX).h zconf$(SUFFIX).h
|
||||
cd $(DESTDIR)$(man3dir) && rm -f zlib$(SUFFIX).3
|
||||
cd $(DESTDIR)$(pkgconfigdir) && rm -f $(PKGFILE)
|
||||
|
||||
docs: zlib.3.pdf
|
||||
|
||||
zlib.3.pdf: $(SRCDIR)/zlib.3
|
||||
groff -mandoc -f H -T ps $(SRCDIR)/zlib.3 | ps2pdf - zlib.3.pdf
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
@if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi
|
||||
@if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi
|
||||
rm -f *.o *.lo *~ \
|
||||
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
|
||||
example64$(EXE) minigzip64$(EXE) \
|
||||
checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \
|
||||
example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) \
|
||||
infcover \
|
||||
$(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \
|
||||
foo.gz so_locations \
|
||||
_match.s maketree
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
rm -f a.out a.exe
|
||||
rm -f *.pc
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean
|
||||
@if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi
|
||||
@if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi
|
||||
rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein
|
||||
-@rm -f .DS_Store
|
||||
# Reset Makefile if building inside source tree
|
||||
@if [ -f Makefile.in ]; then \
|
||||
printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \
|
||||
printf '\ndistclean:\n\t$(MAKE) -f Makefile.in distclean\n' >> Makefile ; \
|
||||
touch -r $(SRCDIR)/Makefile.in Makefile ; fi
|
||||
# Reset zconf.h and zconf.h.cmakein if building inside source tree
|
||||
@if [ -f zconf.h.in ]; then \
|
||||
cp -p $(SRCDIR)/zconf.h.in zconf.h ; \
|
||||
grep -v '^#cmakedefine' $(SRCDIR)/zconf.h.in > zconf.h.cmakein &&\
|
||||
touch -r $(SRCDIR)/zconf.h.in zconf.h.cmakein ; fi
|
||||
# Cleanup these files if building outside source tree
|
||||
@if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf Makefile; fi
|
||||
# Remove arch and test directory if building outside source tree
|
||||
@if [ ! -f $(ARCHDIR)/Makefile.in ]; then rm -rf arch; fi
|
||||
@if [ ! -f test/Makefile.in ]; then rm -rf test; fi
|
||||
|
||||
tags:
|
||||
etags $(SRCDIR)/*.[ch]
|
||||
@@ -1,81 +0,0 @@
|
||||
zlib-ng - zlib for the next generation systems
|
||||
|
||||
Maintained by Hans Kristian Rosbach
|
||||
aka Dead2 (zlib-ng àt circlestorm dót org)
|
||||
|
||||
|
||||
Fork Motivation and History
|
||||
---------------------------
|
||||
|
||||
The motivation for this fork was due to seeing several 3rd party
|
||||
contributions containing new optimizations not getting implemented
|
||||
into the official zlib repository.
|
||||
|
||||
Mark Adler has been maintaining zlib for a very long time, and he has
|
||||
done a great job and hopefully he will continue for a long time yet.
|
||||
The idea of zlib-ng is not to replace zlib, but to co-exist as a
|
||||
drop-in replacement with a lower threshold for code change.
|
||||
|
||||
zlib has a long history and is incredibly portable, even supporting
|
||||
lots of systems that predate the Internet. This is great, but it does
|
||||
complicate further development and maintainability.
|
||||
The zlib code has numerous workarounds for old compilers that do not
|
||||
understand ANSI-C or to accommodate systems with limitations such as
|
||||
operating in a 16-bit environment.
|
||||
|
||||
Many of these workarounds are only maintenance burdens, some of them
|
||||
are pretty huge code-wise. For example, the [v]s[n]printf workaround
|
||||
code has a whopping 8 different implementations just to cater to
|
||||
various old compilers. With this many workarounds cluttered throughout
|
||||
the code, new programmers with an idea/interest for zlib will need
|
||||
to take some time to figure out why all of these seemingly strange
|
||||
things are used, and how to work within those confines.
|
||||
|
||||
So I decided to make a fork, merge all the Intel optimizations, merge
|
||||
the Cloudflare optimizations that did not conflict, plus a couple
|
||||
of other smaller patches. Then I started cleaning out workarounds,
|
||||
various dead code, all contrib and example code as there is little
|
||||
point in having those in this fork for various reasons.
|
||||
|
||||
A lot of improvements have gone into zlib-ng since its start, and
|
||||
numerous people have contributed both small and big improvements,
|
||||
or valuable testing.
|
||||
|
||||
Please read LICENSE.md, it is very simple and very liberal.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Zlib-ng is a young project, and we aim to be open to contributions,
|
||||
and we would be delighted to receive pull requests on github.
|
||||
Just remember that any code you submit must be your own and it must
|
||||
be zlib licensed.
|
||||
Help with testing and reviewing of pull requests etc is also very
|
||||
much appreciated.
|
||||
|
||||
If you are interested in contributing, please consider joining our
|
||||
IRC channel #zlib-ng on the Freenode IRC network.
|
||||
|
||||
|
||||
Acknowledgments
|
||||
----------------
|
||||
|
||||
Thanks to Servebolt.com for sponsoring my maintainership of zlib-ng.
|
||||
|
||||
Thanks go out to all the people and companies who have taken the time
|
||||
to contribute code reviews, testing and/or patches. Zlib-ng would not
|
||||
have been nearly as good without you.
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz.
|
||||
The deflate and zlib specifications were written by L. Peter Deutsch.
|
||||
|
||||
zlib was originally created by Jean-loup Gailly (compression)
|
||||
and Mark Adler (decompression).
|
||||
|
||||
|
||||
Build Status
|
||||
------------
|
||||
|
||||
Travis CI: [](https://travis-ci.org/zlib-ng/zlib-ng/)
|
||||
Buildkite: [](https://buildkite.com/circlestorm-productions/zlib-ng)
|
||||
@@ -1,118 +0,0 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
rfc1952 (gzip format).
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file test/example.c which also tests that
|
||||
the library is working correctly. Another example is given in the file
|
||||
test/minigzip.c. The compression library itself is composed of all source
|
||||
files in the root directory.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile.in. In short "./configure; make test", and if that goes
|
||||
well, "make install" should work for most flavors of Unix. For Windows, use
|
||||
one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
||||
make_vms.com.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||
http://zlib.net/ . Before reporting a problem, please check this site to
|
||||
verify that you have the latest version of zlib; otherwise get the latest
|
||||
version and check whether the problem still exists or not.
|
||||
|
||||
PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
|
||||
|
||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.11 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
zlib is available in Java using the java.util.zip package, documented at
|
||||
http://java.sun.com/developer/technicalArticles/Programming/compression/ .
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
|
||||
at CPAN (Comprehensive Perl Archive Network) sites, including
|
||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
|
||||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://docs.python.org/library/zlib.html .
|
||||
|
||||
zlib is built into tcl: http://wiki.tcl.tk/4610 .
|
||||
|
||||
An experimental package to read and write files in .zip format, written on top
|
||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||
contrib/minizip directory of zlib.
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||
|
||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||
compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||
when compiled with cc.
|
||||
|
||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||
necessary to get gzprintf working correctly. This is done by configure.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||
other compilers. Use "make test" to check your compiler.
|
||||
|
||||
- gzdopen is not supported on RISCOS or BEOS.
|
||||
|
||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib; they
|
||||
are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code. We make all
|
||||
contributions to and distributions of this project solely in our personal
|
||||
capacity, and are not conveying any rights to any intellectual property of
|
||||
any third parties.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
||||
@@ -1,132 +0,0 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "functable.h"
|
||||
#include "adler32_p.h"
|
||||
|
||||
uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2);
|
||||
|
||||
#define DO1(buf, i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf, i) DO1(buf, i); DO1(buf, i+1);
|
||||
#define DO4(buf, i) DO2(buf, i); DO2(buf, i+2);
|
||||
#define DO8(buf, i) DO4(buf, i); DO4(buf, i+4);
|
||||
#define DO16(buf) DO8(buf, 0); DO8(buf, 8);
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
uint32_t sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1)
|
||||
return adler32_len_1(adler, buf, sum2);
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16)
|
||||
return adler32_len_16(adler, buf, len, sum2);
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
#ifdef UNROLL_MORE
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
#else
|
||||
n = NMAX / 8; /* NMAX is divisible by 8 */
|
||||
#endif
|
||||
do {
|
||||
#ifdef UNROLL_MORE
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
#else
|
||||
DO8(buf, 0); /* 8 sums unrolled */
|
||||
buf += 8;
|
||||
#endif
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
#else
|
||||
while (len >= 8) {
|
||||
len -= 8;
|
||||
DO8(buf, 0);
|
||||
buf += 8;
|
||||
#endif
|
||||
}
|
||||
while (len) {
|
||||
--len;
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(adler32_z)(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
return functable.adler32(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(adler32)(uint32_t adler, const unsigned char *buf, uint32_t len) {
|
||||
return functable.adler32(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2) {
|
||||
uint32_t sum1;
|
||||
uint32_t sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffff;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(adler32_combine)(uint32_t adler1, uint32_t adler2, z_off_t len2) {
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(adler32_combine64)(uint32_t adler1, uint32_t adler2, z_off64_t len2) {
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/* adler32_p.h -- Private inline functions and macros shared with
|
||||
* different computation of the Adler-32 checksum
|
||||
* of a data stream.
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef ADLER32_P_H
|
||||
#define ADLER32_P_H
|
||||
|
||||
#define BASE 65521U /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
uint32_t tmp = a >> 16; \
|
||||
a &= 0xffff; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, uint32_t sum2) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) {
|
||||
while (len) {
|
||||
--len;
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
#endif /* ADLER32_P_H */
|
||||
@@ -1,2 +0,0 @@
|
||||
# ignore Makefiles; they're all automatically generated
|
||||
Makefile
|
||||
@@ -1,54 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
CC=
|
||||
CFLAGS=
|
||||
SFLAGS=
|
||||
INCLUDES=
|
||||
SUFFIX=
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
all: adler32_neon.o adler32_neon.lo armfeature.o armfeature.lo crc32_acle.o crc32_acle.lo fill_window_arm.o fill_window_arm.lo insert_string_acle.o insert_string_acle.lo
|
||||
|
||||
adler32_neon.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c
|
||||
|
||||
adler32_neon.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c
|
||||
|
||||
armfeature.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c
|
||||
|
||||
armfeature.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c
|
||||
|
||||
crc32_acle.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c
|
||||
|
||||
crc32_acle.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c
|
||||
|
||||
fill_window_arm.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_arm.c
|
||||
|
||||
fill_window_arm.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_arm.c
|
||||
|
||||
insert_string_acle.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c
|
||||
|
||||
insert_string_acle.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
|
||||
distclean:
|
||||
rm -f Makefile
|
||||
@@ -1,134 +0,0 @@
|
||||
/* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* Copyright (C) 2017 ARM Holdings Inc.
|
||||
* Author: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "adler32_neon.h"
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
#include <arm_neon.h>
|
||||
#include "adler32_p.h"
|
||||
|
||||
static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) {
|
||||
static const uint8_t taps[32] = {
|
||||
32, 31, 30, 29, 28, 27, 26, 25,
|
||||
24, 23, 22, 21, 20, 19, 18, 17,
|
||||
16, 15, 14, 13, 12, 11, 10, 9,
|
||||
8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
|
||||
uint32x2_t adacc2, s2acc2, as;
|
||||
uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
|
||||
|
||||
uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
|
||||
adacc = vsetq_lane_u32(s[0], adacc, 0);
|
||||
s2acc = vsetq_lane_u32(s[1], s2acc, 0);
|
||||
|
||||
while (len >= 2) {
|
||||
uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16);
|
||||
uint16x8_t adler, sum2;
|
||||
s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
|
||||
adler = vpaddlq_u8( d0);
|
||||
adler = vpadalq_u8(adler, d1);
|
||||
sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1));
|
||||
adacc = vpadalq_u16(adacc, adler);
|
||||
s2acc = vpadalq_u16(s2acc, sum2);
|
||||
len -= 2;
|
||||
buf += 32;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
uint8x16_t d0 = vld1q_u8(buf);
|
||||
uint16x8_t adler, sum2;
|
||||
s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
|
||||
adler = vpaddlq_u8(d0);
|
||||
sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
|
||||
adacc = vpadalq_u16(adacc, adler);
|
||||
s2acc = vpadalq_u16(s2acc, sum2);
|
||||
buf += 16;
|
||||
len--;
|
||||
}
|
||||
|
||||
adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
|
||||
s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc));
|
||||
as = vpadd_u32(adacc2, s2acc2);
|
||||
s[0] = vget_lane_u32(as, 0);
|
||||
s[1] = vget_lane_u32(as, 1);
|
||||
}
|
||||
|
||||
static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, size_t len) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
pair[0] += buf[i];
|
||||
pair[1] += pair[0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
/* split Adler-32 into component sums */
|
||||
uint32_t sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1)
|
||||
return adler32_len_1(adler, buf, sum2);
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16)
|
||||
return adler32_len_16(adler, buf, len, sum2);
|
||||
|
||||
uint32_t pair[2];
|
||||
int n = NMAX;
|
||||
unsigned int done = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* Split Adler-32 into component sums, it can be supplied by
|
||||
* the caller sites (e.g. in a PNG file).
|
||||
*/
|
||||
pair[0] = adler;
|
||||
pair[1] = sum2;
|
||||
|
||||
for (i = 0; i < len; i += n) {
|
||||
if ((i + n) > len)
|
||||
n = len - i;
|
||||
|
||||
if (n < 16)
|
||||
break;
|
||||
|
||||
NEON_accum32(pair, buf + i, n / 16);
|
||||
pair[0] %= BASE;
|
||||
pair[1] %= BASE;
|
||||
|
||||
done += (n / 16) * 16;
|
||||
}
|
||||
|
||||
/* Handle the tail elements. */
|
||||
if (done < len) {
|
||||
NEON_handle_tail(pair, (buf + done), len - done);
|
||||
pair[0] %= BASE;
|
||||
pair[1] %= BASE;
|
||||
}
|
||||
|
||||
/* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */
|
||||
return (pair[1] << 16) | pair[0];
|
||||
}
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* Copyright (C) 2017 ARM Holdings Inc.
|
||||
* Author: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef __ADLER32_NEON__
|
||||
#define __ADLER32_NEON__
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
// Depending on the compiler flavor, size_t may be defined in one or the other header. See:
|
||||
// http://stackoverflow.com/questions/26410466/gcc-linaro-compiler-throws-error-unknown-type-name-size-t
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
/* arm.h -- check for ARM features.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef ARM_H_
|
||||
#define ARM_H_
|
||||
|
||||
extern int arm_cpu_has_neon;
|
||||
extern int arm_cpu_has_crc32;
|
||||
|
||||
void ZLIB_INTERNAL arm_check_features(void);
|
||||
|
||||
#endif /* ARM_H_ */
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "zutil.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/auxv.h>
|
||||
# include <asm/hwcap.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <winapifamily.h>
|
||||
#endif
|
||||
|
||||
static int arm_has_crc32() {
|
||||
#if defined(__linux__) && defined(HWCAP2_CRC32)
|
||||
return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0;
|
||||
#elif defined(ARM_NOCHECK_ACLE)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* AArch64 has neon. */
|
||||
#if !defined(__aarch64__)
|
||||
static inline int arm_has_neon()
|
||||
{
|
||||
#if defined(__linux__) && defined(HWCAP_NEON)
|
||||
return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0;
|
||||
#elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
return 1; /* Always supported */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARM_NOCHECK_NEON)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ZLIB_INTERNAL int arm_cpu_has_neon;
|
||||
ZLIB_INTERNAL int arm_cpu_has_crc32;
|
||||
|
||||
void ZLIB_INTERNAL arm_check_features(void) {
|
||||
#if defined(__aarch64__)
|
||||
arm_cpu_has_neon = 1; /* always available */
|
||||
#else
|
||||
arm_cpu_has_neon = arm_has_neon();
|
||||
#endif
|
||||
arm_cpu_has_crc32 = arm_has_crc32();
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* crc32_acle.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
||||
* Copyright (C) 2016 Yang Zhang
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __ARM_FEATURE_CRC32
|
||||
# include <arm_acle.h>
|
||||
# ifdef ZLIB_COMPAT
|
||||
# include <zconf.h>
|
||||
# else
|
||||
# include <zconf-ng.h>
|
||||
# endif
|
||||
# ifdef __linux__
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
|
||||
uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) {
|
||||
register uint32_t c;
|
||||
register const uint16_t *buf2;
|
||||
register const uint32_t *buf4;
|
||||
|
||||
c = ~crc;
|
||||
if (len && ((ptrdiff_t)buf & 1)) {
|
||||
c = __crc32b(c, *buf++);
|
||||
len--;
|
||||
}
|
||||
|
||||
if ((len > sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) {
|
||||
buf2 = (const uint16_t *) buf;
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
buf4 = (const uint32_t *) buf2;
|
||||
} else {
|
||||
buf4 = (const uint32_t *) buf;
|
||||
}
|
||||
|
||||
# if defined(__aarch64__)
|
||||
if ((len > sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
const uint64_t *buf8 = (const uint64_t *) buf4;
|
||||
|
||||
# ifdef UNROLL_MORE
|
||||
while (len >= 4 * sizeof(uint64_t)) {
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
len -= 4 * sizeof(uint64_t);
|
||||
}
|
||||
# endif
|
||||
|
||||
while (len >= sizeof(uint64_t)) {
|
||||
c = __crc32d(c, *buf8++);
|
||||
len -= sizeof(uint64_t);
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint32_t)) {
|
||||
buf4 = (const uint32_t *) buf8;
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
buf2 = (const uint16_t *) buf4;
|
||||
} else {
|
||||
buf2 = (const uint16_t *) buf8;
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint16_t)) {
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
}
|
||||
|
||||
buf = (const unsigned char *) buf2;
|
||||
# else /* __aarch64__ */
|
||||
|
||||
# ifdef UNROLL_MORE
|
||||
while (len >= 8 * sizeof(uint32_t)) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= 8 * sizeof(uint32_t);
|
||||
}
|
||||
# endif
|
||||
|
||||
while (len >= sizeof(uint32_t)) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint16_t)) {
|
||||
buf2 = (const uint16_t *) buf4;
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
buf = (const unsigned char *) buf2;
|
||||
} else {
|
||||
buf = (const unsigned char *) buf4;
|
||||
}
|
||||
# endif /* __aarch64__ */
|
||||
|
||||
if (len) {
|
||||
c = __crc32b(c, *buf);
|
||||
}
|
||||
|
||||
c = ~c;
|
||||
return c;
|
||||
}
|
||||
#endif /* __ARM_FEATURE_CRC32 */
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef ARM_CTZL_H
|
||||
#define ARM_CTZL_H
|
||||
|
||||
#include <armintr.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
static __forceinline unsigned long __builtin_ctzl(unsigned long value) {
|
||||
return _arm_clz(_arm_rbit(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
/* fill_window_arm.c -- Optimized hash table shifting for ARM with support for NEON instructions
|
||||
* Copyright (C) 2017 Mika T. Lindqvist
|
||||
*
|
||||
* Authors:
|
||||
* Mika T. Lindqvist <postmaster@raasu.org>
|
||||
* Jun He <jun.he@arm.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "functable.h"
|
||||
|
||||
extern ZLIB_INTERNAL int read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size);
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
#include <arm_neon.h>
|
||||
|
||||
/* SIMD version of hash_chain rebase */
|
||||
static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) {
|
||||
register uint16x8_t v, *p;
|
||||
register size_t n;
|
||||
|
||||
size_t size = entries*sizeof(table[0]);
|
||||
Assert((size % sizeof(uint16x8_t) * 8 == 0), "hash table size err");
|
||||
|
||||
Assert(sizeof(Pos) == 2, "Wrong Pos size");
|
||||
v = vdupq_n_u16(window_size);
|
||||
|
||||
p = (uint16x8_t *)table;
|
||||
n = size / (sizeof(uint16x8_t) * 8);
|
||||
do {
|
||||
p[0] = vqsubq_u16(p[0], v);
|
||||
p[1] = vqsubq_u16(p[1], v);
|
||||
p[2] = vqsubq_u16(p[2], v);
|
||||
p[3] = vqsubq_u16(p[3], v);
|
||||
p[4] = vqsubq_u16(p[4], v);
|
||||
p[5] = vqsubq_u16(p[5], v);
|
||||
p[6] = vqsubq_u16(p[6], v);
|
||||
p[7] = vqsubq_u16(p[7], v);
|
||||
p += 8;
|
||||
} while (--n);
|
||||
}
|
||||
#else
|
||||
/* generic version for hash rebase */
|
||||
static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < entries; i++) {
|
||||
table[i] = (table[i] >= window_size) ? (table[i] - window_size) : NIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fill_window_arm(deflate_state *s) {
|
||||
register unsigned n;
|
||||
unsigned long more; /* Amount of free space at the end of the window. */
|
||||
unsigned int wsize = s->w_size;
|
||||
|
||||
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
|
||||
|
||||
do {
|
||||
more = s->window_size - s->lookahead - s->strstart;
|
||||
|
||||
/* If the window is almost full and there is insufficient lookahead,
|
||||
* move the upper half to the lower one to make room in the upper half.
|
||||
*/
|
||||
if (s->strstart >= wsize+MAX_DIST(s)) {
|
||||
memcpy(s->window, s->window+wsize, wsize);
|
||||
s->match_start -= wsize;
|
||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
||||
s->block_start -= wsize;
|
||||
|
||||
/* Slide the hash table (could be avoided with 32 bit values
|
||||
at the expense of memory usage). We slide even when level == 0
|
||||
to keep the hash table consistent if we switch back to level > 0
|
||||
later. (Using level 0 permanently is not an optimal usage of
|
||||
zlib, so we don't care about this pathological case.)
|
||||
*/
|
||||
|
||||
slide_hash_chain(s->head, s->hash_size, wsize);
|
||||
slide_hash_chain(s->prev, wsize, wsize);
|
||||
more += wsize;
|
||||
}
|
||||
if (s->strm->avail_in == 0)
|
||||
break;
|
||||
|
||||
/* If there was no sliding:
|
||||
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
|
||||
* more == window_size - lookahead - strstart
|
||||
* => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
|
||||
* => more >= window_size - 2*WSIZE + 2
|
||||
* In the BIG_MEM or MMAP case (not yet supported),
|
||||
* window_size == input_size + MIN_LOOKAHEAD &&
|
||||
* strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
|
||||
* Otherwise, window_size == 2*WSIZE so more >= 2.
|
||||
* If there was sliding, more >= WSIZE. So in all cases, more >= 2.
|
||||
*/
|
||||
Assert(more >= 2, "more < 2");
|
||||
|
||||
n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
|
||||
s->lookahead += n;
|
||||
|
||||
/* Initialize the hash value now that we have some input: */
|
||||
if (s->lookahead + s->insert >= MIN_MATCH) {
|
||||
unsigned int str = s->strstart - s->insert;
|
||||
unsigned int insert_cnt = s->insert;
|
||||
unsigned int slen;
|
||||
|
||||
s->ins_h = s->window[str];
|
||||
|
||||
if (unlikely(s->lookahead < MIN_MATCH))
|
||||
insert_cnt += s->lookahead - MIN_MATCH;
|
||||
slen = insert_cnt;
|
||||
if (str >= (MIN_MATCH - 2))
|
||||
{
|
||||
str += 2 - MIN_MATCH;
|
||||
insert_cnt += MIN_MATCH - 2;
|
||||
}
|
||||
if (insert_cnt > 0)
|
||||
{
|
||||
functable.insert_string(s, str, insert_cnt);
|
||||
s->insert -= slen;
|
||||
}
|
||||
}
|
||||
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
|
||||
* but this is not important since only literal bytes will be emitted.
|
||||
*/
|
||||
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
|
||||
|
||||
/* If the WIN_INIT bytes after the end of the current data have never been
|
||||
* written, then zero those bytes in order to avoid memory check reports of
|
||||
* the use of uninitialized (or uninitialised as Julian writes) bytes by
|
||||
* the longest match routines. Update the high water mark for the next
|
||||
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
|
||||
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
|
||||
*/
|
||||
if (s->high_water < s->window_size) {
|
||||
unsigned long curr = s->strstart + (unsigned long)s->lookahead;
|
||||
unsigned long init;
|
||||
|
||||
if (s->high_water < curr) {
|
||||
/* Previous high water mark below current data -- zero WIN_INIT
|
||||
* bytes or up to end of window, whichever is less.
|
||||
*/
|
||||
init = s->window_size - curr;
|
||||
if (init > WIN_INIT)
|
||||
init = WIN_INIT;
|
||||
memset(s->window + curr, 0, init);
|
||||
s->high_water = curr + init;
|
||||
} else if (s->high_water < curr + WIN_INIT) {
|
||||
/* High water mark at or above current data, but below current data
|
||||
* plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
|
||||
* to end of window, whichever is less.
|
||||
*/
|
||||
init = curr + WIN_INIT;
|
||||
if (init > s->window_size)
|
||||
init = s->window_size;
|
||||
init -= s->high_water;
|
||||
memset(s->window + s->high_water, 0, init);
|
||||
s->high_water += init;
|
||||
}
|
||||
}
|
||||
|
||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search");
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/* insert_string_acle.c -- insert_string variant using ACLE's CRC instructions
|
||||
*
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ARM_FEATURE_CRC32) && defined(ARM_ACLE_CRC_HASH)
|
||||
#include <arm_acle.h>
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
|
||||
/* ===========================================================================
|
||||
* Insert string str in the dictionary and set match_head to the previous head
|
||||
* of the hash chain (the most recent string with same hash key). Return
|
||||
* the previous length of the hash chain.
|
||||
* IN assertion: all calls to to INSERT_STRING are made with consecutive
|
||||
* input characters and the first MIN_MATCH bytes of str are valid
|
||||
* (except for the last MIN_MATCH-1 bytes of the input file).
|
||||
*/
|
||||
Pos insert_string_acle(deflate_state *const s, const Pos str, unsigned int count) {
|
||||
Pos p, lp, ret;
|
||||
|
||||
if (unlikely(count == 0)) {
|
||||
return s->prev[str & s->w_mask];
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
lp = str + count - 1; /* last position */
|
||||
|
||||
for (p = str; p <= lp; p++) {
|
||||
uint32_t val, h, hm;
|
||||
memcpy(&val, &s->window[p], sizeof(val));
|
||||
|
||||
if (s->level >= TRIGGER_LEVEL)
|
||||
val &= 0xFFFFFF;
|
||||
|
||||
h = __crc32w(0, val);
|
||||
hm = h & s->hash_mask;
|
||||
|
||||
Pos head = s->head[hm];
|
||||
if (head != p) {
|
||||
s->prev[p & s->w_mask] = head;
|
||||
s->head[hm] = p;
|
||||
if (p == lp)
|
||||
ret = head;
|
||||
} else if (p == lp) {
|
||||
ret = p;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
CC=
|
||||
CFLAGS=
|
||||
SFLAGS=
|
||||
INCLUDES=
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
all:
|
||||
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~ \
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
@@ -1,40 +0,0 @@
|
||||
# Makefile for zlib-ng
|
||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
CC=
|
||||
CFLAGS=
|
||||
SFLAGS=
|
||||
INCLUDES=
|
||||
SUFFIX=
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
dfltcc_common.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c
|
||||
|
||||
dfltcc_common.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c
|
||||
|
||||
dfltcc_deflate.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c
|
||||
|
||||
dfltcc_deflate.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c
|
||||
|
||||
dfltcc_inflate.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c
|
||||
|
||||
dfltcc_inflate.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
|
||||
distclean:
|
||||
rm -f Makefile
|
||||
@@ -1,69 +0,0 @@
|
||||
This directory contains IBM Z DEFLATE CONVERSION CALL support for
|
||||
zlib-ng. In order to enable it, the following build commands should be
|
||||
used:
|
||||
|
||||
$ ./configure --with-dfltcc-deflate --with-dfltcc-inflate
|
||||
$ make
|
||||
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_DEFLATE=1 -DWITH_DFLTCC_INFLATE=1 .
|
||||
$ make
|
||||
|
||||
When built like this, zlib-ng would compress in hardware on level 1,
|
||||
and in software on all other levels. Decompression will always happen
|
||||
in hardware. In order to enable DFLTCC compression for levels 1-6 (i.e.
|
||||
to make it used by default) one could add -DDFLTCC_LEVEL_MASK=0x7e to
|
||||
CFLAGS when building zlib-ng.
|
||||
|
||||
Two DFLTCC compression calls produce the same results only when they
|
||||
both are made on machines of the same generation, and when the
|
||||
respective buffers have the same offset relative to the start of the
|
||||
page. Therefore care should be taken when using hardware compression
|
||||
when reproducible results are desired.
|
||||
|
||||
DFLTCC does not support every single zlib-ng feature, in particular:
|
||||
|
||||
* inflate(Z_BLOCK) and inflate(Z_TREES)
|
||||
* inflateMark()
|
||||
* inflatePrime()
|
||||
* deflateParams() after the first deflate() call
|
||||
|
||||
When used, these functions will either switch to software, or, in case
|
||||
this is not possible, gracefully fail.
|
||||
|
||||
All SystemZ-specific code lives in a separate file and is integrated
|
||||
with the rest of zlib-ng using hook macros, which are explained below.
|
||||
|
||||
DFLTCC takes as arguments a parameter block, an input buffer, an output
|
||||
buffer and a window. ZALLOC_STATE, ZFREE_STATE, ZCOPY_STATE,
|
||||
ZALLOC_WINDOW and TRY_FREE_WINDOW macros encapsulate allocation details
|
||||
for the parameter block (which is allocated alongside zlib-ng state)
|
||||
and the window (which must be page-aligned).
|
||||
|
||||
While for inflate software and hardware window formats match, this is
|
||||
not the case for deflate. Therefore, deflateSetDictionary and
|
||||
deflateGetDictionary need special handling, which is triggered using
|
||||
the DEFLATE_SET_DICTIONARY_HOOK and DEFLATE_GET_DICTIONARY_HOOK macros.
|
||||
|
||||
deflateResetKeep() and inflateResetKeep() update the DFLTCC parameter
|
||||
block using DEFLATE_RESET_KEEP_HOOK and INFLATE_RESET_KEEP_HOOK macros.
|
||||
|
||||
DEFLATE_PARAMS_HOOK, INFLATE_PRIME_HOOK and INFLATE_MARK_HOOK macros
|
||||
make the unsupported deflateParams(), inflatePrime() and inflateMark()
|
||||
calls fail gracefully.
|
||||
|
||||
The algorithm implemented in hardware has different compression ratio
|
||||
than the one implemented in software. DEFLATE_BOUND_ADJUST_COMPLEN and
|
||||
DEFLATE_NEED_CONSERVATIVE_BOUND macros make deflateBound() return the
|
||||
correct results for the hardware implementation.
|
||||
|
||||
Actual compression and decompression are handled by DEFLATE_HOOK and
|
||||
INFLATE_TYPEDO_HOOK macros. Since inflation with DFLTCC manages the
|
||||
window on its own, calling updatewindow() is suppressed using
|
||||
INFLATE_NEED_UPDATEWINDOW() macro.
|
||||
|
||||
In addition to compression, DFLTCC computes CRC-32 and Adler-32
|
||||
checksums, therefore, whenever it's used, software checksumming is
|
||||
suppressed using DEFLATE_NEED_CHECKSUM and INFLATE_NEED_CHECKSUM
|
||||
macros.
|
||||
@@ -1,86 +0,0 @@
|
||||
/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL general support. */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "dfltcc_common.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
/*
|
||||
Memory management.
|
||||
|
||||
DFLTCC requires parameter blocks and window to be aligned. zlib-ng allows
|
||||
users to specify their own allocation functions, so using e.g.
|
||||
`posix_memalign' is not an option. Thus, we overallocate and take the
|
||||
aligned portion of the buffer.
|
||||
*/
|
||||
static inline int is_dfltcc_enabled(void)
|
||||
{
|
||||
uint64_t facilities[(DFLTCC_FACILITY / 64) + 1];
|
||||
register uint8_t r0 __asm__("r0");
|
||||
|
||||
memset(facilities, 0, sizeof(facilities));
|
||||
r0 = sizeof(facilities) / sizeof(facilities[0]) - 1;
|
||||
__asm__ volatile("stfle %[facilities]\n" : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc");
|
||||
return is_bit_set((const char *)facilities, DFLTCC_FACILITY);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size)
|
||||
{
|
||||
struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + size);
|
||||
struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param;
|
||||
|
||||
/* Initialize available functions */
|
||||
if (is_dfltcc_enabled()) {
|
||||
dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL);
|
||||
memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af));
|
||||
} else
|
||||
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
|
||||
|
||||
/* Initialize parameter block */
|
||||
memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
|
||||
dfltcc_state->param.nt = 1;
|
||||
|
||||
/* Initialize tuning parameters */
|
||||
dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
|
||||
dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
|
||||
dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
|
||||
dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
|
||||
dfltcc_state->param.ribm = DFLTCC_RIBM;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size)
|
||||
{
|
||||
Assert((items * size) % 8 == 0,
|
||||
"The size of zlib-ng state must be a multiple of 8");
|
||||
return ZALLOC(strm, items * size + sizeof(struct dfltcc_state), sizeof(unsigned char));
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size)
|
||||
{
|
||||
memcpy(dst, src, size + sizeof(struct dfltcc_state));
|
||||
}
|
||||
|
||||
static const int PAGE_ALIGN = 0x1000;
|
||||
|
||||
#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size)
|
||||
{
|
||||
void *p;
|
||||
void *w;
|
||||
|
||||
/* To simplify freeing, we store the pointer to the allocated buffer right
|
||||
* before the window.
|
||||
*/
|
||||
p = ZALLOC(strm, sizeof(void *) + items * size + PAGE_ALIGN, sizeof(unsigned char));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
w = ALIGN_UP((char *)p + sizeof(void *), PAGE_ALIGN);
|
||||
*(void **)((char *)w - sizeof(void *)) = p;
|
||||
return w;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w)
|
||||
{
|
||||
if (w)
|
||||
ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *)));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef DFLTCC_COMMON_H
|
||||
#define DFLTCC_COMMON_H
|
||||
|
||||
#ifdef ZLIB_COMPAT
|
||||
#include "zlib.h"
|
||||
#else
|
||||
#include "zlib-ng.h"
|
||||
#endif
|
||||
#include "zutil.h"
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size);
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w);
|
||||
|
||||
#define ZALLOC_STATE dfltcc_alloc_state
|
||||
|
||||
#define ZFREE_STATE ZFREE
|
||||
|
||||
#define ZCOPY_STATE dfltcc_copy_state
|
||||
|
||||
#define ZALLOC_WINDOW dfltcc_alloc_window
|
||||
|
||||
#define ZFREE_WINDOW dfltcc_free_window
|
||||
|
||||
#define TRY_FREE_WINDOW dfltcc_free_window
|
||||
|
||||
#endif
|
||||
@@ -1,365 +0,0 @@
|
||||
/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL compression support. */
|
||||
|
||||
/*
|
||||
Use the following commands to build zlib-ng with DFLTCC compression support:
|
||||
|
||||
$ ./configure --with-dfltcc-deflate
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_DEFLATE=1 .
|
||||
|
||||
and then
|
||||
|
||||
$ make
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "deflate.h"
|
||||
#include "dfltcc_deflate.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
static inline int dfltcc_are_params_ok(int level, uInt window_bits, int strategy, uint16_t level_mask)
|
||||
{
|
||||
return (level_mask & ((uint16_t)1 << level)) != 0 &&
|
||||
(window_bits == HB_BITS) &&
|
||||
(strategy == Z_FIXED || strategy == Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
/* Unsupported compression settings */
|
||||
if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy, dfltcc_state->level_mask))
|
||||
return 0;
|
||||
|
||||
/* Unsupported hardware */
|
||||
if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
|
||||
!is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
|
||||
!is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void dfltcc_gdht(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
|
||||
dfltcc(DFLTCC_GDHT, param, NULL, NULL, &strm->next_in, &avail_in, NULL);
|
||||
}
|
||||
|
||||
static inline dfltcc_cc dfltcc_cmpr(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
size_t avail_out = strm->avail_out;
|
||||
dfltcc_cc cc;
|
||||
|
||||
cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
|
||||
param, &strm->next_out, &avail_out,
|
||||
&strm->next_in, &avail_in, state->window);
|
||||
strm->total_in += (strm->avail_in - avail_in);
|
||||
strm->total_out += (strm->avail_out - avail_out);
|
||||
strm->avail_in = avail_in;
|
||||
strm->avail_out = avail_out;
|
||||
return cc;
|
||||
}
|
||||
|
||||
static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 *param)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
|
||||
send_bits(state, bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), param->eobl);
|
||||
flush_pending(strm);
|
||||
if (state->pending != 0) {
|
||||
/* The remaining data is located in pending_out[0:pending]. If someone
|
||||
* calls put_byte() - this might happen in deflate() - the byte will be
|
||||
* placed into pending_buf[pending], which is incorrect. Move the
|
||||
* remaining data to the beginning of pending_buf so that put_byte() is
|
||||
* usable again.
|
||||
*/
|
||||
memmove(state->pending_buf, state->pending_out, state->pending);
|
||||
state->pending_out = state->pending_buf;
|
||||
}
|
||||
#ifdef ZLIB_DEBUG
|
||||
state->compressed_len += param->eobl;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
uInt masked_avail_in;
|
||||
dfltcc_cc cc;
|
||||
int need_empty_block;
|
||||
int soft_bcc;
|
||||
int no_flush;
|
||||
|
||||
if (!dfltcc_can_deflate(strm))
|
||||
return 0;
|
||||
|
||||
again:
|
||||
masked_avail_in = 0;
|
||||
soft_bcc = 0;
|
||||
no_flush = flush == Z_NO_FLUSH;
|
||||
|
||||
/* Trailing empty block. Switch to software, except when Continuation Flag
|
||||
* is set, which means that DFLTCC has buffered some output in the
|
||||
* parameter block and needs to be called again in order to flush it.
|
||||
*/
|
||||
if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
|
||||
if (param->bcf) {
|
||||
/* A block is still open, and the hardware does not support closing
|
||||
* blocks without adding data. Thus, close it manually.
|
||||
*/
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strm->avail_in == 0 && !param->cf) {
|
||||
*result = need_more;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* There is an open non-BFINAL block, we are not going to close it just
|
||||
* yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
|
||||
* more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
|
||||
* DHT in order to adapt to a possibly changed input data distribution.
|
||||
*/
|
||||
if (param->bcf && no_flush &&
|
||||
strm->total_in > dfltcc_state->block_threshold &&
|
||||
strm->avail_in >= dfltcc_state->dht_threshold) {
|
||||
if (param->cf) {
|
||||
/* We need to flush the DFLTCC buffer before writing the
|
||||
* End-of-block Symbol. Mask the input data and proceed as usual.
|
||||
*/
|
||||
masked_avail_in += strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
no_flush = 0;
|
||||
} else {
|
||||
/* DFLTCC buffer is empty, so we can manually write the
|
||||
* End-of-block Symbol right away.
|
||||
*/
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size;
|
||||
if (strm->avail_out == 0) {
|
||||
*result = need_more;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The caller gave us too much data. Pass only one block worth of
|
||||
* uncompressed data to DFLTCC and mask the rest, so that on the next
|
||||
* iteration we start a new block.
|
||||
*/
|
||||
if (no_flush && strm->avail_in > dfltcc_state->block_size) {
|
||||
masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
|
||||
strm->avail_in = dfltcc_state->block_size;
|
||||
}
|
||||
|
||||
/* When we have an open non-BFINAL deflate block and caller indicates that
|
||||
* the stream is ending, we need to close an open deflate block and open a
|
||||
* BFINAL one.
|
||||
*/
|
||||
need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
|
||||
|
||||
/* Translate stream to parameter block */
|
||||
param->cvt = state->wrap == 2 ? CVT_CRC32 : CVT_ADLER32;
|
||||
if (!no_flush)
|
||||
/* We need to close a block. Always do this in software - when there is
|
||||
* no input data, the hardware will not nohor BCC. */
|
||||
soft_bcc = 1;
|
||||
if (flush == Z_FINISH && !param->bcf)
|
||||
/* We are about to open a BFINAL block, set Block Header Final bit
|
||||
* until the stream ends.
|
||||
*/
|
||||
param->bhf = 1;
|
||||
/* DFLTCC-CMPR will write to next_out, so make sure that buffers with
|
||||
* higher precedence are empty.
|
||||
*/
|
||||
Assert(state->pending == 0, "There must be no pending bytes");
|
||||
Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
|
||||
param->sbb = (unsigned int)state->bi_valid;
|
||||
if (param->sbb > 0)
|
||||
*strm->next_out = (unsigned char)state->bi_buf;
|
||||
if (param->hl)
|
||||
param->nt = 0; /* Honor history */
|
||||
param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler;
|
||||
|
||||
/* When opening a block, choose a Huffman-Table Type */
|
||||
if (!param->bcf) {
|
||||
if (state->strategy == Z_FIXED || (strm->total_in == 0 && dfltcc_state->block_threshold > 0))
|
||||
param->htt = HTT_FIXED;
|
||||
else {
|
||||
param->htt = HTT_DYNAMIC;
|
||||
dfltcc_gdht(strm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deflate */
|
||||
do {
|
||||
cc = dfltcc_cmpr(strm);
|
||||
if (strm->avail_in < 4096 && masked_avail_in > 0)
|
||||
/* We are about to call DFLTCC with a small input buffer, which is
|
||||
* inefficient. Since there is masked data, there will be at least
|
||||
* one more DFLTCC call, so skip the current one and make the next
|
||||
* one handle more data.
|
||||
*/
|
||||
break;
|
||||
} while (cc == DFLTCC_CC_AGAIN);
|
||||
|
||||
/* Translate parameter block to stream */
|
||||
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
|
||||
state->bi_valid = param->sbb;
|
||||
if (state->bi_valid == 0)
|
||||
state->bi_buf = 0; /* Avoid accessing next_out */
|
||||
else
|
||||
state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
|
||||
strm->adler = state->wrap == 2 ? ZSWAP32(param->cv) : param->cv;
|
||||
|
||||
/* Unmask the input data */
|
||||
strm->avail_in += masked_avail_in;
|
||||
masked_avail_in = 0;
|
||||
|
||||
/* If we encounter an error, it means there is a bug in DFLTCC call */
|
||||
Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
|
||||
|
||||
/* Update Block-Continuation Flag. It will be used to check whether to call
|
||||
* GDHT the next time.
|
||||
*/
|
||||
if (cc == DFLTCC_CC_OK) {
|
||||
if (soft_bcc) {
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size;
|
||||
} else
|
||||
param->bcf = 1;
|
||||
if (flush == Z_FINISH) {
|
||||
if (need_empty_block)
|
||||
/* Make the current deflate() call also close the stream */
|
||||
return 0;
|
||||
else {
|
||||
bi_windup(state);
|
||||
*result = finish_done;
|
||||
}
|
||||
} else {
|
||||
if (flush == Z_FULL_FLUSH)
|
||||
param->hl = 0; /* Clear history */
|
||||
*result = flush == Z_NO_FLUSH ? need_more : block_done;
|
||||
}
|
||||
} else {
|
||||
param->bcf = 1;
|
||||
*result = need_more;
|
||||
}
|
||||
if (strm->avail_in != 0 && strm->avail_out != 0)
|
||||
goto again; /* deflate() must use all input or all output */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Switching between hardware and software compression.
|
||||
|
||||
DFLTCC does not support all zlib settings, e.g. generation of non-compressed
|
||||
blocks or alternative window sizes. When such settings are applied on the
|
||||
fly with deflateParams, we need to convert between hardware and software
|
||||
window formats.
|
||||
*/
|
||||
int ZLIB_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
int could_deflate = dfltcc_can_deflate(strm);
|
||||
int can_deflate = dfltcc_are_params_ok(level, state->w_bits, strategy, dfltcc_state->level_mask);
|
||||
|
||||
if (can_deflate == could_deflate)
|
||||
/* We continue to work in the same mode - no changes needed */
|
||||
return Z_OK;
|
||||
|
||||
if (strm->total_in == 0 && param->nt == 1 && param->hl == 0)
|
||||
/* DFLTCC was not used yet - no changes needed */
|
||||
return Z_OK;
|
||||
|
||||
/* Switching between hardware and software is not implemented */
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
Preloading history.
|
||||
*/
|
||||
static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count)
|
||||
{
|
||||
size_t offset;
|
||||
size_t n;
|
||||
|
||||
/* Do not use more than 32K */
|
||||
if (count > HB_SIZE) {
|
||||
buf += count - HB_SIZE;
|
||||
count = HB_SIZE;
|
||||
}
|
||||
offset = (param->ho + param->hl) % HB_SIZE;
|
||||
if (offset + count <= HB_SIZE)
|
||||
/* Circular history buffer does not wrap - copy one chunk */
|
||||
memcpy(history + offset, buf, count);
|
||||
else {
|
||||
/* Circular history buffer wraps - copy two chunks */
|
||||
n = HB_SIZE - offset;
|
||||
memcpy(history + offset, buf, n);
|
||||
memcpy(history, buf + n, count - n);
|
||||
}
|
||||
n = param->hl + count;
|
||||
if (n <= HB_SIZE)
|
||||
/* All history fits into buffer - no need to discard anything */
|
||||
param->hl = n;
|
||||
else {
|
||||
/* History does not fit into buffer - discard extra bytes */
|
||||
param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE;
|
||||
param->hl = HB_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm,
|
||||
const unsigned char *dictionary, uInt dict_length)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
|
||||
append_history(param, state->window, dictionary, dict_length);
|
||||
state->strstart = 1; /* Add FDICT to zlib header */
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
|
||||
if (dictionary) {
|
||||
if (param->ho + param->hl <= HB_SIZE)
|
||||
/* Circular history buffer does not wrap - copy one chunk */
|
||||
memcpy(dictionary, state->window + param->ho, param->hl);
|
||||
else {
|
||||
/* Circular history buffer wraps - copy two chunks */
|
||||
memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho);
|
||||
memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE);
|
||||
}
|
||||
}
|
||||
if (dict_length)
|
||||
*dict_length = param->hl;
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#ifndef DFLTCC_DEFLATE_H
|
||||
#define DFLTCC_DEFLATE_H
|
||||
|
||||
#include "dfltcc_common.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm);
|
||||
int ZLIB_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm,
|
||||
const unsigned char *dictionary, uInt dict_length);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length);
|
||||
|
||||
#define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
return dfltcc_deflate_set_dictionary((strm), (dict), (dict_len)); \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
return dfltcc_deflate_get_dictionary((strm), (dict), (dict_len)); \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_RESET_KEEP_HOOK(strm) \
|
||||
dfltcc_reset((strm), sizeof(deflate_state))
|
||||
|
||||
#define DEFLATE_PARAMS_HOOK(strm, level, strategy) \
|
||||
do { \
|
||||
int err; \
|
||||
\
|
||||
err = dfltcc_deflate_params((strm), (level), (strategy)); \
|
||||
if (err == Z_STREAM_ERROR) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
(complen) = (3 + 5 + 5 + 4 + 19 * 3 + (286 + 30) * 7 + \
|
||||
(source_len) * 16 + 15 + 7) >> 3; \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm)))
|
||||
|
||||
#define DEFLATE_HOOK dfltcc_deflate
|
||||
|
||||
#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
|
||||
|
||||
#endif
|
||||
@@ -1,201 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
#include <sys/sdt.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
Tuning parameters.
|
||||
*/
|
||||
#ifndef DFLTCC_LEVEL_MASK
|
||||
#define DFLTCC_LEVEL_MASK 0x2
|
||||
#endif
|
||||
#ifndef DFLTCC_BLOCK_SIZE
|
||||
#define DFLTCC_BLOCK_SIZE 1048576
|
||||
#endif
|
||||
#ifndef DFLTCC_FIRST_FHT_BLOCK_SIZE
|
||||
#define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096
|
||||
#endif
|
||||
#ifndef DFLTCC_DHT_MIN_SAMPLE_SIZE
|
||||
#define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096
|
||||
#endif
|
||||
#ifndef DFLTCC_RIBM
|
||||
#define DFLTCC_RIBM 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
C wrapper for the DEFLATE CONVERSION CALL instruction.
|
||||
*/
|
||||
typedef enum {
|
||||
DFLTCC_CC_OK = 0,
|
||||
DFLTCC_CC_OP1_TOO_SHORT = 1,
|
||||
DFLTCC_CC_OP2_TOO_SHORT = 2,
|
||||
DFLTCC_CC_OP2_CORRUPT = 2,
|
||||
DFLTCC_CC_AGAIN = 3,
|
||||
} dfltcc_cc;
|
||||
|
||||
#define DFLTCC_QAF 0
|
||||
#define DFLTCC_GDHT 1
|
||||
#define DFLTCC_CMPR 2
|
||||
#define DFLTCC_XPND 4
|
||||
#define HBT_CIRCULAR (1 << 7)
|
||||
#define HB_BITS 15
|
||||
#define HB_SIZE (1 << HB_BITS)
|
||||
#define DFLTCC_FACILITY 151
|
||||
|
||||
static inline dfltcc_cc dfltcc(int fn, void *param,
|
||||
unsigned char **op1, size_t *len1, const unsigned char **op2, size_t *len2, void *hist)
|
||||
{
|
||||
unsigned char *t2 = op1 ? *op1 : NULL;
|
||||
size_t t3 = len1 ? *len1 : 0;
|
||||
const unsigned char *t4 = op2 ? *op2 : NULL;
|
||||
size_t t5 = len2 ? *len2 : 0;
|
||||
register int r0 __asm__("r0") = fn;
|
||||
register void *r1 __asm__("r1") = param;
|
||||
register unsigned char *r2 __asm__("r2") = t2;
|
||||
register size_t r3 __asm__("r3") = t3;
|
||||
register const unsigned char *r4 __asm__("r4") = t4;
|
||||
register size_t r5 __asm__("r5") = t5;
|
||||
int cc;
|
||||
|
||||
__asm__ volatile(
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5))
|
||||
#endif
|
||||
".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5))
|
||||
#endif
|
||||
"ipm %[cc]\n"
|
||||
: [r2] "+r" (r2)
|
||||
, [r3] "+r" (r3)
|
||||
, [r4] "+r" (r4)
|
||||
, [r5] "+r" (r5)
|
||||
, [cc] "=r" (cc)
|
||||
: [r0] "r" (r0)
|
||||
, [r1] "r" (r1)
|
||||
, [hist] "r" (hist)
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
, STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist)
|
||||
#endif
|
||||
: "cc", "memory");
|
||||
t2 = r2; t3 = r3; t4 = r4; t5 = r5;
|
||||
|
||||
if (op1)
|
||||
*op1 = t2;
|
||||
if (len1)
|
||||
*len1 = t3;
|
||||
if (op2)
|
||||
*op2 = t4;
|
||||
if (len2)
|
||||
*len2 = t5;
|
||||
return (cc >> 28) & 3;
|
||||
}
|
||||
|
||||
/*
|
||||
Parameter Block for Query Available Functions.
|
||||
*/
|
||||
#define static_assert(c, msg) __attribute__((unused)) static char static_assert_failed_ ## msg[c ? 1 : -1]
|
||||
|
||||
struct dfltcc_qaf_param {
|
||||
char fns[16];
|
||||
char reserved1[8];
|
||||
char fmts[2];
|
||||
char reserved2[6];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct dfltcc_qaf_param) == 32, sizeof_struct_dfltcc_qaf_param_is_32);
|
||||
|
||||
static inline int is_bit_set(const char *bits, int n)
|
||||
{
|
||||
return bits[n / 8] & (1 << (7 - (n % 8)));
|
||||
}
|
||||
|
||||
static inline void clear_bit(char *bits, int n)
|
||||
{
|
||||
bits[n / 8] &= ~(1 << (7 - (n % 8)));
|
||||
}
|
||||
|
||||
#define DFLTCC_FMT0 0
|
||||
|
||||
/*
|
||||
Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand.
|
||||
*/
|
||||
#define CVT_CRC32 0
|
||||
#define CVT_ADLER32 1
|
||||
#define HTT_FIXED 0
|
||||
#define HTT_DYNAMIC 1
|
||||
|
||||
struct dfltcc_param_v0 {
|
||||
uint16_t pbvn; /* Parameter-Block-Version Number */
|
||||
uint8_t mvn; /* Model-Version Number */
|
||||
uint8_t ribm; /* Reserved for IBM use */
|
||||
uint32_t reserved32 : 31;
|
||||
uint32_t cf : 1; /* Continuation Flag */
|
||||
uint8_t reserved64[8];
|
||||
uint32_t nt : 1; /* New Task */
|
||||
uint32_t reserved129 : 1;
|
||||
uint32_t cvt : 1; /* Check Value Type */
|
||||
uint32_t reserved131 : 1;
|
||||
uint32_t htt : 1; /* Huffman-Table Type */
|
||||
uint32_t bcf : 1; /* Block-Continuation Flag */
|
||||
uint32_t bcc : 1; /* Block Closing Control */
|
||||
uint32_t bhf : 1; /* Block Header Final */
|
||||
uint32_t reserved136 : 1;
|
||||
uint32_t reserved137 : 1;
|
||||
uint32_t dhtgc : 1; /* DHT Generation Control */
|
||||
uint32_t reserved139 : 5;
|
||||
uint32_t reserved144 : 5;
|
||||
uint32_t sbb : 3; /* Sub-Byte Boundary */
|
||||
uint8_t oesc; /* Operation-Ending-Supplemental Code */
|
||||
uint32_t reserved160 : 12;
|
||||
uint32_t ifs : 4; /* Incomplete-Function Status */
|
||||
uint16_t ifl; /* Incomplete-Function Length */
|
||||
uint8_t reserved192[8];
|
||||
uint8_t reserved256[8];
|
||||
uint8_t reserved320[4];
|
||||
uint16_t hl; /* History Length */
|
||||
uint32_t reserved368 : 1;
|
||||
uint16_t ho : 15; /* History Offset */
|
||||
uint32_t cv; /* Check Value */
|
||||
uint32_t eobs : 15; /* End-of-block Symbol */
|
||||
uint32_t reserved431: 1;
|
||||
uint8_t eobl : 4; /* End-of-block Length */
|
||||
uint32_t reserved436 : 12;
|
||||
uint32_t reserved448 : 4;
|
||||
uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table
|
||||
Length */
|
||||
uint8_t reserved464[6];
|
||||
uint8_t cdht[288];
|
||||
uint8_t reserved[32];
|
||||
uint8_t csb[1152];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct dfltcc_param_v0) == 1536, sizeof_struct_dfltcc_param_v0_is_1536);
|
||||
|
||||
static inline const char *oesc_msg(char *buf, int oesc)
|
||||
{
|
||||
if (oesc == 0x00)
|
||||
return NULL; /* Successful completion */
|
||||
else {
|
||||
sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Extension of inflate_state and deflate_state. Must be doubleword-aligned.
|
||||
*/
|
||||
struct dfltcc_state {
|
||||
struct dfltcc_param_v0 param; /* Parameter block. */
|
||||
struct dfltcc_qaf_param af; /* Available functions. */
|
||||
uint16_t level_mask; /* Levels on which to use DFLTCC */
|
||||
uint32_t block_size; /* New block each X bytes */
|
||||
size_t block_threshold; /* New block after total_in > X */
|
||||
uint32_t dht_threshold; /* New block only if avail_in >= X */
|
||||
char msg[64]; /* Buffer for strm->msg */
|
||||
};
|
||||
|
||||
#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((state) + 1))
|
||||
@@ -1,142 +0,0 @@
|
||||
/* dfltcc_inflate.c - IBM Z DEFLATE CONVERSION CALL decompression support. */
|
||||
|
||||
/*
|
||||
Use the following commands to build zlib-ng with DFLTCC decompression support:
|
||||
|
||||
$ ./configure --with-dfltcc-inflate
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_INFLATE=1 .
|
||||
|
||||
and then
|
||||
|
||||
$ make
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "dfltcc_inflate.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
/* Unsupported compression settings */
|
||||
if (state->wbits != HB_BITS)
|
||||
return 0;
|
||||
|
||||
/* Unsupported hardware */
|
||||
return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
|
||||
}
|
||||
|
||||
static inline dfltcc_cc dfltcc_xpnd(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
size_t avail_out = strm->avail_out;
|
||||
dfltcc_cc cc;
|
||||
|
||||
cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
|
||||
param, &strm->next_out, &avail_out,
|
||||
&strm->next_in, &avail_in, state->window);
|
||||
strm->avail_in = avail_in;
|
||||
strm->avail_out = avail_out;
|
||||
return cc;
|
||||
}
|
||||
|
||||
dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
dfltcc_cc cc;
|
||||
|
||||
if (flush == Z_BLOCK || flush == Z_TREES) {
|
||||
/* DFLTCC does not support stopping on block boundaries */
|
||||
if (dfltcc_inflate_disable(strm)) {
|
||||
*ret = Z_STREAM_ERROR;
|
||||
return DFLTCC_INFLATE_BREAK;
|
||||
} else
|
||||
return DFLTCC_INFLATE_SOFTWARE;
|
||||
}
|
||||
|
||||
if (state->last) {
|
||||
if (state->bits != 0) {
|
||||
strm->next_in++;
|
||||
strm->avail_in--;
|
||||
state->bits = 0;
|
||||
}
|
||||
state->mode = CHECK;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
if (strm->avail_in == 0 && !param->cf)
|
||||
return DFLTCC_INFLATE_BREAK;
|
||||
|
||||
if (inflate_ensure_window(state)) {
|
||||
state->mode = MEM;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
/* Translate stream to parameter block */
|
||||
param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32;
|
||||
param->sbb = state->bits;
|
||||
param->hl = state->whave; /* Software and hardware history formats match */
|
||||
param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1);
|
||||
if (param->hl)
|
||||
param->nt = 0; /* Honor history for the first block */
|
||||
param->cv = state->flags ? ZSWAP32(state->check) : state->check;
|
||||
|
||||
/* Inflate */
|
||||
do {
|
||||
cc = dfltcc_xpnd(strm);
|
||||
} while (cc == DFLTCC_CC_AGAIN);
|
||||
|
||||
/* Translate parameter block to stream */
|
||||
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
|
||||
state->last = cc == DFLTCC_CC_OK;
|
||||
state->bits = param->sbb;
|
||||
state->whave = param->hl;
|
||||
state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
|
||||
state->check = state->flags ? ZSWAP32(param->cv) : param->cv;
|
||||
if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
|
||||
/* Report an error if stream is corrupted */
|
||||
state->mode = BAD;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
state->mode = TYPEDO;
|
||||
/* Break if operands are exhausted, otherwise continue looping */
|
||||
return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
|
||||
DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
|
||||
return !param->nt;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
if (!dfltcc_can_inflate(strm))
|
||||
return 0;
|
||||
if (dfltcc_was_inflate_used(strm))
|
||||
/* DFLTCC has already decompressed some data. Since there is not
|
||||
* enough information to resume decompression in software, the call
|
||||
* must fail.
|
||||
*/
|
||||
return 1;
|
||||
/* DFLTCC was not used yet - decompress in software */
|
||||
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef DFLTCC_INFLATE_H
|
||||
#define DFLTCC_INFLATE_H
|
||||
|
||||
#include "dfltcc_common.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm);
|
||||
typedef enum {
|
||||
DFLTCC_INFLATE_CONTINUE,
|
||||
DFLTCC_INFLATE_BREAK,
|
||||
DFLTCC_INFLATE_SOFTWARE,
|
||||
} dfltcc_inflate_action;
|
||||
dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret);
|
||||
int ZLIB_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm);
|
||||
int ZLIB_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm);
|
||||
|
||||
#define INFLATE_RESET_KEEP_HOOK(strm) \
|
||||
dfltcc_reset((strm), sizeof(struct inflate_state))
|
||||
|
||||
#define INFLATE_PRIME_HOOK(strm, bits, value) \
|
||||
do { if (dfltcc_inflate_disable((strm))) return Z_STREAM_ERROR; } while (0)
|
||||
|
||||
#define INFLATE_TYPEDO_HOOK(strm, flush) \
|
||||
if (dfltcc_can_inflate((strm))) { \
|
||||
dfltcc_inflate_action action; \
|
||||
\
|
||||
RESTORE(); \
|
||||
action = dfltcc_inflate((strm), (flush), &ret); \
|
||||
LOAD(); \
|
||||
if (action == DFLTCC_INFLATE_CONTINUE) \
|
||||
break; \
|
||||
else if (action == DFLTCC_INFLATE_BREAK) \
|
||||
goto inf_leave; \
|
||||
}
|
||||
|
||||
#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
|
||||
|
||||
#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
|
||||
|
||||
#define INFLATE_MARK_HOOK(strm) \
|
||||
do { \
|
||||
if (dfltcc_was_inflate_used((strm))) return -(1L << 16); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
fill_window_sse.c SSE2 optimized fill_window
|
||||
deflate_quick.c SSE4 optimized deflate strategy for use as level 1
|
||||
crc_folding.c SSE4 + PCLMULQDQ optimized CRC folding implementation
|
||||
@@ -1,58 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
CC=
|
||||
CFLAGS=
|
||||
SFLAGS=
|
||||
INCLUDES=
|
||||
SUFFIX=
|
||||
|
||||
SSE2FLAG=-msse2
|
||||
SSE4FLAG=-msse4
|
||||
PCLMULFLAG=-mpclmul
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
all: x86.o x86.lo fill_window_sse.o fill_window_sse.lo deflate_quick.o deflate_quick.lo insert_string_sse.o insert_string_sse.lo crc_folding.o crc_folding.lo
|
||||
|
||||
x86.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c
|
||||
|
||||
x86.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c
|
||||
|
||||
fill_window_sse.o:
|
||||
$(CC) $(CFLAGS) $(SSE2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_sse.c
|
||||
|
||||
fill_window_sse.lo:
|
||||
$(CC) $(SFLAGS) $(SSE2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_sse.c
|
||||
|
||||
deflate_quick.o:
|
||||
$(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/deflate_quick.c
|
||||
|
||||
deflate_quick.lo:
|
||||
$(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/deflate_quick.c
|
||||
|
||||
insert_string_sse.o:
|
||||
$(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c
|
||||
|
||||
insert_string_sse.lo:
|
||||
$(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c
|
||||
|
||||
crc_folding.o:
|
||||
$(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c
|
||||
|
||||
crc_folding.lo:
|
||||
$(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
|
||||
distclean:
|
||||
rm -f Makefile
|
||||
@@ -1,450 +0,0 @@
|
||||
/*
|
||||
* Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
||||
* instruction.
|
||||
*
|
||||
* A white paper describing this algorithm can be found at:
|
||||
* http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
* Authors:
|
||||
* Wajdi Feghali <wajdi.k.feghali@intel.com>
|
||||
* Jim Guilford <james.guilford@intel.com>
|
||||
* Vinodh Gopal <vinodh.gopal@intel.com>
|
||||
* Erdinc Ozturk <erdinc.ozturk@intel.com>
|
||||
* Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef X86_PCLMULQDQ_CRC
|
||||
|
||||
#include "zbuild.h"
|
||||
#include <inttypes.h>
|
||||
#include <immintrin.h>
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#include "crc_folding.h"
|
||||
|
||||
ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) {
|
||||
/* CRC_SAVE */
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 0, _mm_cvtsi32_si128(0x9db42487));
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 1, _mm_setzero_si128());
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 2, _mm_setzero_si128());
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 3, _mm_setzero_si128());
|
||||
|
||||
s->strm->adler = 0;
|
||||
}
|
||||
|
||||
static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
||||
const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4,
|
||||
0x00000001, 0xc6e41596);
|
||||
__m128i x_tmp3;
|
||||
__m128 ps_crc0, ps_crc3, ps_res;
|
||||
|
||||
x_tmp3 = *xmm_crc3;
|
||||
|
||||
*xmm_crc3 = *xmm_crc0;
|
||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
||||
ps_res = _mm_xor_ps(ps_crc0, ps_crc3);
|
||||
|
||||
*xmm_crc0 = *xmm_crc1;
|
||||
*xmm_crc1 = *xmm_crc2;
|
||||
*xmm_crc2 = x_tmp3;
|
||||
*xmm_crc3 = _mm_castps_si128(ps_res);
|
||||
}
|
||||
|
||||
static void fold_2(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
||||
const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4,
|
||||
0x00000001, 0xc6e41596);
|
||||
__m128i x_tmp3, x_tmp2;
|
||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20;
|
||||
|
||||
x_tmp3 = *xmm_crc3;
|
||||
x_tmp2 = *xmm_crc2;
|
||||
|
||||
*xmm_crc3 = *xmm_crc1;
|
||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
||||
ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1);
|
||||
|
||||
*xmm_crc2 = *xmm_crc0;
|
||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
|
||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
||||
ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2);
|
||||
|
||||
*xmm_crc0 = x_tmp2;
|
||||
*xmm_crc1 = x_tmp3;
|
||||
*xmm_crc2 = _mm_castps_si128(ps_res20);
|
||||
*xmm_crc3 = _mm_castps_si128(ps_res31);
|
||||
}
|
||||
|
||||
static void fold_3(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
||||
const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4,
|
||||
0x00000001, 0xc6e41596);
|
||||
__m128i x_tmp3;
|
||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10;
|
||||
|
||||
x_tmp3 = *xmm_crc3;
|
||||
|
||||
*xmm_crc3 = *xmm_crc2;
|
||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
|
||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
||||
ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3);
|
||||
|
||||
*xmm_crc2 = *xmm_crc1;
|
||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
|
||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
||||
ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2);
|
||||
|
||||
*xmm_crc1 = *xmm_crc0;
|
||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10);
|
||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
||||
ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1);
|
||||
|
||||
*xmm_crc0 = x_tmp3;
|
||||
*xmm_crc1 = _mm_castps_si128(ps_res10);
|
||||
*xmm_crc2 = _mm_castps_si128(ps_res21);
|
||||
*xmm_crc3 = _mm_castps_si128(ps_res32);
|
||||
}
|
||||
|
||||
static void fold_4(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
||||
const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4,
|
||||
0x00000001, 0xc6e41596);
|
||||
__m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3;
|
||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3;
|
||||
__m128 ps_t0, ps_t1, ps_t2, ps_t3;
|
||||
__m128 ps_res0, ps_res1, ps_res2, ps_res3;
|
||||
|
||||
x_tmp0 = *xmm_crc0;
|
||||
x_tmp1 = *xmm_crc1;
|
||||
x_tmp2 = *xmm_crc2;
|
||||
x_tmp3 = *xmm_crc3;
|
||||
|
||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
||||
x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10);
|
||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
||||
ps_t0 = _mm_castsi128_ps(x_tmp0);
|
||||
ps_res0 = _mm_xor_ps(ps_crc0, ps_t0);
|
||||
|
||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
||||
x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10);
|
||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
||||
ps_t1 = _mm_castsi128_ps(x_tmp1);
|
||||
ps_res1 = _mm_xor_ps(ps_crc1, ps_t1);
|
||||
|
||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
|
||||
x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10);
|
||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
||||
ps_t2 = _mm_castsi128_ps(x_tmp2);
|
||||
ps_res2 = _mm_xor_ps(ps_crc2, ps_t2);
|
||||
|
||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01);
|
||||
x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10);
|
||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
||||
ps_t3 = _mm_castsi128_ps(x_tmp3);
|
||||
ps_res3 = _mm_xor_ps(ps_crc3, ps_t3);
|
||||
|
||||
*xmm_crc0 = _mm_castps_si128(ps_res0);
|
||||
*xmm_crc1 = _mm_castps_si128(ps_res1);
|
||||
*xmm_crc2 = _mm_castps_si128(ps_res2);
|
||||
*xmm_crc3 = _mm_castps_si128(ps_res3);
|
||||
}
|
||||
|
||||
static const unsigned ALIGNED_(32) pshufb_shf_table[60] = {
|
||||
0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */
|
||||
0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */
|
||||
0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */
|
||||
0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */
|
||||
0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */
|
||||
0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */
|
||||
0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */
|
||||
0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */
|
||||
0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */
|
||||
0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/
|
||||
0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/
|
||||
0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/
|
||||
0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/
|
||||
0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/
|
||||
0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/
|
||||
};
|
||||
|
||||
static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2,
|
||||
__m128i *xmm_crc3, __m128i *xmm_crc_part) {
|
||||
|
||||
const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4,
|
||||
0x00000001, 0xc6e41596);
|
||||
const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080);
|
||||
|
||||
__m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3;
|
||||
__m128i xmm_a0_0, xmm_a0_1;
|
||||
__m128 ps_crc3, psa0_0, psa0_1, ps_res;
|
||||
|
||||
xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1));
|
||||
xmm_shr = xmm_shl;
|
||||
xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3);
|
||||
|
||||
xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl);
|
||||
|
||||
*xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr);
|
||||
xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl);
|
||||
*xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1);
|
||||
|
||||
*xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr);
|
||||
xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl);
|
||||
*xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2);
|
||||
|
||||
*xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr);
|
||||
xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl);
|
||||
*xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3);
|
||||
|
||||
*xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr);
|
||||
*xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl);
|
||||
*xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part);
|
||||
|
||||
xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10);
|
||||
xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01);
|
||||
|
||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
||||
psa0_0 = _mm_castsi128_ps(xmm_a0_0);
|
||||
psa0_1 = _mm_castsi128_ps(xmm_a0_1);
|
||||
|
||||
ps_res = _mm_xor_ps(ps_crc3, psa0_0);
|
||||
ps_res = _mm_xor_ps(ps_res, psa0_1);
|
||||
|
||||
*xmm_crc3 = _mm_castps_si128(ps_res);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const unsigned char *src, long len) {
|
||||
unsigned long algn_diff;
|
||||
__m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3;
|
||||
|
||||
/* CRC_LOAD */
|
||||
__m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);
|
||||
__m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);
|
||||
__m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);
|
||||
__m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);
|
||||
__m128i xmm_crc_part;
|
||||
|
||||
if (len < 16) {
|
||||
if (len == 0)
|
||||
return;
|
||||
xmm_crc_part = _mm_loadu_si128((__m128i *)src);
|
||||
goto partial;
|
||||
}
|
||||
|
||||
algn_diff = (0 - (uintptr_t)src) & 0xF;
|
||||
if (algn_diff) {
|
||||
xmm_crc_part = _mm_loadu_si128((__m128i *)src);
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_crc_part);
|
||||
|
||||
dst += algn_diff;
|
||||
src += algn_diff;
|
||||
len -= algn_diff;
|
||||
|
||||
partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part);
|
||||
}
|
||||
|
||||
while ((len -= 64) >= 0) {
|
||||
/* CRC_LOAD */
|
||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
||||
xmm_t2 = _mm_load_si128((__m128i *)src + 2);
|
||||
xmm_t3 = _mm_load_si128((__m128i *)src + 3);
|
||||
|
||||
fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
||||
|
||||
/* CRC_SAVE */
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
||||
_mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
|
||||
_mm_storeu_si128((__m128i *)dst + 3, xmm_t3);
|
||||
|
||||
xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0);
|
||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1);
|
||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3);
|
||||
|
||||
src += 64;
|
||||
dst += 64;
|
||||
}
|
||||
|
||||
/*
|
||||
* len = num bytes left - 64
|
||||
*/
|
||||
if (len + 16 >= 0) {
|
||||
len += 16;
|
||||
|
||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
||||
xmm_t2 = _mm_load_si128((__m128i *)src + 2);
|
||||
|
||||
fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
||||
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
||||
_mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
|
||||
|
||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0);
|
||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2);
|
||||
|
||||
if (len == 0)
|
||||
goto done;
|
||||
|
||||
dst += 48;
|
||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 3);
|
||||
} else if (len + 32 >= 0) {
|
||||
len += 32;
|
||||
|
||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
||||
|
||||
fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
||||
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
||||
|
||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1);
|
||||
|
||||
if (len == 0)
|
||||
goto done;
|
||||
|
||||
dst += 32;
|
||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 2);
|
||||
} else if (len + 48 >= 0) {
|
||||
len += 48;
|
||||
|
||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
||||
|
||||
fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
||||
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
||||
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0);
|
||||
|
||||
if (len == 0)
|
||||
goto done;
|
||||
|
||||
dst += 16;
|
||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 1);
|
||||
} else {
|
||||
len += 64;
|
||||
if (len == 0)
|
||||
goto done;
|
||||
xmm_crc_part = _mm_load_si128((__m128i *)src);
|
||||
}
|
||||
|
||||
partial:
|
||||
_mm_storeu_si128((__m128i *)dst, xmm_crc_part);
|
||||
partial_fold(len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part);
|
||||
done:
|
||||
/* CRC_SAVE */
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);
|
||||
_mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);
|
||||
}
|
||||
|
||||
static const unsigned ALIGNED_(16) crc_k[] = {
|
||||
0xccaa009e, 0x00000000, /* rk1 */
|
||||
0x751997d0, 0x00000001, /* rk2 */
|
||||
0xccaa009e, 0x00000000, /* rk5 */
|
||||
0x63cd6124, 0x00000001, /* rk6 */
|
||||
0xf7011640, 0x00000001, /* rk7 */
|
||||
0xdb710640, 0x00000001 /* rk8 */
|
||||
};
|
||||
|
||||
static const unsigned ALIGNED_(16) crc_mask[4] = {
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const unsigned ALIGNED_(16) crc_mask2[4] = {
|
||||
0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
uint32_t ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) {
|
||||
const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask);
|
||||
const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2);
|
||||
|
||||
uint32_t crc;
|
||||
__m128i x_tmp0, x_tmp1, x_tmp2, crc_fold;
|
||||
|
||||
/* CRC_LOAD */
|
||||
__m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);
|
||||
__m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);
|
||||
__m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);
|
||||
__m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);
|
||||
|
||||
/*
|
||||
* k1
|
||||
*/
|
||||
crc_fold = _mm_load_si128((__m128i *)crc_k);
|
||||
|
||||
x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10);
|
||||
xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01);
|
||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0);
|
||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0);
|
||||
|
||||
x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10);
|
||||
xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01);
|
||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1);
|
||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1);
|
||||
|
||||
x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10);
|
||||
xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
||||
|
||||
/*
|
||||
* k5
|
||||
*/
|
||||
crc_fold = _mm_load_si128((__m128i *)crc_k + 1);
|
||||
|
||||
xmm_crc0 = xmm_crc3;
|
||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
|
||||
xmm_crc0 = _mm_srli_si128(xmm_crc0, 8);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
|
||||
|
||||
xmm_crc0 = xmm_crc3;
|
||||
xmm_crc3 = _mm_slli_si128(xmm_crc3, 4);
|
||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
|
||||
xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2);
|
||||
|
||||
/*
|
||||
* k7
|
||||
*/
|
||||
xmm_crc1 = xmm_crc3;
|
||||
xmm_crc2 = xmm_crc3;
|
||||
crc_fold = _mm_load_si128((__m128i *)crc_k + 2);
|
||||
|
||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
||||
xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask);
|
||||
|
||||
xmm_crc2 = xmm_crc3;
|
||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1);
|
||||
|
||||
crc = _mm_extract_epi32(xmm_crc3, 2);
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/* crc_folding.h
|
||||
*
|
||||
* Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
||||
* instruction.
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation Jim Kukunas
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef CRC_FOLDING_H_
|
||||
#define CRC_FOLDING_H_
|
||||
|
||||
#include "deflate.h"
|
||||
|
||||
ZLIB_INTERNAL void crc_fold_init(deflate_state *const);
|
||||
ZLIB_INTERNAL uint32_t crc_fold_512to32(deflate_state *const);
|
||||
ZLIB_INTERNAL void crc_fold_copy(deflate_state *const, unsigned char *, const unsigned char *, long);
|
||||
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef X86_CTZL_H
|
||||
#define X86_CTZL_H
|
||||
|
||||
#include <intrin.h>
|
||||
#ifdef X86_CPUID
|
||||
# include "x86.h"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
/* This is not a general purpose replacement for __builtin_ctzl. The function expects that value is != 0
|
||||
* Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked
|
||||
*/
|
||||
static __forceinline unsigned long __builtin_ctzl(unsigned long value)
|
||||
{
|
||||
#ifdef X86_CPUID
|
||||
if (x86_cpu_has_tzcnt)
|
||||
return _tzcnt_u32(value);
|
||||
#endif
|
||||
unsigned long trailing_zero;
|
||||
_BitScanForward(&trailing_zero, value);
|
||||
return trailing_zero;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Fill Window with SSE2-optimized hash shifting
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation
|
||||
* Authors:
|
||||
* Arjan van de Ven <arjan@linux.intel.com>
|
||||
* Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
#ifdef X86_SSE2
|
||||
|
||||
#include "zbuild.h"
|
||||
#include <immintrin.h>
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "functable.h"
|
||||
|
||||
extern int read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size);
|
||||
|
||||
ZLIB_INTERNAL void fill_window_sse(deflate_state *s) {
|
||||
const __m128i xmm_wsize = _mm_set1_epi16(s->w_size);
|
||||
|
||||
register unsigned n;
|
||||
register Pos *p;
|
||||
unsigned more; /* Amount of free space at the end of the window. */
|
||||
unsigned int wsize = s->w_size;
|
||||
|
||||
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
|
||||
|
||||
do {
|
||||
more = (unsigned)(s->window_size -(unsigned long)s->lookahead -(unsigned long)s->strstart);
|
||||
|
||||
/* Deal with !@#$% 64K limit: */
|
||||
if (sizeof(int) <= 2) {
|
||||
if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
|
||||
more = wsize;
|
||||
|
||||
} else if (more == (unsigned)(-1)) {
|
||||
/* Very unlikely, but possible on 16 bit machine if
|
||||
* strstart == 0 && lookahead == 1 (input done a byte at time)
|
||||
*/
|
||||
more--;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the window is almost full and there is insufficient lookahead,
|
||||
* move the upper half to the lower one to make room in the upper half.
|
||||
*/
|
||||
if (s->strstart >= wsize+MAX_DIST(s)) {
|
||||
memcpy(s->window, s->window+wsize, (unsigned)wsize);
|
||||
s->match_start = (s->match_start >= wsize) ? s->match_start - wsize : 0;
|
||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
||||
s->block_start -= (long) wsize;
|
||||
|
||||
/* Slide the hash table (could be avoided with 32 bit values
|
||||
at the expense of memory usage). We slide even when level == 0
|
||||
to keep the hash table consistent if we switch back to level > 0
|
||||
later. (Using level 0 permanently is not an optimal usage of
|
||||
zlib, so we don't care about this pathological case.)
|
||||
*/
|
||||
n = s->hash_size;
|
||||
p = &s->head[n];
|
||||
p -= 8;
|
||||
do {
|
||||
__m128i value, result;
|
||||
|
||||
value = _mm_loadu_si128((__m128i *)p);
|
||||
result = _mm_subs_epu16(value, xmm_wsize);
|
||||
_mm_storeu_si128((__m128i *)p, result);
|
||||
|
||||
p -= 8;
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
|
||||
n = wsize;
|
||||
p = &s->prev[n];
|
||||
p -= 8;
|
||||
do {
|
||||
__m128i value, result;
|
||||
|
||||
value = _mm_loadu_si128((__m128i *)p);
|
||||
result = _mm_subs_epu16(value, xmm_wsize);
|
||||
_mm_storeu_si128((__m128i *)p, result);
|
||||
|
||||
p -= 8;
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
more += wsize;
|
||||
}
|
||||
if (s->strm->avail_in == 0) break;
|
||||
|
||||
/* If there was no sliding:
|
||||
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
|
||||
* more == window_size - lookahead - strstart
|
||||
* => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
|
||||
* => more >= window_size - 2*WSIZE + 2
|
||||
* In the BIG_MEM or MMAP case (not yet supported),
|
||||
* window_size == input_size + MIN_LOOKAHEAD &&
|
||||
* strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
|
||||
* Otherwise, window_size == 2*WSIZE so more >= 2.
|
||||
* If there was sliding, more >= WSIZE. So in all cases, more >= 2.
|
||||
*/
|
||||
Assert(more >= 2, "more < 2");
|
||||
|
||||
n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
|
||||
s->lookahead += n;
|
||||
|
||||
/* Initialize the hash value now that we have some input: */
|
||||
if (s->lookahead + s->insert >= MIN_MATCH) {
|
||||
unsigned int str = s->strstart - s->insert;
|
||||
s->ins_h = s->window[str];
|
||||
if (str >= 1)
|
||||
functable.insert_string(s, str + 2 - MIN_MATCH, 1);
|
||||
#if MIN_MATCH != 3
|
||||
#error Call insert_string() MIN_MATCH-3 more times
|
||||
while (s->insert) {
|
||||
functable.insert_string(s, str, 1);
|
||||
str++;
|
||||
s->insert--;
|
||||
if (s->lookahead + s->insert < MIN_MATCH)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
unsigned int count;
|
||||
if (unlikely(s->lookahead == 1)){
|
||||
count = s->insert - 1;
|
||||
}else{
|
||||
count = s->insert;
|
||||
}
|
||||
functable.insert_string(s, str, count);
|
||||
s->insert -= count;
|
||||
#endif
|
||||
}
|
||||
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
|
||||
* but this is not important since only literal bytes will be emitted.
|
||||
*/
|
||||
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
|
||||
|
||||
/* If the WIN_INIT bytes after the end of the current data have never been
|
||||
* written, then zero those bytes in order to avoid memory check reports of
|
||||
* the use of uninitialized (or uninitialised as Julian writes) bytes by
|
||||
* the longest match routines. Update the high water mark for the next
|
||||
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
|
||||
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
|
||||
*/
|
||||
if (s->high_water < s->window_size) {
|
||||
unsigned long curr = s->strstart + (unsigned long)(s->lookahead);
|
||||
unsigned long init;
|
||||
|
||||
if (s->high_water < curr) {
|
||||
/* Previous high water mark below current data -- zero WIN_INIT
|
||||
* bytes or up to end of window, whichever is less.
|
||||
*/
|
||||
init = s->window_size - curr;
|
||||
if (init > WIN_INIT)
|
||||
init = WIN_INIT;
|
||||
memset(s->window + curr, 0, (unsigned)init);
|
||||
s->high_water = curr + init;
|
||||
} else if (s->high_water < (unsigned long)curr + WIN_INIT) {
|
||||
/* High water mark at or above current data, but below current data
|
||||
* plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
|
||||
* to end of window, whichever is less.
|
||||
*/
|
||||
init = (unsigned long)curr + WIN_INIT - s->high_water;
|
||||
if (init > s->window_size - s->high_water)
|
||||
init = s->window_size - s->high_water;
|
||||
memset(s->window + s->high_water, 0, (unsigned)init);
|
||||
s->high_water += init;
|
||||
}
|
||||
}
|
||||
|
||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search");
|
||||
}
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
/* insert_string_sse -- insert_string variant using SSE4.2's CRC instructions
|
||||
*
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
|
||||
/* ===========================================================================
|
||||
* Insert string str in the dictionary and set match_head to the previous head
|
||||
* of the hash chain (the most recent string with same hash key). Return
|
||||
* the previous length of the hash chain.
|
||||
* IN assertion: all calls to to INSERT_STRING are made with consecutive
|
||||
* input characters and the first MIN_MATCH bytes of str are valid
|
||||
* (except for the last MIN_MATCH-1 bytes of the input file).
|
||||
*/
|
||||
#ifdef X86_SSE4_2_CRC_HASH
|
||||
ZLIB_INTERNAL Pos insert_string_sse(deflate_state *const s, const Pos str, unsigned int count) {
|
||||
Pos ret = 0;
|
||||
unsigned int idx;
|
||||
unsigned int *ip, val, h;
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
ip = (unsigned *)&s->window[str+idx];
|
||||
memcpy(&val, ip, sizeof(val));
|
||||
h = 0;
|
||||
|
||||
if (s->level >= TRIGGER_LEVEL)
|
||||
val &= 0xFFFFFF;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
h = _mm_crc32_u32(h, val);
|
||||
#elif defined(X86_SSE4_2_CRC_INTRIN)
|
||||
h = __builtin_ia32_crc32si(h, val);
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"crc32 %1,%0\n\t"
|
||||
: "+r" (h)
|
||||
: "r" (val)
|
||||
);
|
||||
#endif
|
||||
Pos head = s->head[h & s->hash_mask];
|
||||
if (head != str+idx) {
|
||||
s->prev[(str+idx) & s->w_mask] = head;
|
||||
s->head[h & s->hash_mask] = str+idx;
|
||||
if (idx == count-1)
|
||||
ret = head;
|
||||
} else if (idx == count - 1) {
|
||||
ret = str + idx;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* x86 feature check
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
* Author:
|
||||
* Jim Kukunas
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#else
|
||||
// Newer versions of GCC and clang come with cpuid.h
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
ZLIB_INTERNAL int x86_cpu_has_sse2;
|
||||
ZLIB_INTERNAL int x86_cpu_has_sse42;
|
||||
ZLIB_INTERNAL int x86_cpu_has_pclmulqdq;
|
||||
ZLIB_INTERNAL int x86_cpu_has_tzcnt;
|
||||
|
||||
static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
|
||||
#ifdef _MSC_VER
|
||||
unsigned int registers[4];
|
||||
__cpuid(registers, info);
|
||||
|
||||
*eax = registers[0];
|
||||
*ebx = registers[1];
|
||||
*ecx = registers[2];
|
||||
*edx = registers[3];
|
||||
#else
|
||||
unsigned int _eax;
|
||||
unsigned int _ebx;
|
||||
unsigned int _ecx;
|
||||
unsigned int _edx;
|
||||
__cpuid(info, _eax, _ebx, _ecx, _edx);
|
||||
*eax = _eax;
|
||||
*ebx = _ebx;
|
||||
*ecx = _ecx;
|
||||
*edx = _edx;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL x86_check_features(void) {
|
||||
unsigned eax, ebx, ecx, edx;
|
||||
unsigned maxbasic;
|
||||
|
||||
cpuid(0, &maxbasic, &ebx, &ecx, &edx);
|
||||
|
||||
cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
x86_cpu_has_sse2 = edx & 0x4000000;
|
||||
x86_cpu_has_sse42 = ecx & 0x100000;
|
||||
x86_cpu_has_pclmulqdq = ecx & 0x2;
|
||||
|
||||
if (maxbasic >= 7) {
|
||||
cpuid(7, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
// check BMI1 bit
|
||||
// Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf
|
||||
x86_cpu_has_tzcnt = ebx & 0x8;
|
||||
} else {
|
||||
x86_cpu_has_tzcnt = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/* cpu.h -- check for CPU features
|
||||
* Copyright (C) 2013 Intel Corporation Jim Kukunas
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef CPU_H_
|
||||
#define CPU_H_
|
||||
|
||||
extern int x86_cpu_has_sse2;
|
||||
extern int x86_cpu_has_sse42;
|
||||
extern int x86_cpu_has_pclmulqdq;
|
||||
extern int x86_cpu_has_tzcnt;
|
||||
|
||||
void ZLIB_INTERNAL x86_check_features(void);
|
||||
|
||||
#endif /* CPU_H_ */
|
||||
@@ -1,79 +0,0 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zbuild.h"
|
||||
#if defined(ZLIB_COMPAT)
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT PREFIX(compress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source,
|
||||
z_size_t sourceLen, int level) {
|
||||
PREFIX3(stream) stream;
|
||||
int err;
|
||||
const unsigned int max = (unsigned int)-1;
|
||||
z_size_t left;
|
||||
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = NULL;
|
||||
stream.zfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
err = PREFIX(deflateInit)(&stream, level);
|
||||
if (err != Z_OK)
|
||||
return err;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
stream.next_in = (const unsigned char *)source;
|
||||
stream.avail_in = 0;
|
||||
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = sourceLen > (unsigned long)max ? max : (unsigned int)sourceLen;
|
||||
sourceLen -= stream.avail_in;
|
||||
}
|
||||
err = PREFIX(deflate)(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = (z_size_t)stream.total_out;
|
||||
PREFIX(deflateEnd)(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) {
|
||||
return PREFIX(compress2)(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
z_size_t ZEXPORT PREFIX(compressBound)(z_size_t sourceLen) {
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
|
||||
}
|
||||
Vendored
-1503
File diff suppressed because it is too large
Load Diff
@@ -1,498 +0,0 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
# include "zbuild.h"
|
||||
# include "gzendian.h"
|
||||
# include <inttypes.h>
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. A main()
|
||||
routine is also produced, so that this one source file can be compiled to an
|
||||
executable.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "deflate.h"
|
||||
#include "functable.h"
|
||||
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
static uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec);
|
||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2);
|
||||
static void crc32_combine_gen_(uint32_t *op, z_off64_t len2);
|
||||
|
||||
/* ========================================================================= */
|
||||
static uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) {
|
||||
uint32_t sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
volatile int crc_table_empty = 1;
|
||||
static uint32_t crc_table[8][256];
|
||||
static uint32_t crc_comb[GF2_DIM][GF2_DIM];
|
||||
void make_crc_table(void);
|
||||
static void gf2_matrix_square(uint32_t *square, const uint32_t *mat);
|
||||
#ifdef MAKECRCH
|
||||
static void write_table(FILE *, const uint32_t *, int);
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
/* ========================================================================= */
|
||||
static void gf2_matrix_square(uint32_t *square, const uint32_t *mat) {
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
void make_crc_table() {
|
||||
uint32_t c;
|
||||
int n, k;
|
||||
uint32_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320) */
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (uint32_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (uint32_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* generate zero operators table for crc32_combine() */
|
||||
|
||||
/* generate the operator to apply a single zero bit to a CRC -- the
|
||||
first row adds the polynomial if the low bit is a 1, and the
|
||||
remaining rows shift the CRC right one bit */
|
||||
k = GF2_DIM - 3;
|
||||
crc_comb[k][0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
uint32_t row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
crc_comb[k][n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* generate operators that apply 2, 4, and 8 zeros to a CRC, putting
|
||||
the last one, the operator for one zero byte, at the 0 position */
|
||||
gf2_matrix_square(crc_comb[k + 1], crc_comb[k]);
|
||||
gf2_matrix_square(crc_comb[k + 2], crc_comb[k + 1]);
|
||||
gf2_matrix_square(crc_comb[0], crc_comb[k + 2]);
|
||||
|
||||
/* generate operators for applying 2^n zero bytes to a CRC, filling out
|
||||
the remainder of the table -- the operators repeat after GF2_DIM
|
||||
values of n, so the table only needs GF2_DIM entries, regardless of
|
||||
the size of the length being processed */
|
||||
for (n = 1; n < k; n++)
|
||||
gf2_matrix_square(crc_comb[n], crc_comb[n - 1]);
|
||||
|
||||
/* mark tables as complete, in case someone else is waiting */
|
||||
crc_table_empty = 0;
|
||||
} else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
{}
|
||||
}
|
||||
#ifdef MAKECRCH
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
|
||||
/* write out CRC table to crc32.h */
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "static const uint32_t ");
|
||||
fprintf(out, "crc_table[8][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0], 256);
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k], 256);
|
||||
}
|
||||
fprintf(out, " }\n};\n");
|
||||
|
||||
/* write out zero operator table to crc32.h */
|
||||
fprintf(out, "\nstatic const uint32_t ");
|
||||
fprintf(out, "crc_comb[%d][%d] =\n{\n {\n", GF2_DIM, GF2_DIM);
|
||||
write_table(out, crc_comb[0], GF2_DIM);
|
||||
for (k = 1; k < GF2_DIM; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_comb[k], GF2_DIM);
|
||||
}
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
static void write_table(FILE *out, const uint32_t *table, int k) {
|
||||
int n;
|
||||
|
||||
for (n = 0; n < k; n++)
|
||||
fprintf(out, "%s0x%08" PRIx32 "%s", n % 5 ? "" : " ",
|
||||
(uint32_t)(table[n]),
|
||||
n == k - 1 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
make_crc_table();
|
||||
return 0;
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table(),
|
||||
* and tables of zero operator matrices for crc32_combine().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const uint32_t * ZEXPORT PREFIX(get_crc_table)(void) {
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const uint32_t *)crc_table;
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) {
|
||||
if (buf == NULL) return 0;
|
||||
|
||||
return functable.crc32(crc, buf, len);
|
||||
}
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
#define DO4 DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len)
|
||||
{
|
||||
crc = crc ^ 0xffffffff;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
#else
|
||||
while (len >= 4) {
|
||||
DO4;
|
||||
len -= 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) {
|
||||
return PREFIX(crc32_z)(crc, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
|
||||
integer pointer type. This violates the strict aliasing rule, where a
|
||||
compiler can assume, for optimization purposes, that two pointers to
|
||||
fundamentally different types won't ever point to the same memory. This can
|
||||
manifest as a problem only if one of the pointers is written to. This code
|
||||
only reads from those pointers. So long as this code remains isolated in
|
||||
this compilation unit, there won't be a problem. For this reason, this code
|
||||
should not be copied and pasted into a compilation unit in which other code
|
||||
writes to the buffer that is passed to these routines.
|
||||
*/
|
||||
|
||||
/* ========================================================================= */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_t len) {
|
||||
register uint32_t c;
|
||||
register const uint32_t *buf4;
|
||||
|
||||
c = crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const uint32_t *)(const void *)buf;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return c;
|
||||
}
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
||||
/* ========================================================================= */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define DOBIG4 c ^= *buf4++; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t len) {
|
||||
register uint32_t c;
|
||||
register const uint32_t *buf4;
|
||||
|
||||
c = ZSWAP32(crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const uint32_t *)(const void *)buf;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return ZSWAP32(c);
|
||||
}
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) {
|
||||
int n;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
if (len2 > 0)
|
||||
/* operator for 2^n zeros repeats every GF2_DIM n values */
|
||||
for (n = 0; len2; n = (n + 1) % GF2_DIM, len2 >>= 1)
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(crc_comb[n], crc1);
|
||||
return crc1 ^ crc2;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off_t len2) {
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(crc32_combine64)(uint32_t crc1, uint32_t crc2, z_off64_t len2) {
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
#ifdef X86_PCLMULQDQ_CRC
|
||||
#include "arch/x86/x86.h"
|
||||
#include "arch/x86/crc_folding.h"
|
||||
|
||||
ZLIB_INTERNAL void crc_finalize(deflate_state *const s) {
|
||||
if (x86_cpu_has_pclmulqdq)
|
||||
s->strm->adler = crc_fold_512to32(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
ZLIB_INTERNAL void crc_reset(deflate_state *const s) {
|
||||
#ifdef X86_PCLMULQDQ_CRC
|
||||
if (x86_cpu_has_pclmulqdq) {
|
||||
crc_fold_init(s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
s->strm->adler = PREFIX(crc32)(0L, NULL, 0);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) {
|
||||
#ifdef X86_PCLMULQDQ_CRC
|
||||
if (x86_cpu_has_pclmulqdq) {
|
||||
crc_fold_copy(strm->state, dst, strm->next_in, size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
memcpy(dst, strm->next_in, size);
|
||||
strm->adler = PREFIX(crc32)(strm->adler, dst, size);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
static void crc32_combine_gen_(uint32_t *op, z_off64_t len2)
|
||||
{
|
||||
uint32_t row;
|
||||
int j;
|
||||
unsigned i;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* if len2 is zero or negative, return the identity matrix */
|
||||
if (len2 <= 0) {
|
||||
row = 1;
|
||||
for (j = 0; j < GF2_DIM; j++) {
|
||||
op[j] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* at least one bit in len2 is set -- find it, and copy the operator
|
||||
corresponding to that position into op */
|
||||
i = 0;
|
||||
for (;;) {
|
||||
if (len2 & 1) {
|
||||
for (j = 0; j < GF2_DIM; j++)
|
||||
op[j] = crc_comb[i][j];
|
||||
break;
|
||||
}
|
||||
len2 >>= 1;
|
||||
i = (i + 1) % GF2_DIM;
|
||||
}
|
||||
|
||||
/* for each remaining bit set in len2 (if any), multiply op by the operator
|
||||
corresponding to that position */
|
||||
for (;;) {
|
||||
len2 >>= 1;
|
||||
i = (i + 1) % GF2_DIM;
|
||||
if (len2 == 0)
|
||||
break;
|
||||
if (len2 & 1)
|
||||
for (j = 0; j < GF2_DIM; j++)
|
||||
op[j] = gf2_matrix_times(crc_comb[i], op[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
void ZEXPORT PREFIX(crc32_combine_gen)(uint32_t *op, z_off_t len2)
|
||||
{
|
||||
crc32_combine_gen_(op, len2);
|
||||
}
|
||||
|
||||
void ZEXPORT PREFIX(crc32_combine_gen64)(uint32_t *op, z_off64_t len2)
|
||||
{
|
||||
crc32_combine_gen_(op, len2);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t *op)
|
||||
{
|
||||
return gf2_matrix_times(op, crc1) ^ crc2;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user