Compare commits

..

10 Commits

370 changed files with 8146 additions and 38117 deletions
+12 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
-6
View File
@@ -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>
-51
View File
@@ -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.
+6 -9
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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;
-6
View File
@@ -307,12 +307,6 @@ namespace EQEmu
} // namespace bug
enum WaypointStatus : int {
RoamBoxPauseInProgress = -3,
QuestControlNoGrid = -2,
QuestControlGrid = -1
};
} /*EQEmu*/
#endif /*COMMON_EMU_CONSTANTS_H*/
-22
View File
@@ -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*/
-14
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
-1
View File
@@ -84,7 +84,6 @@ class EQEmuConfig
// From <files/>
std::string SpellsFile;
std::string OpCodesFile;
std::string MailOpCodesFile;
std::string PluginPlFile;
// From <directories/>
+1 -4
View File
@@ -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
);
}
}
}
+1 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-114
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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);
+32 -20
View File
@@ -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);
+17 -24
View File
@@ -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
View File
@@ -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);
}
}
}
+2 -9
View File
@@ -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);
+7 -7
View File
@@ -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;
};
}
+685
View File
@@ -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;
}
+75
View File
@@ -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;
};
}
}
+95
View File
@@ -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;
}
}
+7 -3
View File
@@ -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];
+2
View File
@@ -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();
+9 -2
View File
@@ -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);
+4 -1
View File
@@ -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;
};
}
}
}
-265
View File
@@ -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 &params)
{
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 &params)
{
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 &params)
{
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 &params)
{
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);
}
}
-74
View File
@@ -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 &params);
Json::Value Login(WebsocketServerConnection *connection, const Json::Value &params);
Json::Value Subscribe(WebsocketServerConnection *connection, const Json::Value &params);
Json::Value Unsubscribe(WebsocketServerConnection *connection, const Json::Value &params);
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;
};
}
}
-153
View File
@@ -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;
}
-46
View File
@@ -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;
};
}
}
+1 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -136,7 +136,7 @@ int main(int argc, char *argv[]) {
zones.erase(rem);
}
EQ::EventLoop::Get().Process();
EQ::EventLoop::GetDefault().Process();
Sleep(5);
}
-4
View File
@@ -1,4 +0,0 @@
* text=auto
*.c text
*.h text
Makefile text
-76
View File
@@ -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
-283
View File
@@ -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
-865
View File
@@ -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
-374
View File
@@ -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.
-55
View File
@@ -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
-64
View File
@@ -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
-19
View File
@@ -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.
-365
View File
@@ -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]
-81
View File
@@ -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: [![build status](https://api.travis-ci.org/zlib-ng/zlib-ng.svg)](https://travis-ci.org/zlib-ng/zlib-ng/)
Buildkite: [![Build status](https://badge.buildkite.com/7bb1ef84356d3baee26202706cc053ee1de871c0c712b65d26.svg?branch=develop)](https://buildkite.com/circlestorm-productions/zlib-ng)
-118
View File
@@ -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.
-132
View File
@@ -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);
}
-77
View File
@@ -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 */
-2
View File
@@ -1,2 +0,0 @@
# ignore Makefiles; they're all automatically generated
Makefile
-54
View File
@@ -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
-134
View File
@@ -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
-29
View File
@@ -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
-13
View File
@@ -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_ */
-50
View File
@@ -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();
}
-115
View File
@@ -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 */
-12
View File
@@ -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
-169
View File
@@ -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");
}
-53
View File
@@ -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
-21
View File
@@ -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
-40
View File
@@ -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
-69
View File
@@ -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.
-86
View File
@@ -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 *)));
}
-29
View File
@@ -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
-365
View File
@@ -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;
}
-50
View File
@@ -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
-201
View File
@@ -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))
-142
View File
@@ -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;
}
-44
View File
@@ -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
-3
View File
@@ -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
-58
View File
@@ -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
-450
View File
@@ -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
-19
View File
@@ -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
-25
View File
@@ -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
-175
View File
@@ -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
-56
View File
@@ -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
-68
View File
@@ -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;
}
}
-16
View File
@@ -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_ */
-79
View File
@@ -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;
}
-1503
View File
File diff suppressed because it is too large Load Diff
-498
View File
@@ -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