From 58b76dd538c8f09a02b76fe6c44e5f6960fdd9f0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 17 Jan 2014 06:28:18 -0700 Subject: [PATCH] Added CentralServer project --- engine/server/application/CMakeLists.txt | 1 + .../application/CentralServer/CMakeLists.txt | 6 + .../CentralServer/src/CMakeLists.txt | 188 + .../CentralServer/src/linux/main.cpp | 55 + .../src/shared/AuctionTransferClient.cpp | 58 + .../src/shared/AuctionTransferClient.h | 141 + .../ATGenericAPI/GenericApiCore.cpp | 272 ++ .../ATGenericAPI/GenericApiCore.h | 123 + .../ATGenericAPI/GenericApiCore.o | Bin 0 -> 48764 bytes .../ATGenericAPI/GenericConnection.cpp | 218 + .../ATGenericAPI/GenericConnection.h | 88 + .../ATGenericAPI/GenericConnection.o | Bin 0 -> 24632 bytes .../ATGenericAPI/GenericMessage.cpp | 44 + .../ATGenericAPI/GenericMessage.h | 75 + .../ATGenericAPI/GenericMessage.o | Bin 0 -> 11860 bytes .../AuctionTransferAPI.cpp | 194 + .../AuctionTransferAPI.h | 92 + .../AuctionTransferAPI.o | Bin 0 -> 49356 bytes .../AuctionTransferAPICore.cpp | 181 + .../AuctionTransferAPICore.h | 35 + .../AuctionTransferAPICore.o | Bin 0 -> 38328 bytes .../AuctionTransferEnum.h | 164 + .../AuctionTransferGameAPI.ncb | Bin 0 -> 265216 bytes .../AuctionTransferGameAPI.sln | 30 + .../AuctionTransferGameAPI.suo | Bin 0 -> 13312 bytes .../AuctionTransferGameAPI.vcproj | 326 ++ .../AuctionTransferGameAPI/Base/Archive.cpp | 283 ++ .../AuctionTransferGameAPI/Base/Archive.h | 746 +++ .../AuctionTransferGameAPI/Base/Archive.o | Bin 0 -> 22488 bytes .../AuctionTransferGameAPI/Base/Platform.h | 105 + .../Base/linux/Archive.h | 44 + .../Base/linux/Mutex.cpp | 40 + .../AuctionTransferGameAPI/Base/linux/Mutex.h | 79 + .../Base/linux/Platform.cpp | 55 + .../Base/linux/Platform.h | 112 + .../Base/linux/Platform.o | Bin 0 -> 1356 bytes .../AuctionTransferGameAPI/Base/linux/Types.h | 42 + .../Base/win32/Archive.h | 42 + .../Base/win32/Platform.cpp | 31 + .../Base/win32/Platform.h | 98 + .../AuctionTransferGameAPI/Base/win32/Types.h | 42 + .../AuctionTransferGameAPI/Character.cpp | 44 + .../shared/AuctionTransferGameAPI/Character.h | 70 + .../shared/AuctionTransferGameAPI/Character.o | Bin 0 -> 15012 bytes .../shared/AuctionTransferGameAPI/Request.cpp | 231 + .../shared/AuctionTransferGameAPI/Request.h | 147 + .../shared/AuctionTransferGameAPI/Request.o | Bin 0 -> 61168 bytes .../AuctionTransferGameAPI/Response.cpp | 17 + .../shared/AuctionTransferGameAPI/Response.h | 35 + .../shared/AuctionTransferGameAPI/Response.o | Bin 0 -> 23016 bytes .../TcpLibrary/Clock.cpp | 119 + .../AuctionTransferGameAPI/TcpLibrary/Clock.h | 71 + .../AuctionTransferGameAPI/TcpLibrary/Clock.o | Bin 0 -> 1976 bytes .../TcpLibrary/IPAddress.cpp | 33 + .../TcpLibrary/IPAddress.h | 51 + .../TcpLibrary/IPAddress.o | Bin 0 -> 1220 bytes .../TcpLibrary/TcpBlockAllocator.cpp | 94 + .../TcpLibrary/TcpBlockAllocator.h | 44 + .../TcpLibrary/TcpBlockAllocator.o | Bin 0 -> 2176 bytes .../TcpLibrary/TcpConnection.cpp | 787 ++++ .../TcpLibrary/TcpConnection.h | 157 + .../TcpLibrary/TcpConnection.o | Bin 0 -> 7692 bytes .../TcpLibrary/TcpHandlers.h | 50 + .../TcpLibrary/TcpManager.cpp | 746 +++ .../TcpLibrary/TcpManager.h | 287 ++ .../TcpLibrary/TcpManager.o | Bin 0 -> 8748 bytes .../libAuctionTransferGameAPI.a | Bin 0 -> 260171 bytes .../AuctionTransferGameAPI/zip/GZipHelper.h | 472 ++ .../AuctionTransferGameAPI/zip/Zip/adler32.c | 48 + .../AuctionTransferGameAPI/zip/Zip/adler32.o | Bin 0 -> 1168 bytes .../AuctionTransferGameAPI/zip/Zip/compress.c | 68 + .../AuctionTransferGameAPI/zip/Zip/compress.o | Bin 0 -> 1188 bytes .../AuctionTransferGameAPI/zip/Zip/crc32.c | 162 + .../AuctionTransferGameAPI/zip/Zip/crc32.o | Bin 0 -> 2168 bytes .../AuctionTransferGameAPI/zip/Zip/deflate.c | 1350 ++++++ .../AuctionTransferGameAPI/zip/Zip/deflate.h | 318 ++ .../AuctionTransferGameAPI/zip/Zip/deflate.o | Bin 0 -> 8124 bytes .../AuctionTransferGameAPI/zip/Zip/gzio.c | 875 ++++ .../AuctionTransferGameAPI/zip/Zip/gzio.o | Bin 0 -> 6952 bytes .../AuctionTransferGameAPI/zip/Zip/infblock.c | 403 ++ .../AuctionTransferGameAPI/zip/Zip/infblock.h | 39 + .../AuctionTransferGameAPI/zip/Zip/infblock.o | Bin 0 -> 5740 bytes .../AuctionTransferGameAPI/zip/Zip/infcodes.c | 251 + .../AuctionTransferGameAPI/zip/Zip/infcodes.h | 27 + .../AuctionTransferGameAPI/zip/Zip/infcodes.o | Bin 0 -> 3496 bytes .../AuctionTransferGameAPI/zip/Zip/inffast.c | 183 + .../AuctionTransferGameAPI/zip/Zip/inffast.h | 17 + .../AuctionTransferGameAPI/zip/Zip/inffast.o | Bin 0 -> 1876 bytes .../AuctionTransferGameAPI/zip/Zip/inffixed.h | 151 + .../AuctionTransferGameAPI/zip/Zip/inflate.c | 366 ++ .../AuctionTransferGameAPI/zip/Zip/inflate.o | Bin 0 -> 3744 bytes .../AuctionTransferGameAPI/zip/Zip/inftrees.c | 454 ++ .../AuctionTransferGameAPI/zip/Zip/inftrees.h | 58 + .../AuctionTransferGameAPI/zip/Zip/inftrees.o | Bin 0 -> 8920 bytes .../AuctionTransferGameAPI/zip/Zip/infutil.c | 87 + .../AuctionTransferGameAPI/zip/Zip/infutil.h | 98 + .../AuctionTransferGameAPI/zip/Zip/infutil.o | Bin 0 -> 1196 bytes .../AuctionTransferGameAPI/zip/Zip/maketree.c | 51 + .../AuctionTransferGameAPI/zip/Zip/maketree.o | Bin 0 -> 1320 bytes .../AuctionTransferGameAPI/zip/Zip/trees.c | 1214 +++++ .../AuctionTransferGameAPI/zip/Zip/trees.h | 128 + .../AuctionTransferGameAPI/zip/Zip/trees.o | Bin 0 -> 12168 bytes .../AuctionTransferGameAPI/zip/Zip/uncompr.c | 58 + .../AuctionTransferGameAPI/zip/Zip/uncompr.o | Bin 0 -> 1108 bytes .../AuctionTransferGameAPI/zip/Zip/zconf.h | 279 ++ .../AuctionTransferGameAPI/zip/Zip/zlib.h | 893 ++++ .../AuctionTransferGameAPI/zip/Zip/zutil.c | 225 + .../AuctionTransferGameAPI/zip/Zip/zutil.h | 220 + .../AuctionTransferGameAPI/zip/Zip/zutil.o | Bin 0 -> 1384 bytes .../src/shared/CentralCSHandler.cpp | 342 ++ .../src/shared/CentralCSHandler.h | 128 + .../src/shared/CentralServer.cpp | 4086 +++++++++++++++++ .../CentralServer/src/shared/CentralServer.h | 467 ++ .../src/shared/CentralServerMetricsData.cpp | 307 ++ .../src/shared/CentralServerMetricsData.h | 65 + .../src/shared/CharacterCreationTracker.cpp | 374 ++ .../src/shared/CharacterCreationTracker.h | 84 + .../src/shared/ChatServerConnection.cpp | 64 + .../src/shared/ChatServerConnection.h | 34 + .../src/shared/ConfigCentralServer.cpp | 165 + .../src/shared/ConfigCentralServer.h | 515 +++ .../src/shared/ConnectionServerConnection.cpp | 427 ++ .../src/shared/ConnectionServerConnection.h | 253 + .../src/shared/ConsoleCommandParser.cpp | 132 + .../src/shared/ConsoleCommandParser.h | 29 + .../shared/ConsoleCommandParserDatabase.cpp | 65 + .../src/shared/ConsoleCommandParserDatabase.h | 29 + .../src/shared/ConsoleCommandParserGame.cpp | 212 + .../src/shared/ConsoleCommandParserGame.h | 29 + .../ConsoleCommandParserLoginServer.cpp | 64 + .../shared/ConsoleCommandParserLoginServer.h | 29 + .../src/shared/ConsoleConnection.cpp | 97 + .../src/shared/ConsoleConnection.h | 33 + .../src/shared/ConsoleManager.cpp | 65 + .../CentralServer/src/shared/ConsoleManager.h | 27 + .../src/shared/CustomerServiceConnection.cpp | 64 + .../src/shared/CustomerServiceConnection.h | 34 + .../src/shared/FirstCentralServer.h | 27 + .../src/shared/GameServerConnection.cpp | 379 ++ .../src/shared/GameServerConnection.h | 134 + .../src/shared/LoginServerConnection.cpp | 332 ++ .../src/shared/LoginServerConnection.h | 35 + .../src/shared/PlanetManager.cpp | 168 + .../CentralServer/src/shared/PlanetManager.h | 69 + .../src/shared/PlanetServerConnection.cpp | 175 + .../src/shared/PlanetServerConnection.h | 51 + .../StationPlayersCollectorConnection.cpp | 68 + .../StationPlayersCollectorConnection.h | 34 + .../src/shared/TaskConnection.cpp | 108 + .../CentralServer/src/shared/TaskConnection.h | 58 + .../src/shared/TransferServerConnection.cpp | 197 + .../src/shared/TransferServerConnection.h | 34 + .../src/shared/UniverseManager.cpp | 191 + .../src/shared/UniverseManager.h | 54 + .../src/win32/FirstCentralServer.cpp | 5 + .../CentralServer/src/win32/WinMain.cpp | 84 + 156 files changed, 25911 insertions(+) create mode 100644 engine/server/application/CentralServer/CMakeLists.txt create mode 100644 engine/server/application/CentralServer/src/CMakeLists.txt create mode 100644 engine/server/application/CentralServer/src/linux/main.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferClient.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferClient.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferEnum.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.ncb create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.sln create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.suo create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.vcproj create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Platform.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Archive.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpHandlers.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.cpp create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/libAuctionTransferGameAPI.a create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/GZipHelper.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/compress.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/compress.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/crc32.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/crc32.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffixed.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/maketree.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/maketree.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.o create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zconf.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zlib.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.c create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.h create mode 100644 engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.o create mode 100644 engine/server/application/CentralServer/src/shared/CentralCSHandler.cpp create mode 100644 engine/server/application/CentralServer/src/shared/CentralCSHandler.h create mode 100644 engine/server/application/CentralServer/src/shared/CentralServer.cpp create mode 100644 engine/server/application/CentralServer/src/shared/CentralServer.h create mode 100644 engine/server/application/CentralServer/src/shared/CentralServerMetricsData.cpp create mode 100644 engine/server/application/CentralServer/src/shared/CentralServerMetricsData.h create mode 100644 engine/server/application/CentralServer/src/shared/CharacterCreationTracker.cpp create mode 100644 engine/server/application/CentralServer/src/shared/CharacterCreationTracker.h create mode 100644 engine/server/application/CentralServer/src/shared/ChatServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ChatServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConfigCentralServer.h create mode 100644 engine/server/application/CentralServer/src/shared/ConnectionServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConnectionServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParser.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParser.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserGame.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserGame.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserLoginServer.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleCommandParserLoginServer.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleManager.cpp create mode 100644 engine/server/application/CentralServer/src/shared/ConsoleManager.h create mode 100644 engine/server/application/CentralServer/src/shared/CustomerServiceConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/CustomerServiceConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/FirstCentralServer.h create mode 100644 engine/server/application/CentralServer/src/shared/GameServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/GameServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/LoginServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/LoginServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/PlanetManager.cpp create mode 100644 engine/server/application/CentralServer/src/shared/PlanetManager.h create mode 100644 engine/server/application/CentralServer/src/shared/PlanetServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/PlanetServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/StationPlayersCollectorConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/StationPlayersCollectorConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/TaskConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/TaskConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/TransferServerConnection.cpp create mode 100644 engine/server/application/CentralServer/src/shared/TransferServerConnection.h create mode 100644 engine/server/application/CentralServer/src/shared/UniverseManager.cpp create mode 100644 engine/server/application/CentralServer/src/shared/UniverseManager.h create mode 100644 engine/server/application/CentralServer/src/win32/FirstCentralServer.cpp create mode 100644 engine/server/application/CentralServer/src/win32/WinMain.cpp diff --git a/engine/server/application/CMakeLists.txt b/engine/server/application/CMakeLists.txt index ebd82183..2317195d 100644 --- a/engine/server/application/CMakeLists.txt +++ b/engine/server/application/CMakeLists.txt @@ -1,4 +1,5 @@ +add_subdirectory(CentralServer) add_subdirectory(ChatServer) add_subdirectory(ConnectionServer) add_subdirectory(LoginServer) diff --git a/engine/server/application/CentralServer/CMakeLists.txt b/engine/server/application/CentralServer/CMakeLists.txt new file mode 100644 index 00000000..7ca4b09b --- /dev/null +++ b/engine/server/application/CentralServer/CMakeLists.txt @@ -0,0 +1,6 @@ + +cmake_minimum_required(VERSION 2.8) + +project(CentralServer) + +add_subdirectory(src) diff --git a/engine/server/application/CentralServer/src/CMakeLists.txt b/engine/server/application/CentralServer/src/CMakeLists.txt new file mode 100644 index 00000000..7b0fdcd2 --- /dev/null +++ b/engine/server/application/CentralServer/src/CMakeLists.txt @@ -0,0 +1,188 @@ + +set(SHARED_SOURCES + shared/AuctionTransferClient.cpp + shared/AuctionTransferClient.h + shared/CentralCSHandler.cpp + shared/CentralCSHandler.h + shared/CentralServer.cpp + shared/CentralServer.h + shared/CentralServerMetricsData.cpp + shared/CentralServerMetricsData.h + shared/CharacterCreationTracker.cpp + shared/CharacterCreationTracker.h + shared/ChatServerConnection.cpp + shared/ChatServerConnection.h + shared/ConfigCentralServer.cpp + shared/ConfigCentralServer.h + shared/ConnectionServerConnection.cpp + shared/ConnectionServerConnection.h + shared/ConsoleCommandParser.cpp + shared/ConsoleCommandParser.h + shared/ConsoleCommandParserDatabase.cpp + shared/ConsoleCommandParserDatabase.h + shared/ConsoleCommandParserGame.cpp + shared/ConsoleCommandParserGame.h + shared/ConsoleCommandParserLoginServer.cpp + shared/ConsoleCommandParserLoginServer.h + shared/ConsoleConnection.cpp + shared/ConsoleConnection.h + shared/ConsoleManager.cpp + shared/ConsoleManager.h + shared/CustomerServiceConnection.cpp + shared/CustomerServiceConnection.h + shared/FirstCentralServer.h + shared/GameServerConnection.cpp + shared/GameServerConnection.h + shared/LoginServerConnection.cpp + shared/LoginServerConnection.h + shared/PlanetManager.cpp + shared/PlanetManager.h + shared/PlanetServerConnection.cpp + shared/PlanetServerConnection.h + shared/StationPlayersCollectorConnection.cpp + shared/StationPlayersCollectorConnection.h + shared/TaskConnection.cpp + shared/TaskConnection.h + shared/TransferServerConnection.cpp + shared/TransferServerConnection.h + shared/UniverseManager.cpp + shared/UniverseManager.h + + shared/AuctionTransferGameAPI/AuctionTransferAPI.cpp + shared/AuctionTransferGameAPI/AuctionTransferAPI.h + shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp + shared/AuctionTransferGameAPI/AuctionTransferAPICore.h + shared/AuctionTransferGameAPI/Character.cpp + shared/AuctionTransferGameAPI/Character.h + shared/AuctionTransferGameAPI/Request.cpp + shared/AuctionTransferGameAPI/Request.h + shared/AuctionTransferGameAPI/Response.cpp + shared/AuctionTransferGameAPI/Response.h + + shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.cpp + shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.h + shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.cpp + shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.h + shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.cpp + shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.h + + shared/AuctionTransferGameAPI/Base/Archive.cpp + + shared/AuctionTransferGameAPI/TcpLibrary/Clock.cpp + shared/AuctionTransferGameAPI/TcpLibrary/Clock.h + shared/AuctionTransferGameAPI/TcpLibrary/IpAddress.cpp + shared/AuctionTransferGameAPI/TcpLibrary/IpAddress.h + shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.cpp + shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.h + shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.cpp + shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.h + shared/AuctionTransferGameAPI/TcpLibrary/TcpHandlers.h + shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.cpp + shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.h + + shared/AuctionTransferGameAPI/zip/GZipHelper.h + shared/AuctionTransferGameAPI/zip/Zip/deflate.h + shared/AuctionTransferGameAPI/zip/Zip/infblock.h + shared/AuctionTransferGameAPI/zip/Zip/infcodes.h + shared/AuctionTransferGameAPI/zip/Zip/inffast.h + shared/AuctionTransferGameAPI/zip/Zip/inffixed.h + shared/AuctionTransferGameAPI/zip/Zip/inftrees.h + shared/AuctionTransferGameAPI/zip/Zip/infutil.h + shared/AuctionTransferGameAPI/zip/Zip/trees.h + shared/AuctionTransferGameAPI/zip/Zip/zconf.h + shared/AuctionTransferGameAPI/zip/Zip/zlib.h + shared/AuctionTransferGameAPI/zip/Zip/zutil.h +) + +if(WIN32) + set(PLATFORM_SOURCES + win32/FirstCentralServer.cpp + win32/WinMain.cpp + shared/AuctionTransferGameAPI/Base/win32/Archive.h + shared/AuctionTransferGameAPI/Base/win32/Platform.cpp + shared/AuctionTransferGameAPI/Base/win32/Platform.h + shared/AuctionTransferGameAPI/Base/win32/Types.h + ) +else() + set(PLATFORM_SOURCES + linux/main.cpp + ) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/shared + ${CMAKE_CURRENT_SOURCE_DIR}/shared/AuctionTransferGameAPI + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCommandParser/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCompression/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedGame/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverKeyShare/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverMetrics/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public +) + +link_directories(${STLPORT_LIBDIR}) + +add_executable(CentralServer + ${SHARED_SOURCES} + ${PLATFORM_SOURCES} +) + +target_link_libraries(CentralServer + sharedCommandParser + sharedCompression + sharedDebug + sharedFile + sharedFoundation + sharedGame + sharedLog + sharedMath + sharedMemoryManager + sharedMessageDispatch + sharedNetwork + sharedNetworkMessages + sharedObject + sharedRandom + sharedSynchronization + sharedThread + sharedUtility + serverKeyShare + serverMetrics + serverNetworkMessages + serverUtility + archive + crypto + fileInterface + localization + localizationArchive + unicode + unicodeArchive + udplibrary + ${ZLIB_LIBRARY} +) + +if(WIN32) + target_link_libraries(CentralServer mswsock ws2_32) +endif() diff --git a/engine/server/application/CentralServer/src/linux/main.cpp b/engine/server/application/CentralServer/src/linux/main.cpp new file mode 100644 index 00000000..c454fbe9 --- /dev/null +++ b/engine/server/application/CentralServer/src/linux/main.cpp @@ -0,0 +1,55 @@ +#include "sharedFoundation/FirstSharedFoundation.h" + +#include "ConfigCentralServer.h" +#include "CentralServer.h" + +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/Os.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedThread/SetupSharedThread.h" + +// ====================================================================== + +int main(int argc, char ** argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + setupFoundationData.lpCmdLine = ConvertCommandLine(argc,argv); + SetupSharedFoundation::install(setupFoundationData); + + SetupSharedCompression::install(); + + SetupSharedFile::install(false); + SetupSharedRandom::install(time(0)); //lint !e732 + + NetworkHandler::install(); + Os::setProgramName("CentralServer"); + ConfigCentralServer::install(); + + std::string cmdLine = setupFoundationData.lpCmdLine; + size_t firstArg = cmdLine.find(" ", 0); + size_t lastSlash = 0; + size_t nextSlash = 0; + while(nextSlash < firstArg) + { + nextSlash = cmdLine.find("/", lastSlash); + if(nextSlash == cmdLine.npos || nextSlash >= firstArg) //lint !e1705 static class members may be accessed by the scoping operator (huh?) + break; + lastSlash = nextSlash + 1; + } + cmdLine = cmdLine.substr(lastSlash); + CentralServer::getInstance().setCommandLine(cmdLine); + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(CentralServer::run); + NetworkHandler::remove(); + SetupSharedFoundation::remove(); + + return 0; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferClient.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.cpp new file mode 100644 index 00000000..eb67f237 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.cpp @@ -0,0 +1,58 @@ +#include "FirstCentralServer.h" +#include "AuctionTransferClient.h" +#include "sharedLog/Log.h" + + +AuctionTransferClient::AuctionTransferClient(const char *hostName[], const short port[], int count, const char *identifier[], unsigned identifierCount) : + AuctionTransferAPI( hostName, port, count, identifier, identifierCount ) +{ +} + +AuctionTransferClient::~AuctionTransferClient() +{ +} + + +// Connection status callbacks +void AuctionTransferClient::onConnect(const char* host, unsigned short port, const short current, const short max) +{ + LOG("AuctionTransferClient", ("onConnect")); +} + +void AuctionTransferClient::onDisconnect(const char *host, const short port, const short current, const short max) +{ + LOG("AuctionTransferClient", ("onDisconnect")); +} + + +/***************************** +void AuctionTransferClient::addCoinToAuction( const ExchangeListCreditsMessage& msg ) +{ + //1. get transaction id from auction system (save msg details for use when get response) + //2. on response: if success: + // 2a. send prepare transaction + // 2b. on response: + // 2bi. if user connected: send VeAuctionCoinReply (with result code) to user's ES + // 2bii. if user not connected: send immediate abort back to auction service + + const unsigned uTrack = getNewTransactionID( NULL ); + + AuctionAssetDetails &details = m_mPendingRequestDetails[ uTrack ]; + details.u8Type = AuctionAssetDetails::TYPE_COIN; + details.u32AccountNum = msg.getAccountNum(); + details.u32CharDBID = msg.getCharacterId(); + details.i64ItemDBID = 0; + details.u32ItemStackCount = 0; + details.i64Credits = msg.getCredits(); + details.sAssetXML = ""; ///msg.getAssetXML(); +} +**********************/ + + + + + + + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h new file mode 100644 index 00000000..176ec79e --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferClient.h @@ -0,0 +1,141 @@ + +#ifndef AUCTIONSTRANFERCLIENT_H +#define AUCTIONSTRANFERCLIENT_H + +#ifndef _WIN32 +#include "AuctionTransferGameAPI/AuctionTransferAPI.h" +#else + +namespace AuctionTransfer +{ + class AuctionTransferAPI + { + public: + AuctionTransferAPI( const char *[], const short [], int , const char *[], unsigned ) + {}; + virtual void process() {}; + }; + +}; + +#endif + + +class AuctionTransferClient : public AuctionTransfer::AuctionTransferAPI +{ +public: + AuctionTransferClient(const char *hostName[], const short port[], int count, const char *identifier[], unsigned identifierCount); + virtual ~AuctionTransferClient(); + + + // Connection status callbacks + virtual void onConnect(const char* host, unsigned short port, const short current, const short max); + virtual void onDisconnect(const char *host, const short port, const short current, const short max); + + + // Callbacks that are responses + void onSendPrepareTransaction(unsigned int, unsigned int, void *) {}; + void onSendPrepareTransactionCompressed(unsigned int, unsigned int, void *) {}; + void onSendCommitTransaction(unsigned int, unsigned int, void *) {}; + void onSendAbortTransaction(unsigned int, unsigned int, void *) {}; + void onSendAuditAssetTransfer(unsigned int, unsigned int, void *) {}; + + void onGetNewTransactionID(unsigned int, unsigned int, int64, void *) {}; + + // Responses to reply requests + void onReplyReceivePrepareTransaction(unsigned int, unsigned int, void *) {}; + void onReplyReceiveCommitTransaction(unsigned int, unsigned int, void *) {}; + void onReplyReceiveAbortTransaction(unsigned int, unsigned int, void *) {}; + void onReplyReceiveGetCharacterList(unsigned int, unsigned int, void *) {}; + + // house keeping + void onIdentifyHost(unsigned int, unsigned int, void *) {}; + + // callbacks initiated by auction + void onReceivePrepareTransaction(unsigned int, int64, unsigned int, unsigned int, int64, const char *) {}; + void onReceiveCommitTransaction(unsigned int, int64) {}; + void onReceiveAbortTransaction(unsigned int, int64) {}; + void onReceiveGetCharacterList(unsigned int, unsigned int, const char *) {}; + +private: + +/************************************************* + struct AuctionAssetDetails + { + enum eAssetTypes + { + TYPE_ITEM, + TYPE_COIN, + TYPE_CHARACTER, + TYPE_FOR_IMAGE_UPLOAD + }; + + AuctionAssetDetails() + : u8Type( TYPE_ITEM ), + u32AccountNum( 0 ), + u32CharDBID( 0 ), + i64ItemDBID( INVALID_EQUID ), + u32ItemStackCount( 0 ), + i64AssetID( 0 ) + {} + + uns8 u8Type; + uns32 u32AccountNum; + uns32 u32CharDBID; + int64 i64ItemDBID; + uns32 u32ItemStackCount; + int64 i64Copper; + CharString sAssetXML; + + int64 i64AssetID; + }; + + typedef std::map< unsigned, AuctionAssetDetails > PendingRequestMap; + PendingRequestMap m_mPendingRequestDetails; + + + + + + struct IncomingPrepareDetails + { + int64 i64TransactionID; + int64 i64AssetID; + uns32 u32DestStationID; + uns32 u32DestCharDBID; + }; + typedef std::map< unsigned, IncomingPrepareDetails > IncomingPrepareMap;//key=tracking + IncomingPrepareMap m_mPendingIncomingPrepareDetails; + + + + typedef std::map< unsigned, int64 > IncomingCommitMap;//key=tracking, val=transaction + IncomingCommitMap m_mPendingIncomingCommitDetails; + + + + struct TransferDetails + { + TransferDetails() + : i64AssetID( 0 ), + u32DestStationID( 0 ), + u32DestCharDBID( INVALID_EQUID ) + {} + + int64 i64AssetID; + uns32 u32DestStationID; + uns32 u32DestCharDBID; + + //used when committing + std::vector< uns8 > aAssetSerialData; + int32 i32Copper; + }; + typedef std::map< int64, TransferDetails > PendingTransferMap; + PendingTransferMap m_mPendingTransferDetails; +**********************************************/ + + +}; + + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.cpp new file mode 100644 index 00000000..6c412225 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.cpp @@ -0,0 +1,272 @@ +#include "GenericApiCore.h" +#include "GenericConnection.h" +#include "GenericMessage.h" + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +using namespace std; + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif + +//---------------------------------------- +ServerTrackObject::ServerTrackObject(unsigned mapped_track, unsigned real_track, GenericConnection *con) +: m_mappedTrack(mapped_track), m_realTrack(real_track), m_connection(con) +//---------------------------------------- +{ +} + +//---------------------------------------- +GenericAPICore::GenericAPICore(const char *host, + short port, + unsigned reqTimeout, + unsigned reconnectTimeout, + unsigned noDataTimeoutSecs, + unsigned noAckTimeoutSecs, + unsigned incomingBufSizeInKB, + unsigned outgoingBufSizeInKB, + unsigned keepAlive, + unsigned maxRecvMessageSizeInKB) +: m_currTrack(0), + m_reconnectTimeout(0), + m_outCount(0), + m_pendingCount(0), + m_requestTimeout(reqTimeout), + m_currentConnections(0), m_maxConnections(0), + m_suspended(false), + m_nextConnectionIndex(0) +//---------------------------------------- +{ + GenericConnection *con = new GenericConnection(host, port, this, reconnectTimeout, noDataTimeoutSecs, noAckTimeoutSecs, incomingBufSizeInKB, outgoingBufSizeInKB, keepAlive, maxRecvMessageSizeInKB); + m_serverConnections.push_back(con); +} + +//---------------------------------------- +GenericAPICore::GenericAPICore(const char *game, const char *hosts[], + const short port[], + unsigned arraySize, + unsigned reqTimeout, + unsigned reconnectTimeout, + unsigned noDataTimeoutSecs, + unsigned noAckTimeoutSecs, + unsigned incomingBufSizeInKB, + unsigned outgoingBufSizeInKB, + unsigned keepAlive, + unsigned maxRecvMessageSizeInKB) +: m_currTrack(0), + m_reconnectTimeout(0), + m_outCount(0), + m_pendingCount(0), + m_requestTimeout(reqTimeout), + m_currentConnections(0), m_maxConnections(0), + m_suspended(false), + m_nextConnectionIndex(0), + m_game(game) +//---------------------------------------- +{ + for (unsigned i=0; i::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++) + { + GenericConnection *con = *conIter; + delete con; + } + m_serverConnections.clear(); + + for(map::iterator iter = m_pending.begin(); iter != m_pending.end(); ++iter) + { + delete (*iter).second; + } + + m_pending.empty(); + + while(m_outCount > 0) + { + delete m_outboundQueue.front().second; + delete m_outboundQueue.front().first; + m_outboundQueue.pop(); + --m_outCount; + } +} + +//---------------------------------------- +unsigned GenericAPICore::submitRequest(GenericRequest *req, GenericResponse *res) +//---------------------------------------- +{ + ++m_outCount; + if(m_currTrack == 0) + { + m_currTrack++; + } + req->setTrack(m_currTrack); + res->setTrack(m_currTrack); + time_t timeout = time(NULL) + m_requestTimeout; + + req->setTimeout(timeout); + res->setTimeout(timeout); + + m_outboundQueue.push(pair(req, res)); + return(m_currTrack++); +} + +//---------------------------------------- +void GenericAPICore::process() +//---------------------------------------- +{ + GenericRequest *req; + GenericResponse *res; + + if (!m_suspended) + { + // Process timeout on pending requests + while((m_outCount > 0) && ((req = m_outboundQueue.front().first)->getTimeout() <= time(NULL))) + { + --m_outCount; + res = m_outboundQueue.front().second; + m_outboundQueue.pop(); + + responseCallback(res); + delete res; + delete req; + } + + // Process timeout on pending responses + while((m_pendingCount > 0) && ((res = (*m_pending.begin()).second)->getTimeout() <= time(NULL))) + { + --m_pendingCount; + m_pending.erase(m_pending.begin()); + responseCallback(res); + delete res; + } + + while(m_outCount > 0) + { + pair out_pair = m_outboundQueue.front(); + req = out_pair.first; + res = out_pair.second; + GenericConnection *con = NULL; + if (req->getMappedServerTrack() == 0) // request has no originating "owner" server + { + con = getNextActiveConnection(); // it does not matter which server we send this to + } + else + { + ServerTrackObject *stobj = findServer(req->getMappedServerTrack()); + if (stobj) + { + con = stobj->getConnection(); // the server connection to respond to + req->setServerTrack(stobj->getRealServerTrack()); // map server track back to REAL server track + //printf("\nUnmapping %d to %d", stobj->getMappedServerTrack(), req->getMappedServerTrack()); //debug + delete stobj; + } + } + + if (con != NULL) + { + Base::ByteStream msg; + req->pack(msg); + con->Send(msg); + m_pending.insert(pair(res->getTrack(), res)); + --m_outCount; + ++m_pendingCount; + m_outboundQueue.pop(); + delete req; + } + else + { + //no active connections + break; //from while loop + } + + } + } + + for (std::vector::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++) + { + GenericConnection *con = *conIter; + con->process(); + } +} + + +//---------------------------------------- +GenericConnection *GenericAPICore::getNextActiveConnection() +//---------------------------------------- +{ + unsigned startIndex = m_nextConnectionIndex; + unsigned maxIndex = m_serverConnections.size() - 1; + + GenericConnection *con = NULL; + + //loop until we find an active connection, or until we get back + // to where we started + do + { + if (m_serverConnections[m_nextConnectionIndex]->isConnected()) + { + con = m_serverConnections[m_nextConnectionIndex]; + if (m_nextConnectionIndex == maxIndex) + m_nextConnectionIndex = 0; + else + m_nextConnectionIndex++; + + } + else if (++m_nextConnectionIndex > maxIndex) + { + //went past end of vector, start back at 0 + m_nextConnectionIndex = 0; + } + }while (con == NULL && m_nextConnectionIndex != startIndex); + + return con; +} + +//---------------------------------------- +void GenericAPICore::countOpenConnections() +//---------------------------------------- +{ + m_currentConnections = 0; + m_maxConnections = m_serverConnections.size(); + + for (std::vector::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++) + { + GenericConnection *con = *conIter; + if (con->isConnected()) + ++m_currentConnections; + } +} + +//---------------------------------------- +ServerTrackObject *GenericAPICore::findServer(unsigned server_track) +//---------------------------------------- +{ + std::map::iterator iter = m_serverTracks.find(server_track); + if (iter == m_serverTracks.end()) + return NULL; + ServerTrackObject *stobj = (*iter).second; + m_serverTracks.erase(server_track); + return stobj; +} + +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.h new file mode 100644 index 00000000..215f5817 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.h @@ -0,0 +1,123 @@ +#if !defined (GENERICAPICORE_H_) +#define GENERICAPICORE_H_ + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +#pragma warning (disable: 4786) + +#include +#include +#include +#include "Base/Archive.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +class GenericRequest; +class GenericResponse; +class GenericConnection; + +//---------------------------------------------- +class ServerTrackObject +//---------------------------------------------- +{ +public: + ServerTrackObject(unsigned mapped_track, unsigned real_track, GenericConnection *con); + ~ServerTrackObject() { } + + inline GenericConnection *getConnection() { return m_connection; } + inline unsigned getRealServerTrack() { return m_realTrack; } + inline unsigned getMappedServerTrack() { return m_mappedTrack; } + +private: + unsigned m_mappedTrack; + unsigned m_realTrack; + GenericConnection *m_connection; +}; + +//---------------------------------------------- +class GenericAPICore +//---------------------------------------------- +{ +public: + friend class GenericConnection; + + GenericAPICore::GenericAPICore(const char *host, + short port, + unsigned reqTimeout, + unsigned reconnectTimeout, + unsigned noDataTimeoutSecs = 5, + unsigned noAckTimeoutSecs = 5, + unsigned incomingBufSizeInKB = 32, + unsigned outgoingBufSizeInKB = 32, + unsigned keepAlive = 1, + unsigned maxRecvMessageSizeInKB = 0); + + /** + * NOTE: arraySize must be actual size of host and port arrays. + * ALSO: cannot specify a 0 array size. + */ + GenericAPICore(const char *game, const char *hosts[], + const short port[], + unsigned arraySize, + unsigned reqTimeout, + unsigned reconnectTimeout, + unsigned noDataTimeoutSecs = 5, + unsigned noAckTimeoutSecs = 5, + unsigned incomingBufSizeInKB = 32, + unsigned outgoingBufSizeInKB = 32, + unsigned keepAlive = 1, + unsigned maxRecvMessageSizeInKB = 0); + + virtual ~GenericAPICore(); + + void process(); + virtual void responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *con) = 0; + virtual void responseCallback(GenericResponse *R) = 0; + + virtual void OnDisconnect(GenericConnection *con) = 0; + virtual void OnConnect(GenericConnection *con) = 0; + + void countOpenConnections(); + ServerTrackObject *findServer(unsigned server_track); + + + void suspendProcessing() { m_suspended = true; } + void resumeProcessing() { m_suspended = false; } + unsigned submitRequest(GenericRequest *req, GenericResponse *res); + GenericConnection *getNextActiveConnection(); + std::string &getGameCode() { return m_game; } + void addIdentifier(std::string id) { m_gameIdentifiers.push_back(id);} + +protected: + std::vector m_serverConnections; + std::map m_pending; + std::queue > m_outboundQueue; + unsigned m_currTrack; + time_t m_reconnectTimeout; + unsigned m_outCount; + unsigned m_pendingCount; + unsigned m_requestTimeout; + unsigned m_currentConnections; // number currently connected + unsigned m_maxConnections; // number that should be connected + std::map m_serverTracks; + std::vector m_gameIdentifiers; + +private: + bool m_suspended; + unsigned m_nextConnectionIndex; + std::string m_game; +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericApiCore.o new file mode 100644 index 0000000000000000000000000000000000000000..e1b6f0d5cfca18b59542d09ad136f5a86248d359 GIT binary patch literal 48764 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.cpp new file mode 100644 index 00000000..318f5c20 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.cpp @@ -0,0 +1,218 @@ +#include "GenericApiCore.h" +#include "GenericConnection.h" +#include "GenericMessage.h" +#include "AuctionTransferAPICore.h" + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +#define REQUEST_SET_API 0 +#define GAME_RESOURCE 1 + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +using namespace std; +using namespace Base; + +GenericConnection::GenericConnection(const char *host, short port, GenericAPICore *apiCore, unsigned reconnectTimeout, unsigned noDataTimeoutSecs, unsigned, unsigned incomingBufSizeInKB, unsigned outgoingBufSizeInKB, unsigned keepAlive, unsigned maxRecvMessageSizeInKB) +: m_bConnected(CON_NONE), + m_apiCore(apiCore), + m_con(NULL), + m_host(host), + m_port(port), + m_lastTrack(123455), //random choice != 1 + m_conState(CON_DISCONNECT), + m_reconnectTimeout(reconnectTimeout) +{ + TcpManager::TcpParams params; + + params.incomingBufferSize = incomingBufSizeInKB * 1024; + params.outgoingBufferSize = outgoingBufSizeInKB * 1024; + params.maxConnections = 1; + params.port = 0; + params.maxRecvMessageSize = maxRecvMessageSizeInKB*1024; + params.keepAliveDelay = keepAlive * 1000; + params.noDataTimeout = noDataTimeoutSecs * 1000; + //params.oldestUnacknowledgedTimeout = noAckTimeoutSecs * 1000; + + m_manager = new TcpManager(params); +} + +GenericConnection::~GenericConnection() +{ + if(m_con) + { + m_con->SetHandler(NULL); + m_con->Disconnect();//don't worry about onterminated being called, we've set it's handler to null, so it wont + m_con->Release(); + } + + m_manager->Release(); +} + +void GenericConnection::disconnect() +{ + if (m_con) + { + m_con->Disconnect(); + //no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release(); + m_con = NULL; + } + m_conState = CON_DISCONNECT; + m_bConnected = CON_NONE; +} + +void GenericConnection::OnTerminated(TcpConnection *) +{ +// m_apiCore->OnDisconnect(m_host.c_str(), m_port); + m_apiCore->OnDisconnect(this); + if(m_con) + { + m_con->Release(); + m_con = NULL; + } + m_conState = CON_DISCONNECT; + m_bConnected = CON_NONE; +} + +void GenericConnection::OnRoutePacket(TcpConnection *, const unsigned char *data, int dataLen) +{ + short type; + unsigned track; + + ByteStream msg(data, dataLen); + ByteStream::ReadIterator iter = msg.begin(); + + get(iter, type); + get(iter, track); + GenericResponse *res = NULL; + + // the following if block is a temporary fix that prevents + // a crash with a game team in which they occasionally find + // themselves receiving a dupe track in consecutive calls to + // OnRoutePacket (which then leads to a callback being called + // twice and data being invalid on the second call -> crash!). + // TODO: resolve this BK +/* if (track != 0 && + track == m_lastTrack) + { + printf("!!! ERROR !!! Got a duplicate track ID %u\n", track); + return; + } + m_lastTrack = track; +*/ + // end temporary fix. + + if(track == 0) // notification message from the server, not as a response to a request from this API + { + if (type == ATGAME_REQUEST_CONNECT) + { // this is a special case, for when we have identified our game code to server + m_bConnected = CON_IDENTIFIED; + m_apiCore->OnConnect(this); + } + else + { + m_apiCore->responseCallback(type, iter, this); + } + } + else + { + map::iterator mapIter = m_apiCore->m_pending.find(track); + + if(mapIter != m_apiCore->m_pending.end()) + { + res = (*mapIter).second; + iter = msg.begin(); + res->unpack(iter); + m_apiCore->responseCallback(res); + m_apiCore->m_pendingCount--; + m_apiCore->m_pending.erase(mapIter); + delete res; + } + } +} + +void GenericConnection::process() +{ + switch(m_conState) + { + case CON_DISCONNECT: + // create connection object, attempting to connect and + // checking for connection in next state, CON_NEGOTIATE + m_con = m_manager->EstablishConnection(m_host.c_str(), m_port); + if(m_con) + { + m_con->SetHandler(this); + m_conState = CON_NEGOTIATE; + m_conTimeout = time(NULL) + m_reconnectTimeout; + } + break; + case CON_NEGOTIATE: + // check for connection + + if(m_con->GetStatus() == TcpConnection::StatusConnected) + { + // we're connected + m_conState = CON_CONNECT; + m_bConnected = CON_CONNECTED; + // instead of calling OnConnect() right now, we are going to submit a connection packet + // identifying us +// m_apiCore->OnConnect(this); + Base::ByteStream msg; + put(msg, (short)REQUEST_SET_API); + put(msg, (unsigned)0); // track + put(msg, (unsigned)API_VERSION_CODE); + put(msg, GAME_RESOURCE); // identify us as a game connection resource + + // now add in the game identifiers + put(msg, (unsigned)m_apiCore->m_gameIdentifiers.size()); // number of strings to read + for(unsigned index = 0; index < m_apiCore->m_gameIdentifiers.size(); index++) + put(msg, std::string(m_apiCore->m_gameIdentifiers[index])); + Send(msg); + } + else if(time(NULL) > m_conTimeout) + { + // we did not connect + m_con->Disconnect(); + //no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release(); + m_con = NULL; + m_conState = CON_DISCONNECT; + m_bConnected = CON_NONE; + } + break; + case CON_CONNECT: + // do nothing + break; + default: + // this should not occur, but we revert to CON_DISCONNECT if it does + m_conState = CON_DISCONNECT; + m_bConnected = CON_NONE; + if (m_con) + { + m_con->Disconnect(); + //no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release(); + m_con = NULL; + } + } + m_manager->GiveTime(); +} + +void GenericConnection::Send(Base::ByteStream &msg) +{ + if(m_con && m_con->GetStatus() == TcpConnection::StatusConnected) + { + m_con->Send((const char *)msg.getBuffer(), msg.getSize()); + } +} + +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.h new file mode 100644 index 00000000..28852377 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.h @@ -0,0 +1,88 @@ +#if !defined (GENERICCONNECTION_H_) +#define GENERICCONNECTION_H_ + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +#include +#include +#include +#include + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +static const unsigned API_VERSION_CODE = 1; + +////////////////////////////////////////////////////////////////////////////////////////////// +// these will never change. They will also be in the enumeration. These are defined here to +// prevent us from having to re-compile and include the enumeration file in this generic code. +#define ATGAME_REQUEST_CONNECT 0 +#define ATWEB_REQUEST_CONNECT 10000 +////////////////////////////////////////////////////////////////////////////////////////////// + +enum eConState +{ + CON_DISCONNECT, + CON_NEGOTIATE, + CON_CONNECT +}; +enum eConnectStatus +{ + CON_NONE, + CON_CONNECTED, + CON_IDENTIFIED +}; + +class GenericConnection : public TcpConnectionHandler + { + public: + GenericConnection(const char *host, + short port, + GenericAPICore *apiCore, + unsigned reconnectTimeout, + unsigned noDataTimeoutSecs = 5, + unsigned noAckTimeoutSecs = 5, + unsigned incomingBufSizeInKB = 32, + unsigned outgoingBufSizeInKB = 32, + unsigned keepAlive = 1, + unsigned maxRecvMessageSizeInKB = 0); + + virtual ~GenericConnection(); + + virtual void OnRoutePacket(TcpConnection *con, const unsigned char *data, int dataLen); + virtual void OnTerminated(TcpConnection *con); + void Send(Base::ByteStream &msg); + inline const char *getHost() const { return m_host.c_str(); } + inline const short getPort() const { return m_port; } + + inline eConnectStatus isConnected() { return m_bConnected; } + void disconnect(); + void process(); + +private: + eConnectStatus m_bConnected; + GenericAPICore *m_apiCore; + TcpManager *m_manager; + TcpConnection *m_con; + std::string m_host; + short m_port; + unsigned m_lastTrack; + eConState m_conState; + time_t m_conTimeout; + unsigned m_reconnectTimeout; + }; + +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericConnection.o new file mode 100644 index 0000000000000000000000000000000000000000..353581746ec511a8131274519db277b0b0b63fdd GIT binary patch literal 24632 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.cpp new file mode 100644 index 00000000..c01729d8 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.cpp @@ -0,0 +1,44 @@ +#include "GenericMessage.h" + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif + +using namespace Base; + +//------------------------------------------- +GenericRequest::GenericRequest(short type, unsigned server_track) +: m_type(type), m_server_track(server_track) +//------------------------------------------- +{ +} + +//------------------------------------------- +GenericResponse::GenericResponse(short type, unsigned result, void *user) +: m_type(type), m_result(result), m_user(user) +//------------------------------------------- +{ +} + +//----------------------------------------- +void GenericResponse::unpack(ByteStream::ReadIterator &iter) +//----------------------------------------- +{ + get(iter, m_type); + get(iter, m_track); + get(iter, m_result); +} + +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.h new file mode 100644 index 00000000..dec032a6 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.h @@ -0,0 +1,75 @@ +#if !defined (GENERICMESSAGE_H_) +#define GENERICMESSAGE_H_ + +//---------------------------------------- +// +// WARNING: These files are NOT standard generic API files +// They have been modified for this project. +// Do NOT replace them with generic API files +// +//---------------------------------------- + +#include +#include + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +//------------------------------------------- +class GenericRequest +//------------------------------------------- +{ +public: + GenericRequest(short type, unsigned server_track = 0); + virtual ~GenericRequest() {}; + + virtual void pack(Base::ByteStream &msg) = 0; + short getType() const { return m_type; } + void setTimeout(time_t t) { m_timeout = t; } + time_t getTimeout() { return m_timeout; } + void setTrack(unsigned t) { m_track = t; } + unsigned getTrack() const { return m_track; } + inline const unsigned getMappedServerTrack() const { return m_server_track; } + inline void setServerTrack(unsigned track) { m_server_track = track; } + +protected: + short m_type; + unsigned m_track; + time_t m_timeout; + unsigned m_server_track; +}; + +// Basic response message from server. In the case that this response to a request +// submitted from this API, the response would have been generated at request submission +// time, and the timeout value filled in appropriatly +//------------------------------------------- +class GenericResponse +//------------------------------------------- +{ +public: + GenericResponse(short type, unsigned result, void *user); + virtual ~GenericResponse() {}; + virtual void unpack(Base::ByteStream::ReadIterator &iter); + + short getType() const { return m_type; } + void setTimeout(time_t t) { m_timeout = t; } + time_t getTimeout() { return m_timeout; } + void setTrack(unsigned t) { m_track = t; } + unsigned getTrack() const { return m_track; } + unsigned getResult() const { return m_result; } + void setResult(unsigned res) { m_result = res; } + void * getUser() const { return m_user; } +protected: + short m_type; + unsigned m_track; + unsigned m_result; + void *m_user; + time_t m_timeout; +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/ATGenericAPI/GenericMessage.o new file mode 100644 index 0000000000000000000000000000000000000000..9dc7dfe2e7298de815060db033f2919935bbeb30 GIT binary patch literal 11860 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 hostArray; + std::vector identifierArray; + std::vector portArray; + char hostConfig[4096]; + char identifierConfig[4096]; + if (hostNames == NULL) + hostNames = DEFAULT_HOST; + if(identifiers == NULL) + identifiers = DEFAULT_IDENTIFIER; + + // parse the hosts and ports out : + strncpy(hostConfig, hostNames, 4096); hostConfig[4095] = 0; + char *ptr; + if ((ptr = strtok(hostConfig, " ")) != 0) + { + do + { + char * host = ptr; + char * portStr = strchr(host, ':'); + unsigned short port = DEFAULT_PORT; + if (portStr) + { + *portStr++ = 0; + port = (short)atoi(portStr); + } + + if (::strlen(host) && port) + { + hostArray.push_back(host); + portArray.push_back(port); + } + } + while ((ptr = strtok(NULL, " ")) != NULL); + } + + strncpy(identifierConfig, identifiers, 4096); identifierConfig[4095] = 0; + // parse the identifiers out + if ((ptr = strtok(identifierConfig, ";")) != 0) + { + do + { + char * identifier = ptr; + if (::strlen(identifier)) + { + identifierArray.push_back(identifier); + } + } + while ((ptr = strtok(NULL, ";")) != NULL); + } + + if (hostArray.empty()) + { + hostArray.push_back(DEFAULT_HOST); + portArray.push_back(DEFAULT_PORT); + } + if(identifierArray.empty()) + identifierArray.push_back(DEFAULT_IDENTIFIER); + + m_apiCore = new AuctionTransferAPICore(&hostArray[0], &portArray[0], hostArray.size(), this, &identifierArray[0], identifierArray.size()); +} + +////////////////////////////////////////////////////////////////////////////////////// +AuctionTransferAPI::~AuctionTransferAPI() +{ + if( m_apiCore) + delete m_apiCore; +} + +////////////////////////////////////////////////////////////////////////////////////// +void AuctionTransferAPI::process() +{ + m_apiCore->process(); +} + +////////////////////////////////////////////////////////////////////////////////////// +// Calls and replies +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::replyReceiveAbortTransaction(unsigned trackingNumber, unsigned responseCode, void *user) +{ + ReplyRequest *req = new ReplyRequest( GAME_REPLY_RECEIVE_ABORT, trackingNumber, responseCode ); + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REPLY_RECEIVE_ABORT, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::replyReceiveCommitTransaction(unsigned trackingNumber, unsigned responseCode, void *user) +{ + ReplyRequest *req = new ReplyRequest( GAME_REPLY_RECEIVE_COMMIT, trackingNumber, responseCode ); + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REPLY_RECEIVE_COMMIT, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::replyReceivePrepareTransaction(unsigned trackingNumber, unsigned responseCode, void *user) +{ + ReplyRequest *req = new ReplyRequest( GAME_REPLY_RECEIVE_PREPARE_TRANSACTION, trackingNumber, responseCode ); + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REPLY_RECEIVE_PREPARE_TRANSACTION, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::sendAbortTransaction(long long transactionID, void *user) +{ + CommonRequest *req = new CommonRequest( GAME_REQUEST_SEND_ABORT, 0, transactionID ); + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REQUEST_SEND_ABORT, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::sendCommitTransaction(long long transactionID, void *user) +{ + CommonRequest *req = new CommonRequest( GAME_REQUEST_SEND_COMMIT, 0, transactionID ); + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REQUEST_SEND_COMMIT, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::sendPrepareTransaction(const char *serverIdentifier, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xmlAsset, void *user, bool compress) +{ + RequestTypes requestEnum = GAME_REQUEST_SEND_PREPARE_TRANSACTION; + GenericRequest *req = NULL; + if( compress ) + { + requestEnum = GAME_REQUEST_SEND_PREPARE_TRANSACTION_COMPRESSED; + // compress and create the request here + char *data = (char *)xmlAsset; + CA2GZIP zippedData(data, strlen(xmlAsset)); + req = new SendPrepareCompressedRequest( requestEnum, 0, serverIdentifier, transactionID, stationID, characterID, assetID, zippedData.pgzip, zippedData.Length ); + } + else + { + req = new SendPrepareRequest( requestEnum, 0, serverIdentifier, transactionID, stationID, characterID, assetID, xmlAsset ); + } + + return m_apiCore->submitRequest( req, new CommonResponse( requestEnum, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::sendPrepareTransactionCompressed (const char *serverIdentifier, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *zippedXmlAsset, unsigned length, void *user) +{ + SendPrepareCompressedRequest *req = new SendPrepareCompressedRequest( GAME_REQUEST_SEND_PREPARE_TRANSACTION_COMPRESSED, 0, serverIdentifier, transactionID, stationID, characterID, assetID, zippedXmlAsset, length ); + + return m_apiCore->submitRequest( req, new CommonResponse( GAME_REQUEST_SEND_PREPARE_TRANSACTION_COMPRESSED, user )); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::replyReceiveGetCharacterList(unsigned trackingNumber, unsigned responseCode, const Character characters[], unsigned numCharacters, void *user) +{ + ReplyGetCharacterListRequest *req = new ReplyGetCharacterListRequest(GAME_REPLY_RECEIVE_GET_CHARACTER_LIST, trackingNumber, responseCode, characters, numCharacters); + return m_apiCore->submitRequest(req, new CommonResponse(GAME_REPLY_RECEIVE_GET_CHARACTER_LIST, user)); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::identifyHost( const char *serverID[], unsigned idCount, void *user) +{ + IdentifyServerRequest *req = new IdentifyServerRequest(REQUEST_SET_SERVER_LIST, 0, serverID, idCount); + return m_apiCore->submitRequest( req, new CommonResponse(REQUEST_SET_SERVER_LIST, user)); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::sendAuditAssetTransfer(const char *gameCode, const char *serverCode, long long inGameAssetID, unsigned stationID, const char *event, const char *message, void *user) +{ + SendAuditRequest *req = new SendAuditRequest( GAME_SEND_AUDIT_MESSAGE, 0, gameCode, serverCode, inGameAssetID, stationID, event, message ); + return m_apiCore->submitRequest(req, new CommonResponse(GAME_SEND_AUDIT_MESSAGE, user)); +} + +////////////////////////////////////////////////////////////////////////////////////// +unsigned AuctionTransferAPI::getNewTransactionID(void *user) +{ + GetIDRequest *req = new GetIDRequest( GAME_REQUEST_GET_TRANSACTION_ID, 0); + return m_apiCore->submitRequest(req, new GetIDResponse( GAME_REQUEST_GET_TRANSACTION_ID, user)); +} + +}; // namespace +////////////////////////////////////////////////////////////////////////////////////// + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h new file mode 100644 index 00000000..a3d85096 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.h @@ -0,0 +1,92 @@ +#ifndef AUCTIONTRANSFERAPI_H +#define AUCTIONTRANSFERAPI_H + +#pragma warning (disable : 4786) + +#include "AuctionTransferEnum.h" +#include +#include "Character.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + +class AuctionTransferAPICore; + +////////////////////////////////////////////////////////////////////////////////////// +class AuctionTransferAPI +{ +public: + // constructor & destructor + AuctionTransferAPI(const char *hostName[], const short port[], int count, const char *identifier[], unsigned identifierCount, unsigned reqTimeout = 60, unsigned maxRecvMessageSizeInKB = 16000); + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + // the identifier list does not have one entry for each connection, it is a simple list of world names that + // are handled by this API connection, no matter how many servers are connected to. In the case of EQ2 this + // identifier list will just contain 1 name, the name of the world making the connection. + + // the following constructor does the same as the one above, except that the host array is in the format of: + // "hostname1:port1 hostname2:port2" + // and the identifier array would be a semi-colon separated list of world names such as: + // "Guk Befallen" or "GUK" + AuctionTransferAPI(const char *hostNames, const char *identifiers); + virtual ~AuctionTransferAPI(); + + // connect and disconnect call backs + virtual void onConnect(const char* hostname, unsigned short port, const short current, const short max) = 0; + virtual void onDisconnect(const char *host, const short port, const short current, const short max) = 0; + + + //processing + void process(); + + // Requests Generated by API + unsigned sendPrepareTransaction (const char *serverIdentifier, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xmlAsset, void *user, bool compress = false); + unsigned sendPrepareTransactionCompressed (const char *serverIdentifier, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *zippedXmlAsset, unsigned length, void *user); + unsigned sendCommitTransaction (long long transactionID, void *user); + unsigned sendAbortTransaction (long long transactionID, void *user); + unsigned sendAuditAssetTransfer(const char *gameCode, const char *serverCode, long long inGameAssetID, unsigned stationID, const char *event, const char *message, void *user); + unsigned getNewTransactionID(void *user); + + // requests as responses to a call initiated by the auction system + unsigned replyReceivePrepareTransaction (unsigned trackingNumber,unsigned responseCode,void *user); + unsigned replyReceiveCommitTransaction (unsigned trackingNumber, unsigned responseCode, void *user); + unsigned replyReceiveAbortTransaction (unsigned trackingNumber, unsigned responseCode, void *user); + unsigned replyReceiveGetCharacterList(unsigned trackingNumber, unsigned responseCode, const Character characters[], unsigned numCharacters, void *user); + + // house keeping routines + unsigned identifyHost( const char *serverID[], unsigned idCount, void *user); + + // Callbacks that are repsonses + virtual void onSendPrepareTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onSendPrepareTransactionCompressed (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onSendCommitTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onSendAbortTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onSendAuditAssetTransfer(unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onGetNewTransactionID( unsigned trackingNumber, unsigned responseCode, long long transactionID, void *user) = 0; + + // responses to reply requests + virtual void onReplyReceivePrepareTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onReplyReceiveCommitTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onReplyReceiveAbortTransaction (unsigned trackingNumber, unsigned responseCode, void *user) = 0; + virtual void onReplyReceiveGetCharacterList(unsigned trackingNumber, unsigned responseCode, void *user) = 0; + + // house keeping callbacks + virtual void onIdentifyHost(unsigned trackingNumber, unsigned responseCode, void *user) = 0; + + + // Callbacks initiated by the Auction System + virtual void onReceivePrepareTransaction (unsigned trackingNumber, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *newName) = 0; + virtual void onReceiveCommitTransaction (unsigned trackingNumber, long long transactionID) = 0; + virtual void onReceiveAbortTransaction (unsigned trackingNumber, long long transactionID) = 0; + virtual void onReceiveGetCharacterList(unsigned trackingNumber, unsigned stationID, const char *serverID) = 0; + +private: + AuctionTransferAPICore *m_apiCore; + + +}; + + +}; // namespace +////////////////////////////////////////////////////////////////////////////////////// +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPI.o new file mode 100644 index 0000000000000000000000000000000000000000..b0b38e920bf97aacfca472219b6f30461c54e784 GIT binary patch literal 49356 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 Q>lorpO=}@SZnxn71Dr7!qW}N^ literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp new file mode 100644 index 00000000..c2ccccb0 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.cpp @@ -0,0 +1,181 @@ +#include "AuctionTransferAPICore.h" +#include "AuctionTransferAPI.h" +#include "Response.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + +/*///////////////////////////////////////////////////////////////////////////////////// +AuctionTransferAPICore::AuctionTransferAPICore(const char *hostName[], const short port[], int count, AuctionTransferAPI *api, const char *identifier[], unsigned identifierCount) + : GenericAPICore(identifier[0], hostName, port, count, 45, 5, 0, 90, 32, 32), + m_api(api), + m_mappedServerTrack(1000) + ////////////////////////////////////////////////////////////////////////////////////// +{ + for(unsigned i = 0; i < identifierCount; i++) + addIdentifier(identifier[i]); +} +*/ +////////////////////////////////////////////////////////////////////////////////////// +AuctionTransferAPICore::AuctionTransferAPICore(const char *hostName[], const short port[], int count, AuctionTransferAPI *api, const char *identifier[], unsigned identifierCount, unsigned reqTimeout, unsigned maxRecvMessageSizeInKB) + : GenericAPICore(identifier[0], hostName, port, count, reqTimeout, 5, 0, 90, 32, 32, 1, maxRecvMessageSizeInKB), + m_api(api), + m_mappedServerTrack(1000) + ////////////////////////////////////////////////////////////////////////////////////// +{ + for(unsigned i = 0; i < identifierCount; i++) + addIdentifier(identifier[i]); +} + +////////////////////////////////////////////////////////////////////////////////////// +AuctionTransferAPICore::~AuctionTransferAPICore() +////////////////////////////////////////////////////////////////////////////////////// +{ +} + +////////////////////////////////////////////////////////////////////////////////////// +void AuctionTransferAPICore::OnConnect(GenericConnection *connection) +////////////////////////////////////////////////////////////////////////////////////// +{ + countOpenConnections(); + m_api->onConnect(connection->getHost(), connection->getPort(), (short)m_currentConnections, (short)m_maxConnections); +} + +////////////////////////////////////////////////////////////////////////////////////// +void AuctionTransferAPICore::OnDisconnect(GenericConnection *connection) +////////////////////////////////////////////////////////////////////////////////////// +{ + countOpenConnections(); + m_api->onDisconnect(connection->getHost(), connection->getPort(), (short)m_currentConnections, (short)m_maxConnections); +} + +////////////////////////////////////////////////////////////////////////////////////// +void AuctionTransferAPICore::responseCallback(GenericResponse *response) +////////////////////////////////////////////////////////////////////////////////////// +// these callbacks are a result of a call initiated by the game server. +////////////////////////////////////////////////////////////////////////////////////// +{ + switch(response->getType()) + { + case GAME_REPLY_RECEIVE_PREPARE_TRANSACTION: + m_api->onReplyReceivePrepareTransaction(response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REPLY_RECEIVE_COMMIT: + m_api->onReplyReceiveCommitTransaction( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REPLY_RECEIVE_ABORT: + m_api->onReplyReceiveAbortTransaction( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REQUEST_SEND_PREPARE_TRANSACTION: + m_api->onSendPrepareTransaction(response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REQUEST_SEND_PREPARE_TRANSACTION_COMPRESSED: + m_api->onSendPrepareTransactionCompressed(response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REQUEST_SEND_COMMIT: + m_api->onSendCommitTransaction( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REQUEST_SEND_ABORT: + m_api->onSendAbortTransaction( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REPLY_RECEIVE_GET_CHARACTER_LIST: + m_api->onReplyReceiveGetCharacterList( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_SEND_AUDIT_MESSAGE: + m_api->onSendAuditAssetTransfer( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case REQUEST_SET_SERVER_LIST: + m_api->onIdentifyHost( response->getTrack(), + response->getResult(), + response->getUser()); + break; + case GAME_REQUEST_GET_TRANSACTION_ID: + { + GetIDResponse *r = static_cast(response); + m_api->onGetNewTransactionID( r->getTrack(), + r->getResult(), + r->getNewID(), + r->getUser()); + } + break; + default: + break; + } +} + +////////////////////////////////////////////////////////////////////////////////////// +void AuctionTransferAPICore::responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *connection) +////////////////////////////////////////////////////////////////////////////////////// +// these are the callbacks that are initiated from the Auction System. These callbacks +// will be called to initiate a series of communication between the auction system and +// the game servers. +////////////////////////////////////////////////////////////////////////////////////// +{ + unsigned real_server_track; + get(iter, real_server_track); + ServerTrackObject *stobj = new ServerTrackObject(++m_mappedServerTrack, real_server_track, connection); + m_serverTracks.insert(std::pair(m_mappedServerTrack, stobj)); + + long long transactionID; + get(iter, transactionID); + switch (type) + { + case GAME_REQUEST_RECEIVE_PREPARE_TRANSACTION: + { + unsigned stationID; + unsigned characterID; + long long assetID; + std::string newName; + get(iter, stationID); + get(iter, characterID); + get(iter, assetID); + get(iter, newName); + m_api->onReceivePrepareTransaction(m_mappedServerTrack, transactionID, stationID, characterID, assetID, newName.c_str()); + break; + } + case GAME_REQUEST_RECEIVE_COMMIT: + { + m_api->onReceiveCommitTransaction(m_mappedServerTrack, transactionID); + break; + } + case GAME_REQUEST_RECEIVE_ABORT: + { + m_api->onReceiveAbortTransaction(m_mappedServerTrack, transactionID); + break; + } + case GAME_REQUEST_RECEIVE_GET_CHARACTER_LIST: + { + // this had the stationID read in as the transactionID + std::string serverID; + get(iter, serverID); + m_api->onReceiveGetCharacterList(m_mappedServerTrack, (unsigned int)transactionID, serverID.c_str()); + } + default: + break; + } +} + + + +}; // namespace AuctionTransfer +////////////////////////////////////////////////////////////////////////////////////// + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.h new file mode 100644 index 00000000..d1fc41d9 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.h @@ -0,0 +1,35 @@ +#ifndef AUCTIONTRANSFERAPICORE_H +#define AUCTIONTRANSFERAPICORE_H + + +#include "ATGenericAPI/GenericApiCore.h" +#include "ATGenericAPI/GenericConnection.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + +class AuctionTransferAPI; + +////////////////////////////////////////////////////////////////////////////////////// +class AuctionTransferAPICore : public GenericAPICore +{ +public: + AuctionTransferAPICore(const char *hostName[], const short port[], int count, AuctionTransferAPI *api, const char *identifier[], unsigned identifierCount, unsigned timeout = 60, unsigned maxRecvMessageSizeInKB = 16000); + virtual ~AuctionTransferAPICore(); + + void OnConnect(GenericConnection *connection); + void OnDisconnect(GenericConnection *connection); + void responseCallback(GenericResponse *response); + void responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *connection); + +private: + AuctionTransferAPI *m_api; + unsigned m_mappedServerTrack; +}; + +}; // namespace AuctionTransfer +////////////////////////////////////////////////////////////////////////////////////// + +#endif //AUCTIONTRANSFERAPICORE_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferAPICore.o new file mode 100644 index 0000000000000000000000000000000000000000..a2ee71ea6ae146190b3277a5a792ff2ad36ec803 GIT binary patch literal 38328 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 B54r#V literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferEnum.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferEnum.h new file mode 100644 index 00000000..faf0857e --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferEnum.h @@ -0,0 +1,164 @@ +#ifndef AUCTIONTRANSFERENUM_H +#define AUCTIONTRANSFERENUM_H + +#include +#include + +#define DEFAULT_TIMEOUTSECS 60 +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + enum CloseReason + { + REASON_HOST_UNREACHABLE, + REASON_LOCAL_DISCONNECT, + REASON_REMOTE_DISCONNECT, + REASON_SOCKET_FAILURE, + REASON_DNS_FAILURE + }; + + enum ResponseCode + { + RESPONSE_FIRST = 0, + RESPONSE_UNKNOWN = RESPONSE_FIRST, // Initial state internally for call denotes no response yet + RESPONSE_ACCEPTED = 1, + RESPONSE_REJECTED, + RESPONSE_FAILURE, + RESPONSE_DUPLICATE, + GAME_API_TIME_OUT, //5 + TRANSFER_SERVER_TIME_OUT, + AUCTION_API_TIME_OUT, + RESPONSE_REJECTED_INVALID_XML, + RESPONSE_REJECTED_USER_NOT_REGISTERED, + RESPONSE_REJECTED_UNABLE_TO_VALIDATE_USER, //10 + RESPONSE_REJECTED_NO_PAPER_DOLL_IMAGE, + RESPONSE_REJECTED_INVALID_TRANSACTION_ID, + RESPONSE_REJECTED_USER_NOT_AUTHORIZED, + RESPONSE_REJECTED_HOLDING_AREA_FULL, + RESPONSE_REJECTED_HOLDING_AREA_ASSET_TOO_OLD, //15 + RESPONSE_REJECTED_CHARACTER_LIMIT_REACHED, + RESPONSE_REJECTED_CHARACTER_NOT_AVAILABLE, + RESPONSE_REJECTED_MAILBOX_FULL, + RESPONSE_REJECTED_GAME_SERVER_DOWN, + RESPONSE_NAME_INVALID, //20 + RESPONSE_NAME_TAKEN, + RESPONSE_FAILURE_DATABASE, + RESPONSE_FAILURE_SERVER, + RESPONSE_FAILURE_NETWORK, + RESPONSE_INVALID_ALIGNMENT, //25 + RESPONSE_WEB_SERVICE_TIMEOUT, + RESPONSE_REJECTED_EMAIL_NOT_VALIDATED, + + //NOTE: THESE ALWAYS STAY AT THE END. IF EVER ADD A VALUE AFTER THE LAST RESPONSE_*, THEN IT NEEDS TO BE ASSIGNED BELOW + RESPONSE_LAST = RESPONSE_REJECTED_EMAIL_NOT_VALIDATED, + RESPONSE_COUNT = RESPONSE_LAST - RESPONSE_FIRST + 1 + }; + + enum RequestTypes + { + REQUEST_SET_API = 0, + REQUEST_SET_SERVER_LIST, + GAME_REQUEST_SEND_PREPARE_TRANSACTION, + GAME_REQUEST_SEND_COMMIT, + GAME_REQUEST_SEND_ABORT, + GAME_REQUEST_RECEIVE_PREPARE_TRANSACTION, //5 + GAME_REQUEST_RECEIVE_COMMIT, + GAME_REQUEST_RECEIVE_ABORT, + GAME_REPLY_RECEIVE_PREPARE_TRANSACTION, + GAME_REPLY_RECEIVE_COMMIT, + GAME_REPLY_RECEIVE_ABORT, //10 + GAME_REQUEST_RECEIVE_GET_CHARACTER_LIST, + GAME_REPLY_RECEIVE_GET_CHARACTER_LIST, + GAME_SEND_AUDIT_MESSAGE, + GAME_REQUEST_GET_TRANSACTION_ID, + GAME_REQUEST_SEND_PREPARE_TRANSACTION_COMPRESSED, + + WEB_REQUEST_SEND_PREPARE_TRANSACTION = 10000, + WEB_REQUEST_SEND_COMMIT, + WEB_REQUEST_SEND_ABORT, + WEB_REQUEST_RECEIVE_PREPARE_TRANSACTION, + WEB_REQUEST_RECEIVE_COMMIT, + WEB_REQUEST_RECEIVE_ABORT, //10005 + WEB_REPLY_RECEIVE_PREPARE_TRANSACTION, + WEB_REPLY_RECEIVE_COMMIT, + WEB_REPLY_RECEIVE_ABORT, + WEB_REQUEST_SEND_GET_CHARACTER_LIST, + WEB_REQUEST_SEND_GET_SERVER_LIST, //10010 + WEB_REPLY_RECEIVE_AUDIT, + WEB_REQUEST_RECEIVE_GET_TRANSACTION_ID, + WEB_REPLY_RECEIVE_GET_TRANSACTION_ID, + WEB_REQUEST_RECEIVE_PREPARE_TRANSACTION_COMPRESSED, + WEB_REPLY_RECEIVE_PREPARE_TRANSACTION_COMPRESSED + + }; + + #define response_text std::pair + static const response_text _responseString[RESPONSE_COUNT] = + { + response_text(RESPONSE_UNKNOWN, "RESPONSE_UNKNOWN"), + response_text(RESPONSE_ACCEPTED, "RESPONSE_ACCEPTED"), + response_text(RESPONSE_REJECTED, "RESPONSE_REJECTED"), + response_text(RESPONSE_FAILURE, "RESPONSE_FAILURE"), + response_text(RESPONSE_DUPLICATE, "RESPONSE_DUPLICATE"), + response_text(GAME_API_TIME_OUT, "GAME_API_TIME_OUT"), + response_text(TRANSFER_SERVER_TIME_OUT, "TRANSFER_SERVER_TIME_OUT"), + response_text(AUCTION_API_TIME_OUT, "AUCTION_API_TIME_OUT"), + response_text(RESPONSE_REJECTED_INVALID_XML, "RESPONSE_REJECTED_INVALID_XML"), + response_text(RESPONSE_REJECTED_USER_NOT_REGISTERED, "RESPONSE_REJECTED_USER_NOT_REGISTERED"), + response_text(RESPONSE_REJECTED_UNABLE_TO_VALIDATE_USER, "RESPONSE_REJECTED_UNABLE_TO_VALIDATE_USER"), + response_text(RESPONSE_REJECTED_NO_PAPER_DOLL_IMAGE, "RESPONSE_REJECTED_NO_PAPER_DOLL_IMAGE"), + response_text(RESPONSE_REJECTED_INVALID_TRANSACTION_ID, "RESPONSE_REJECTED_INVALID_TRANSACTION_ID"), + response_text(RESPONSE_REJECTED_USER_NOT_AUTHORIZED, "RESPONSE_REJECTED_USER_NOT_AUTHORIZED"), + response_text(RESPONSE_REJECTED_HOLDING_AREA_FULL, "RESPONSE_REJECTED_HOLDING_AREA_FULL"), + response_text(RESPONSE_REJECTED_HOLDING_AREA_ASSET_TOO_OLD, "RESPONSE_REJECTED_HOLDING_AREA_ASSET_TOO_OLD"), + response_text(RESPONSE_REJECTED_CHARACTER_LIMIT_REACHED, "RESPONSE_REJECTED_CHARACTER_LIMIT_REACHED"), + response_text(RESPONSE_REJECTED_CHARACTER_NOT_AVAILABLE, "RESPONSE_REJECTED_CHARACTER_NOT_AVAILABLE"), + response_text(RESPONSE_REJECTED_MAILBOX_FULL, "RESPONSE_REJECTED_MAILBOX_FULL"), + response_text(RESPONSE_REJECTED_GAME_SERVER_DOWN, "RESPONSE_REJECTED_GAME_SERVER_DOWN"), + response_text(RESPONSE_NAME_INVALID, "RESPONSE_NAME_INVALID"), + response_text(RESPONSE_NAME_TAKEN, "RESPONSE_NAME_TAKEN"), + response_text(RESPONSE_FAILURE_DATABASE, "RESPONSE_FAILURE_DATABASE"), + response_text(RESPONSE_FAILURE_SERVER, "RESPONSE_FAILURE_SERVER"), + response_text(RESPONSE_FAILURE_NETWORK, "RESPONSE_FAILURE_NETWORK"), + response_text(RESPONSE_INVALID_ALIGNMENT, "RESPONSE_INVALID_ALIGNMENT"), + response_text(RESPONSE_WEB_SERVICE_TIMEOUT, "RESPONSE_WEB_SERVICE_TIMEOUT"), + response_text(RESPONSE_REJECTED_EMAIL_NOT_VALIDATED, "RESPONSE_EMAIL_NOT_VALIDATED"), + }; + static std::map ResponseString((const std::map::value_type *)&_responseString[0],(const std::map::value_type *)&_responseString[RESPONSE_COUNT]); + + static const response_text _responseText[RESPONSE_COUNT] = + { + response_text(RESPONSE_UNKNOWN, "Unknown response code - default."), + response_text(RESPONSE_ACCEPTED, "The operation completed successfully."), + response_text(RESPONSE_REJECTED, "The operation was rejected by by the auction system."), + response_text(RESPONSE_FAILURE, "There was a general failure processing the request."), + response_text(RESPONSE_DUPLICATE, "This transaction was initiated previously."), + response_text(GAME_API_TIME_OUT, "Unable to contact the Auction Transfer Server."), + response_text(TRANSFER_SERVER_TIME_OUT, "The Auction Transfer Server could not Contact the Web Services."), + response_text(AUCTION_API_TIME_OUT, "The SysEng Web Services did not respond."), + response_text(RESPONSE_REJECTED_INVALID_XML, "The XML format was invalid."), + response_text(RESPONSE_REJECTED_USER_NOT_REGISTERED, "The user has not registered in the Auction System yet."), + response_text(RESPONSE_REJECTED_UNABLE_TO_VALIDATE_USER, "The user account was not able to be validated at this time."), + response_text(RESPONSE_REJECTED_NO_PAPER_DOLL_IMAGE, "There was no image uploaded for this character yet."), + response_text(RESPONSE_REJECTED_INVALID_TRANSACTION_ID, "The transaction id is not valid."), + response_text(RESPONSE_REJECTED_USER_NOT_AUTHORIZED, "The station account is not authorized."), + response_text(RESPONSE_REJECTED_HOLDING_AREA_FULL, "The user has too many items in their holding area."), + response_text(RESPONSE_REJECTED_HOLDING_AREA_ASSET_TOO_OLD, "The user has an item in their holding area that is too old."), + response_text(RESPONSE_REJECTED_CHARACTER_LIMIT_REACHED, "Too Many characters in Auctions."), + response_text(RESPONSE_REJECTED_CHARACTER_NOT_AVAILABLE, "The character is not available for this transaction."), + response_text(RESPONSE_REJECTED_MAILBOX_FULL, "The character mailbox is full."), + response_text(RESPONSE_REJECTED_GAME_SERVER_DOWN, "The game server is unable to process the request."), + response_text(RESPONSE_NAME_INVALID, "The new character name is invalid."), + response_text(RESPONSE_NAME_TAKEN, "The new character name is taken."), + response_text(RESPONSE_FAILURE_DATABASE, "There was a database failure during the transaction."), + response_text(RESPONSE_FAILURE_SERVER, "There was a server failure during the transaction."), + response_text(RESPONSE_FAILURE_NETWORK, "There was a network failure during the transaction."), + response_text(RESPONSE_INVALID_ALIGNMENT, "The alignment of the character for this item is incorrect."), + response_text(RESPONSE_WEB_SERVICE_TIMEOUT, "The AppEng web service failed to respond."), + response_text(RESPONSE_REJECTED_EMAIL_NOT_VALIDATED, "The user has not validated their email with the auction system yet."), + }; + static std::map ResponseText((const std::map::value_type *)&_responseText[0],(const std::map::value_type *)&_responseText[RESPONSE_COUNT]); + + +}; //namespace AuctionTransfer +#endif //AUCTIONTRANSFERENUM_H diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.ncb b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/AuctionTransferGameAPI.ncb new file mode 100644 index 0000000000000000000000000000000000000000..6868f84d57ae29bed1f197222bdf5033eaed7ce6 GIT binary patch literal 265216 zcmeF437p+UmGA3+yVL2;+F2lba?=Uf$wq*rfuuW~PSRvw*aJzY`zGno8@+^tHJ~Dh zh$0#WHy9B`TyRH4jpI5qDvZl0&bXn2%yV4cL+9}j$ou}P>c8E-orKUh&V150m4E%u z|5Vkf?bJD^wslPn9c`U$ySlP9^J-?#&aT_CGJE#i`SS-47`tMN;jh@3fJYJkRpHm) zOYU*<|C1$fvIPE{m%wxX^v7q9y!QrjanP7w1_!Shl*-V-BPah(mcYpp_#ayWrj&tw z+f5qc&BF1c&pG()|Jbaa%-G2iI9URDC2;rL1wrodb;~Ex|L^(cBafE7t7XH(xBskp z!S>oWy&qX%UTb|zu9HW@&Usz+9lLW~O|84y+qxvdHMMqjHRg8t z&>gv5xsF_GL#{3_f_V*<+cqxR*51*!H`mbBxvjdpp{uE_b!$g`YbQbS-&a9U^~Sn< zFrc{&?d?g*`Yhra^3_L?*X*h9sBh@Xb@Wkun{!un=Q_LkD7LK)?Q5HMcGPzq*jCfr z)^KItM_aeCy0Nh%*V)w$@gfDGl^hiGE#uYyIv%YaPq$ zJ9FErI~w*h?dz)sT)lNwt~J-u)Sx~XdfS`&u!|H*q0dXbP$KJSmK1&;)oUIb6Mx$C z>T##Oh&tv?eGyy8nffNK&i1y}&Rn0AU=JqO7ZfHUjaghDN8FRa^?d?~j@I{)udZ)x zY|eFb_H{KNn^t+}r3!uj*h*tW0X>}^f04b9z+xow>XI=6KlXwOBx#);wcwr^kG zuybQ)uDh{qs};<*Z|{TQWpmDR+P;yc!@{a*Xre0?!pZ#|d6$ z%oLvYfjEihr+7b&XDtq|c@yy{UvB|_JkKGdE9>mzWO5|W={Tj4<$XBM7kSC@ynw({ zd0s)f$NK<{?w$Cz0v|-fybu2l+`kg07}yLN_gC?c z^Kol%YjNvv>v0=!8*!U(n{k>0-HN*acOh;U?kb$0F)(fabg0)a8lraq9eHT-$Nvu*7s!uidzPxT|quikIN7!Ci{G z3|EOe2X`*+Jls;;&A4T_ZMe&ESKyZ5#F)e^PsOQ8iSf1JsCvsx#W=(y#Q;O?F;*o1 z$Bh4~;+41}+@7<4@wK15xPL?zzyAJG<4}LnQkOXD_#-6R&0*UR@#}9BeQx1bpSO)O z!+R+$ca>nd`gY+dQ$@7i*8vNPZnbztKn7B)7Ye387O#Z1R$(%qD>j+ZBA$VH1K(}~ z=Yu%;FXh>SJNb9A1WuN~U%mt;GANW}H&(m;AHd(wGk=7cmxz?C{>vcjjW9!n_pKK^ ztjNsgce-Fg$?Csi#?$l75f}EbgY{$Fn_@PC*B|NM!AckhCY$AgZP~KY!TK}Son`6- z+qz-1gOxHa&NR(}Df+DbD`PybF_)!a0~ntw&ABPqK*rP4O??VBh_Qc_sbH{=;~UHv zI^KL5K9ujCVo=@!qx%U1>2Bgl`t@x#1KLb7e+vVu_}JyVD~>Td^-V%@H{ACwTyNhC z!M{bgU*Mj@4J<}>z%9ZR!d*n#zu{Y5f(Dh+$-k2&aJ(h(@DyaU5%h?xlNHNQmEQzx zIPEWlX>6A=xlrRYc#`Y-(f_TS;AICXnv3Bb?;&i7kFVSW_V+1Z<-}JtzY2vkgG^d( z(y$U_kW(BCxx?X=BDan;ty7&6yV`~=LlT*4E*Fe69BhE)F-udhfk+({rW9d&m}pt7 zI0jjs@EmwCY%q%Y9P@MvHUy=6wt39Q=V&QM+L>VBm3 z>?z1VlTz~2F!Fi^8j6*l0t$}88-^r)4nHeDshllr95VO0Cezg4WTuqh`cZnrOlIo< zli6N|E5%Ww+lQLW*de&VCQ~s8H;^!J?%$3??i#_fD8=9Yjrw>IHyAp_vzp-9oA8Ur z>6!G4?>r7nPleI*ZXZs5$#N?RFTZ5D3HVR`{r4$>5!740{6EXVY+qMS)QfBLU>REC zraYMV#M}PP>7n8i`YYyVd52!I`cFFO7tNi770;;33Q`JB8I}hdh%ULwjNSp>;Qkqh zH`qLC9y6tkyX8R`c9{8~`G{#%d~3=*-f;BRE6fiWd*d`tMNi&sCey~tUkc+JYxbg5 z%f1lfWzBod`_1a&By1`=f43Qz!kcdPo9oQ|iZ7yN9>%gynGdJ%7GfWGjd^b>zH_h- z+++5m(8uYnFz+z;nQK#cwb&jmHuvsH%2_Lsxk}8BQm|E&V5vErf~`i*>2Le@XDFNR z;C_Mo4XzlPe}qBc0Tgld|8oh~h*ST6J5Eo@HdQ#it8WXo11GsA#OdullzV!^+e@8> z-$Hq3b$wdi3BMRg>WWefOv+o7M}9^5%PKq{PEj7 zO;$FQDHu9uneXqWZH~o)VqsJ5IM9IMM>Z1&I}I*9+HBjEgo)!%GxG!+i*>_>)yOd2 z+=bC54m$(8%>uJjX_&Ua;Yq@sX>Lo!HwzolY38#j*lauQ{c|oE-yA!}9ZA7X#}GZy ztVzM<+Oez1rW@vCo|VB{!0YS&pWoNZ%okk0j{0V)9skq)e;^vhM%ULNv5GR3H1Zkq zdDqt?*f8^u`LOHj5o|bis>^%y^_^JiY+sM?#$rcn>CxB!);!pwueX~n*ViLHF&*33 zwXUy6@y#=jm`}RC9`UDz*adHPeLV>CaSrytL$0q!uodQB^PV1keGAsU{J!1~Nh`mv zt6%5$b@2qX?UQ}I_r9+FpP7hkM32v4tIE*tGxVYioiRg?$iPE0$Z8oRw#>HiCet+$ zhn&?p)@16(n9QD0d>f5J&cec(VT6))oI#$;FoI6ych=k!)L z$HRXgo$Pq<7bY6>UEI^S=W*i8--L(Ho|J}#d^zNu!V6(4gYaG7uf+hIKmPxUS*mgj zw^dmhyD1`vqs&KBu>MHq6U~0XB(Gb%GD>iIO3szOJ`ldDJYLctTRdY<=zoH+AuVsl ze<=7^u!X@e9uJGn=Yp>UUxAKt!n-v3n{$G@g8?bn5NdOqu`sB0c&A|NzS*3Witki< z>-1o63O34oE!dHHF%{ovvomuzGhTR6x?`~Gf85-S;uFKhny+Naiasw`-H41!cbu6O zED2P;a?kQD^#71Fp1~>q(|In%U50x-?mf7V;PSs6NPMry@Ehkv{g*-aB_S-}GM$yjp^VM_oxm^kz}v&O=hQL=bN)?W8+g^lov>HmYw zM=dPG>j#G(Y;H*5^@kgknR^8LUa^(GMp^ze&|H#Acc7J_Zcl|B3@0C8o&i=Ir8~sR zP*)K)Fy^qMZ^%%+ABjSKgeR;L8?98Cci|E0etd3^rr!1f$6794r*mnQ)6? zS*$FJ%&HV@3YOAJb8`wd1ItT|*$jO)?7}M2JspnqsCn*k!ARG_79c%6Vj4miHkDDt ze=D=N3oR_9M4!&6~_y%oP@|$d|!pq_!r;-ei0iG9P)lnP*|Y_js3@9n1oMKUD@-FkgG2 zd0z^)6N~Rg^Yc{MH&~f_KC*9IM~znguSH%jF22>bwVe3|zbr87*TZ(3zc){t!N5u= zQ&;DEC_`E>%4X)XjQJU4fTGioGp1pKk!*mBaG~S_$qQ3W2E$k856Bt=kvp~_cSy$A zhP=^*yfGI!gPGdQjmRK7kWUUv))-~}g?e2<9xlMWAOB}@ufg4xcy8xg8}2P0{vSLw zUhD&QBTnN*IA-L_h*fkZ>4TS|BWY|YBxkfxuF@a%{guibibL{<1JLboi1 zPl#tdl7fw}JnLUlu#uJ*9TLpzs-?8Wf&6Z=FsFl-(%!@u|7~0{-BGrkKYmFPHrndB zqf=>&LFOA_&Pl<>662|6V+uBolut299k~<^J(8c*k;l-mva;@I7P!Lc$aEzKn~3y1 z#p%Nl-XyF0CiUS`kTqXq^Z$9C`q#m9Imyd~6-Yz#9Kb+m*UTF&o1#23=Hgf>;n?+Yo|>86_B*FJYxg6~EGpSQkV4499DcrN5*OAMjpeer0xC<#}>e{IG~R9hL{{ zM@yJ!9!lZ$CpSyYyHYUK-gNT^3c-#UHoiev`nH<4r(i?i=9ig%4N1IVSoP}7_je{? zBdlHT5;|8L-)QV`kD3pr;u~u|XTD(NP{r#S{H=K46hSfa5 z^La4YrR>_F1l~aN<4h~V6sTTb56tH>U&x#{ED6i7w(YZ~4B}$E5>uDimHCQbnOn{3 zED>M}`&#DPnF|zO1S>U)e}vey6UPPU2W1ZG&hBPrVq0@BmgKg-G|N!ex)bVz2sh+m}(+k-8=Q7?- zcCt-0w=s{R$QsEuHMEIjzmEEUf+whIZU6VWzTVZ>-yohq8&J9GPkdrkDeD9huo5$< z=r%fVY&Q$cCxg!fPZBn^n-#_OzmJw=spG)Hy_CKg_cnSMo1WVZeBG_Nv z{+BfhM@yU@Km(Yfo<)vc{x^90h}rN_&*FMGdi z|FZ34>uhADEL`qHR3C!wl>cs>{s1d zpMlit5Pnw)#&_AO29m;1e#?O^!e0ekFzLA#_EO2l5GGyK(x^L_AT1pl&W11D-U}IM|y^VHL zMw=_@ZvqsKOd0L2NOM7&XHr|C4Sh2J?%IdsY?Vzo&W7(#5x1P`No5v(A95OdAnqEl zoW#t$GmzI7YdMqFU!JF2r2n$+H83Sr;fJplmyUhkSOUNNKL$Ae2TwPLSD$~^aP#I* zUi_&`!`K{Mm6bc8X?3l^I#`O`a7y^u2i`%Bl7IGdw(8>_no(Yphnhq?hX3dNS7#2M zRXfDY-1Pm@x=mMgy>0F4@pl}uX|+DE&X(7;(DeMua4*7~ycl=ny`MNOc@Y(S{o&I^ zrqkDB@ha+co%VZVkO0=C@of$Y((>BPZu^MIx)7?B6a0H{Yf&~gqweA>KWT0FiY4o! z(ir}J>T|f4g9MfR|EFw%DT!nP+w#p!$xvRt5ton+CCNL)WlPO{rdv9XBFaiW)U4<* z^G6q-hZPYwdj*h3V%e?O_RV&5l^E8Ky*$jFCu}2w2&Xl{8_;J$+sGjL|4M#u6)ZU5 z<-<~IL%C75k%*QubokZgG2un90Y)~IH!9sob{lA__|;lk=KA;sS^LYAsj!3D6SK^G zAVu>KEFeqGr&BZ!rT3m^4yW+S?OMM}uoJ|z48vknm$DrWVjPk^Cuutz1ph1N=WK_2 zJ$)l7>p{la4!sR(5M!BajLvq5FmLPQRLgsdr56C%911@we@v7Qiw>CQ(>@OnZ-^8$*|=?QV0TxjjK z)&?4t{TYntlTtR&L6oS*;4e0*Ju{SK)%VY2+?wy~qCSmTz!tND$J#}Ge09J^Fw51k zSG?yYlOb#!@7HO)onYk6!Ok}C;^*wAL}>9ATf1%2ep-iBbqhahKlSO>(UvddXYHpE z>>TEhHaq)i1Ur`%co#eSX#_hDd*vo;KMl*Jjy}GTUwMKL)xirk@cY{YltT*Plx zf*;huZ`SjhA%0M@%J$znxYas-3lyKP%R2bnT7FL__(mQ4a4WxzjnC=Ab#SH&_;sh! zSjkAU#(czyT|K;o#?(%*9%Z zyaabHZmr4uGjetj@-w~P&2=G1zgTNB!7|>faLaKuxK$?eQAUA}Nq*LP8_7zNrzK<8 zF&DN1Ieaw^S-TTiDu?_%HYh?O=UTiWY(}69- zEyA6JJCAgkXZsj)a8~x8!E-)t0gjPs8#+Q4dP5g_Lg#GKokhBH`KD3&Oxzi`BHY{Q~t7%i8;rY+FKhmx< zw8aYCY})DH^WMhyWxUs^-QuS3zHdGA8ibb{fZMyHcYQ?PlJ?xc=6Szlzg|UKRG&-s z>s9oB^;g@keIH&$Ur;}^{o41hRkUaAopSx!$rr2WFXBbEU;FWU75ztiEZMJD(f=hQ zxPILhs9&$5|6j)Hx+~PL>GRv@|6TOeF8XvQeLF{=o-6%GeHz|DS!IyL z96x~vh!?0&TfLh;zmh&2sNbp2hW#2oWOaD@EwX2Z5jKNl;QFlkG<~^C{hGenNq^4G zBu({O^;z|2^?mhe^>6iM@do<7yf{Y z$HsrOeyp`QLxWo_pQq_i8yA@Mz=ornYdjT9b4yFmHc*cbhcK-{-6cHi%OOlM{MEop zqWGMiV08kIH`xTp0~hWvY}$z#0pSS3yf$ zW**B5FN96AdcsoDkPXV=&9r0oP{GEAcysKS-JF8Ww=%%bYK(te`3Tb$w^(l8W?`kCzBNwAu&^-Q4fNQhrYRM6i`6^M zO~Ed*a=qPCVZw60*vhYNPX%@xTlU+m+&sBR5r*Awbpp4iB81&!<@IP!g-!PjR$g~|D!{Y# zdpnXUefuBa51A4i{odLMkxA;|Gi~q^Hl1aP;2TC`Iy}V6DTE2v>1fRk6Tg{y_|~3K z<`It+KNFvXzgc-kwnND`$R(6e=5+B!$vW`Be~4{7h3tjrwbGt(vI8B`*(*9={HAP#({>OU=i|l{0^-=FB`=9V^8VUO!wmupzcnSNT z@Ms??`=4NzmW2J!=Pk1TO+tnZ?SGSK6NT)5lLBngt}a7+UufS8-+QzF(e26gXuGFS z{$bSCd**5W#V}%>VxAi5{2D74A!i9b1R1$xv-1z5?tZt_`TG-(>;b|V&UmS{3-S-3 z{IAEhD8F)g{$S_t2R|>H;rvCki>c>0|Bb{Wdxr1_6Oa0){6lb0&369&^a1V3bny>0 zm!0kW3yJ>?KCJ+Mou|13nospzFhjEqH(W{|--Qf9U*z zkAFDvYcHyBWc$uwVwAs>yzlqeU+l9g z^>%_U4=7wX-|$grnhbA}g{2(MpZxRd`VYIdg}%;j7y8I>&La$ATBBh1`g^%v;pdnM z!JEM=NA9f33Q}Z#3tRc4g)wegSU)o`7#B=w7G9T!m9d8UNi)>KLcD>jOaHj}PAcqR z_Q<~5v|HFLAGRDz&H=Z^px^sSL|;J6GfXzfEX$Y&!TlKSYdF=t{7Kk(q^UJ9g6sJU zp2E`_>DS^9=h-S2G7i#YkPwk_3fE()viukLJ30SXxR6iI|G{QX_%ELSdxAbObZb#Y zeTivj^LAFDJqgT44ouHG%$wa_A7d<^5Ui7*ohS5R1?%GX$YOYh@0)^k^Rv9e(4P+?&k@ z!RsI4jbx9^Tg@kdEfT*Yok7TgZ|4`>ir#lAHm@tu5t`8%7$Mv`6m-Fr=$^aL59_g~ zUWu;ooqpzTi6ftvC1J;M0Uum6AX^q5T5Kv;H3zVKhFDGP%V5KQ|VR zV#lK0|93v~Cad7_d$9F2V^hp9S5bn*eJ8fScVP#7m+XR?U(j5IY>LEgXBR`bD8wKntbB%dDHbI&CRbCT# zG;+R$+M@&usOi4XAkPr=))o2S->{4*Jnc_Y!$F-tm)1c$xGH4!4mTm z5llL=wNLUr#FKr;+9#(VnPgp9*({T5mg+z+L*j|{JI$|RCMtlgp)rgxrH*h~a}(iN zSP9a@F!No?w45|_K3N@7mDWN0r(neGU^?4ulqu>!7RmIpvPd1NYTaRZ3O2y5k+FNK zh!0sQsIwBq$aqhcO?NO_-SBu%m4ywnw)8hpN0N7B@2mqyHuq?smBky$jM{wD44!C~ zy|WHmnbzDtKwT2dma$-(kFhY}0T)c?=H%n)EJq7d-aMYxRORDojwT=0NQ=pbT}8{v zhh0yLiS~xse2ixHa!I^5%)-Xnxs6A6y0Uk98^_FMrHS^7S-h;3U4NS@tI5cL2jV?s z7HYM&CAW}`F&3?;&U+OsQB%0cpkQb z9ptYwzfHkvITQO0=K2(DC3^lX=Ft>v6?@Web^GWdn(H`4>ow+F@F30F^y`?PmJA;4 zt+O<5we#>#w&BCjadAr!`;P+;Qjq-a5 z^Xr$HovHXVlYXh&(-+aa&8{6P0p~ zfoU$*(znO19rz|ZF~)1M^N>FgUX+i$c0IuxQg~OA4(kL`ux2}7Y4;aKG`BL7x614U zFQ&Q8Xs>Bz06NNe?A&F{X=NGDb}+6LGv@7J%&TXt+cDAvFR=cmj5Pvf%#H0}ZfwA4 z6TF?d`7*}6GRDQCsU~=l@vn^Wv5finBG%yym`*t6+RB)FFPjI9Is5^dqn~4fTE@XL z=KRZ;ug_}Ue*xhcJIh$tQ^wk(9jpN;V!cBB68y~L*RyV62Wtgr&%wVij+U`bp$yuy ztSQ)01HH?6E(4FXLp!R#t2RL~^Lb?}aqGcb2Yd~9=ksJeLj5Y9YZ;5{Oy-4Rlle6I zSy>TjqQ9XwXX^X$9ZOL?I^7PZb4l+??zg;>_Vja{Y?zN%yXWV47hJe~$$?$o!cnZm7 z2Pp^b<5XM?yr;)QHygV*A5Tnui8J3U`KI(( z&N3cg%hj{~TQ_ zYEMNO&|bb_7CtVCa@_ud1u(-#n*3DJ4{87$G{x1W)yXfh-_f<@g7-j^_Vr2!aau== zbG*KTy&`5)Un){>?432QJqW1OlrKk8s%Df4{5-eGtXeE84<5{y+Y|A+M;~ z4^rX9rR6tQy_WI|sZ*Yo9-(si(Bl;&X86&atx@+x9|Th$J&0|_W28>rvp56nlMj!+9kbojk{KX^ez zp*$@8dZmAi(C~RbK0Yg}ZdpI02m^LkSMKUOInEP&99{;zR+8ccSwy=nI6Zrt`lbI(|Q{(%qw*o~$= zzr9RIl^+_TV8!N!Cmg>|>;F!w5LzBte=+@kpC7mXn)QFpLvCOVKppE0qjCGDUdC+= z@cO&r#h1R6Uk&cd@&12MmzpR3E`7)4oV)S^SC1$4|3t|Y@*Z|pmr$Sm@3{Uy&Q_`+ zoz(wNuK$lYgBbTo{Xgz1C*b>Q)&G^1z0aO$^|ag98S?~cBdal(6PTOIrPm}=u=pkW zU_WNKj{283`1g*xU?Z{ts_g$M zE@vUf```ch^iQw9-Xc4?>O1a&CY{$Mi@ny?#Cl%AI1d(tCV<(5-+J>3{os+CzWDpk zpX0FHB-!B?Klh9|{4`xPV~YQ7z1AmmcK(`uuDZ)&7WK$U!{8sIZjQ&UpQJ61F8}Gs zr!V}J7cPI!Dir-?&3*ho>Z`JwoLv8}5;^*xTmOH)o#)tGTYe?`@tU3eD+p~liXfE# zjviSbe*HNoG@xgU|Dfd)o1y8KIGt*s{Vmbo3DUJAiokmcx37FG-Vcu(%Kwh8_myZZ z&w%rdy=UwjJfB_V)(&a?kkdvFc=|8RP*SnHnCc>j0&+8?O+tMv)W;oCUjCuvCfgOhuT=mAfd@!JzwvOD~J!W2O!_IjvZH?W{xp@sI6m`v>`i}aBu3Sf- z#I`wiRd=qltB>O9Y;SAr?3-+EZD?QHw6mkW=C+0_`-H+oq;(ss8yh=vot=Fh zF=;Fp!PU+DU*FZ%7xnZF`p?GgoGn0qUe0qO?vKm~*6|#QYsQ_9)A>?5PwEKYu3OJ{ zoX$kh8K7D}uXBWS_Rk#^>;uHucpoV|L+wg!|=E?mJ@nfc7YAPonNB*Zt!EYbIyfh_RxK1I`>oOeCiwz zo#Uxnwepov-tZbvCBX$Jg1H zI_t6lJl)-+`)qYqrS7ZMnf1DVM`zL>!RbDoBH+3&M`y_EEJ&RzraN$S-lNWP)Y*;q z<8=P+Z*e-8Lg!j6zzxOe3=N&rp?#Lx3!=Rr+Uv1@73D*^x|2=!Y+W>ndkM(5_HqBJ zmN3-gP~2DM81o6-_ZCuaxLvd0x9Ds-$K*!d#m{vvr0#M1--~Idl!?xN)OnA(A4m7$ zlu~y(ukmkr*ST#vr%mUw=^VBU?>cAgK!!Uv;q#N|Cl5{f!P`1NwDe~y7r#(+$HmXz zdGDjYx^d8NZe0G(6)zqB-7ju_zUbOJuX)dxZvNugFFkoj)$Tt|T>8QPcj(BuNB;cx z&mQ>mq@R4|+Ux#!Ga^!+%Zk%`fO9yV9{f(d9^Q)iz z;s0IxT<7opbY$7zUAun&3%5Ue|3|R={XgUv7R#7g;*#8rSP3-@nT-<(+6WIR~rF#PVe^ei~ zy(ISk2xjwf%>6%}=EVM=C?Bul{-22E#QqyWKmFMMbA5sRKNIry z|9qmr{-2L!O=|zo6u>l>I-Y ziTyuC1@`~+WB(7WBlBDK|8Tr|kNrQz?Efidd@YW3z?1ub(tCiUD@#W%w5O@io}Gg` z{tNd1WVHtBSoi;)Vr7R>tZvp`OMm~bhw1*`@A>v;SqR$0dP|B4pjoyh&azxQE}b^kACZrU`G_y30UCGYcp+ju>b#S?34T={PHjs?8EGXJPiLk3=i7|&ntBQFVem{=UiuszPkJW$pwGx60x~) zZ}$K4gg0H9EBdlx&@=J;7s&Iat5c);d3cEN@vG?=HKZKS1x<^m`5$HJ5SLHvQ zcm`EF|AoZ!TJ%A|hmr0jp5_VAJjc^H4mza=3a3^yT;}{!&{kx}5PS&n{A#T8_d_<9 z-9d2KW@Yz~Usz*CIsZsBDy?4>ydVF+-**f@{g+{15zZ;ZsrwM+A3&LW(xk0tL9`7#+v ztPe!=k2MQD{llUE%Ra2;cgnCWD9$osl@2X`H8g7txBLr8`Tix&UjYr{MC za7v&@XA;Oy&aJ*J|7zmNY;*9*l=%XmN8MQ>-Cj8Tso{U{G*5tLon6O}Vs`xWP;irv ze+cpa!qeOznl*2vuw$V?=i14y)iSc}$UlH|bJfnj9*Sh65SnXMTJr&=~}R>jq)j*5ubsB(g=xubU{f$4mbH!svp2 zzJ`ylg7*R3=zb>|DTlJEa+O8T^S>+LH1YZ0#^d!o|GR=&i2U=vD=0a8-v{={@Z4;* z$LRd;fW9_d=_bzq_GfMjr;6WWR|{GL7koBr>@&Sc(igR$p-Q$`Lp$L__q z=YL1A`SxCrpD8|Sz~P;3_uXG;VeTyQ3QpYC9{UQxqBNGl6IQtMzoW3aiFl=P=YNOs z>1Kc$fBts}TVv1qK8)dtBKGNSuxFdQ^S|9W;T4pW?jlN_|6PF|bPm5%r|>J zSOoXD#`Cx{2`!tp%#uHU?>#~JIv39fIJ3@YS3HnnrepY%e-3hw<_VO}2kyNmxUbs5 zHxk1Yew@g{A&MFuT<7-5eyy-Gpi}npVfZ(`b7`?`$AS-~Z{O$X908p#dcHiERAlED z&OpNI92ohh(}J^8oWBe{E?fK{;PZzZ3S>tYj(EtYtDS!(w8<7NcoF*^7y3L-B##xI z&LWewZB#g-PxB=5>;4Me#Y|BcbLl++sfi~H*g%c3xCSN|MQ$9NLQ1Jegv*st{ z*LmEs@5?_0zwGDY`%h4Yntu=*Ui`j$0-c#6oZ)=^g0G_~)X{oR^C{5$Heb%-!+DDQ zi}^B&uquaVpt*RqgX>KFFZ*$k(=zNFgYYW}yV;lRDCpGrFoK^;tePiqagH>v_vJQ? za?{;=f)6K;TRi<5&oo~mxbCsj+?4$4$C|@&@r*YdA7cF_KeTB+O8$U+Y2HNsvq|?kUl-G<3(a>3ehM_~^>pfPyZ89K z%p)%u<|u@7K4CTYqw+WJxF?wF;~!4^nj;a8PCnNhlKj$gr$F=5jFHddq?_-cq3Fzy zy*u0;l}T85pQmv2J^YsR>kM$|^2u+4{Tckl^_&?>p9#O^pEdqp`7YZ;n0Mv#Xz$_K zDZSx^Wv4iLJ0B$so5VfZ+153*8^u=$XA<9ZPKx5xngWxR4wbzB>n0C7#{FO1dpE#_ zJ<9!GcVZj63j10aXYORscl&YXPCw4zDaJl_J?H(DG3M#)AK3=!6PX{^g1-z{6)?`- z8Nm5F{WwpjnDb7H8S`W_gRe&Se+AgsUdjDm^ythM#_REmNpm_5d*Kew3F165d;eE4 z<8(1&xz77xl*pL*xCNZ;!?^!S?*Dp_vA-p2G7tXuyZ?*ZY$-L@ZuF46K1;B~UEhM+ zdxE|EuXj#9N}Zc0SU;>w50=2si*7YlSwSS%kGDE7?90Oja$dnK^V<~OU}U_7W`2J! zGup62kq^5aEC}O67BLT*_X;n9jYM**ux&pnFa3b{e?vZW_wtX%Fb9u}Dc&=ju*v6b z{ykjdqwnfRR{l3mmd--4&ct%}|8V0L1(v1#=zcyY|3B|xv+bE(PW}(W&a*m!mHz|d z@y;^31I)_*Ue?btl1YZIAn)P*KUpMr-RpCkVE)dcEbr0@to$Fvx6){S&E5YKrg6TN z*OT&p7D^=RC-48sGRrDiKPmrb(E)WvUh@8*EIL6f>r2c2BME0pW$`;zM?!hf12qf4I04o6N>_xv!HX12jcWSi?ML#~In z)x+EDo#6hSpFlhg+a6MDCcwUD`564?Ixo-Pk1Y^QH?!;L^8B6__x;tp<40pdZ{se- zOuwCM-ZaI@1v=?+$8_gEo7&Ra5#datOr|V%{#tmu)>Q~T1UW)$U*y;AJVosxPPw_v z%SU6tf7Ht?vyoY}hR5L#HML$&DW@z)&vWp(NIchgnQJ)wLuU>NzaO%X*0IQ+g&wU7 zkzbYqtqqc260Yu)l7EQaRyuz@RXO4bqn*oz8=y3?0PMQErI^m`*eqr z!X-YxGsv&ja0#a$wCP+&`76oGLSLR^3ES^%2S0=I)H){NjDenScsk3W^IGUpIq#vI z*ZaB~K;6we-{DUs2QPR!WiKB%*x?@p{}Hc$oJvh<9gpH)L;PBACI3)p*y;0L18s-B z&U7l@-sJ10hWzTBOW~gdj?PJx{}iYi@9Ccj{cnO!!3R;RTDvBH3AxcaE%`^0uGTrp zKLmdBbzh$2i2wJrZRPPEXujE(;TTewOkRYq^X0VWNq*I2lP?Eu*05{H1TQ76G3!J8 zappI^4Es}t@AG*%pR}I${iv7_YkV21-6h9=rJ{C_9RDQ~s4l`g0fnRS|9Zw%%lET_ z3?#LM9%lSlKbkRoqqUjGcw;#I|A-l>u){}Ws%%(zaWF8Dy)wo_Zr}`m-BlFBCU64i z4iBP3A`2W_PZ?O4p__nK~a5sIKC$xCJH~eqV z=>ATg|KrNx=sW$?Hqo+r+N<9*fhENK8*v#PMVcdh?0H_q*U^lt*K?-l%b@3+$# zyux1&4KL@eyV0Z@-gT$Gf2_Oi`Vqg@;VP}%DjLa}IwR zW&3jOz&isP!aMLL5mxJ;m2N<~$8!hXFFpPs@O!%tPv;>k&Sj((-i@bw>B9T)`cqcD z-G`?&zzVw%{2hMmc_nw_Er5oXa~~dNrszIA-5=Rk_u<{)+wct9@T$!&k0p$3(vvk# z|7d7+vDUvU@BNTD9`@tt5c-kUtP9?sG3Co=I6u}*^Lsz8&!$&>)AzM;)T!1_3x5%1 zsI|}XbC9H&JjeM5(08;3TJV|R>r89;mx8lwne*r9gEvieek`8m96GLW`Xl#z-ODS( zpj>O*1wRd%-{oZs-9e*qSnv{Lmwmp?&nM1VKELgk+!JX1wr~cJum9!ckN%AJ5Baj1 zP9Ar9`qx97*55n)ads`Y{4=1x*_Y=~%Coe@;gs_2MtFj729o=kHO{{Y8h+yG9}4|L z=R0@>WvDgf!qoqQJcA#GQ8iH z?V03j!KDtr7#y9^E&Mf<+hHHiH1hJ8Pj?9E>TGY}oDYunNyy)yu$os@Ke&(hf9mrx zpS--=m-ArCS^FS_Kae=J{zd+Il%dWamwzM_YMs3N=TSa7`&|BN(#ouH{_&LOExz1F zQEsve2!|rDdp6`Rg`TmC9DD*ayxF(U%gC=}GvN&2x69Y>mB6((L-4`SrgO>VUrV~5 z^7Idae(l{5TvD|51UUSOM(3i-zZ!h)`H)|?xnAt^m?e+euORq*^7U>{zwYJJ*}8%k z)9Ro0F$oF#h??L`$_;p`}+T?TV7Zms3;BZEgmj^xl z?T;S{w0}kTCB*qfUv5Q|o6gP@d?55_ABg-5i1XJzUjxY3cYM8HPW@_shHy%uQ+rzE z*XsXOzFmzb{?mQgmXY7ve7+`uuYDlG55Un~4f5-rTJ7JEzlwA}=-W~&Y3b~I!Bp96lK&+h=z)gBbZxtuuP<=ctwc9jiP@M8Y| z9p$h3dWJr(JvM@`2VeVhSBJ*8OTNi2l+S4`?8ouoFHJp5X!P9m+@DKTN zo=Z8GRk?T?2z$3LpE1xm!{=)h`MS`T$*GjdExsN{5%#0L%(Wv_dz?g1hPr4P;`+iP z=(pN$B=}HfKD7@_{vy)SJsI*3;_Y(UnEKA@XRC^}KS%Hy@~Hh?@@v-g=RPl|k(XD(Bx0J-WX|@L|yZ zU0*&k$fNdf2_6vV8%S6FB3i`dzWtm^`}v|Tx6zc_e2fXgDW&iH!I$}DXwyC|!DkV_ z?BMd3@W1vS$-fHP?)LEyCH~DmUEMD8g3tR1@-Dlp@CV{9_xYu@nOVLZP9ZJr4HJ%T ztI-+8@&}Z(?(S2$+55kBA9mKg$M=83k${zf6W#xvxa&K*|682P<3;y>6DEY|&K3nrp4_!}q7C zV>#IdwAVQNp4c~YxXO}UO8;N)?!#dYE`;gs5qtJO>-|**i%5S4zwhsq{$@OkcFr$( zAI>5yQZxA_@55O{iEiSTybos)lEQ`jbO&`D->KMHwx;gG(S6st*GFxfrfu87BKnkU zNXh$f7SVn+k74h_5gzrih<0&4zvO*5i)ct%d-Vf&M4WDgosY5i;V8cgs|Y)VSa)Y}M zCkk813`)-3heJ_SSz69DJNRk6gQbstv0yJcT|LI@N6#B<*E+;_(um6J zoI%O=iUXIfZbKhv<;obZ=lcKA#3k8Pwqv-Rr@80)|IxIUXU(rt>;Fen8k#rL_&bcC zlEFvQ*3>t}%c;A=;(?>d>l|jfre7A<=V*wWPpz&>!FsO$A5C26F-mG3jBN`G72oOR z3+5|Ex=ajPU>-G}xAvZL%G9O1h#N}}S=)RJJDc0s-fVT%IP5vx#{6kJC!)DX7k0UM zE%!cYjf=IZ+I+0!X0C&F?T`&?Vdrye)-~3i5y!XQ{Ed01UCR}xyP2E5x|n-QmcfPe zE>1T{!7epdV)fM;?Kq7q=$rNCeJR*ZTKY!w&dwy>F1XWWR)&b{W4Gmjvem?}J$61( z=cvSW-ekVZPy3UDs2yBszR#Vx($nKM)C?CKWr8PJBSDOAPk`1GvL=DL&+KO2@B!uw zuV4-lMKALhYYRWmT;%837hu;RWO@2^g>$w3koiY+-3+@OlKv*OI90X)**Nd#~;Gfm$X)@WPYQ)n|mUqq@U!D@|ANf-0_NN%HKS^cnTviM#wLC#O$S~rAr4p*l_AlvM zF>HYChte%$*g#hHPP6)Q3>$=vz~LNDPAP|MNFTpq7`<&Du&5IIKh;p z@U%W*lAX`Acng(Z%{q*+GP7;J{5O$z@#zmE#|h@j#ob>g+0Nq4SJ-jrq)W_O1&hjW zyyfST)8nucSWkAg`J-S#7~e#@CRlq0;`~lR|5$F<$qzFhDRSkPwPUmPMyNkH*ko)1 z)plRUursM&Th0~8A60gpe~dT9u4DLSissYcPv=>gJkG~-qF8JWr0{0ibqCVlz&l)J z%YHUEp0F}lZ*BS^>`Y*1a=-SUt32LR*_EVwwb^x)RG$P6+KYyjJ?3{y z9bQ$|ovF1LS@7$$Gn#>|;|)B-S3jEv)7_U(`9=4I%R=LPNWZNMBZA7klICwY@*3Wz>_)rYXR)JSyJ{vri2SZN` z{w~ly50x)X8N4#{>EP3W_V6f;)i#X*=A*$!W0;L^p!xgY+kxg_EFOikk+%Ht;NvmO z;te%F2!0W04TkWlY<$DaBf%pv%;JqOj|bliG$(EGY<#DfPXwQcVHR(c`DO5bg6Ys4 z$H)GZ;KPB|2UwWJ8)Lp2d?S!8->%WJ>5erQ1s6G(@;g#AkLPxf9l=xhF= z<|No^OUop4X>e(9KW);M74^K43cVt@BG`(49phD)%Yw@StwXo**|1a1wqRQz+g}Vj z&0HK@9B9u>SihSX8PuMiBn^wlf14OVt_-fsgUvF{L30et3U9XAA6%aYJKfwEyf%>C zNAamHH?d=(Eoh5jHtaledvIrhN6-<&EZ#ZhUBUf<)-Q+cZxgGNifi+Q_U z)1xw#oPUs(D*bMX!djT{Hld;IvU>)?_IwbDRQkL2UpShDw}lmV7sW98)gw8eXkj+Ki_K%Kve5oF!B$(mORSzB z!7SdT<_G3S=Drktm)W~bBbde8W`1n`&CcP3?dl+$y_Mfjmb)|@&D-rAw-Li894EfDjnMn527`EH4iA=+q ztZbtBia3oc8K+xcm) zs?sQ>zaQlNwftnC*VyCA>W$_Gei6*ZcZZoDoDs-Y9@G3L=K626_VbwLJI$HF;$R}_ z3g-I$Te#KubtZz@w)<978B_(2i9X@kyxq+$;&<5nMhaWS**yp057+R!FC3#R>>g_A zTDxc1q|eIKby6gjd`$_%;wC6d9Wb3II}GeRvcWB*_j9HA2eq6VXViLe^v8De$wt|9&^b>*&-?{?<$2hE=x~`4 z(m$~U)nXUo@PlCIS-i7XrBb$|MSP#l^K{%i9D7%=8Dw&cP3Cp%$vJO{$uw2+MBhDt z9$ZA7ZdIx-uDo$ zk>{m^+eWyZ_^*Jb9VWA57yjKQ^Il`<>f|jTop%uSUfkah?jF7$!o3~$Hr(BWdn@|) zUHIREdo%7vToLYrxQB2bz`Y;$Antv*2XODj{Vnc(+{Hr%ba*W+%%y$<(U+-q<*haIQt0O=BxUrUV z2Kg>0y}SvYpL}*Bqw76%p&s(8Aq$7N8;#)|Ip2_gZv_qT~jK6m=p6R{DKa+UZEO*~@XS(8&`vx$% zYG86Vco%-JALQ^}0!J`C{}Y@r&G6YDIVnt6cpv9I`CQHz{U06{`ZrWzN5H9Uldcgw z#TPzhi}@jVieLWy{h}}Qi@wk=`a-|x3;p@@ zshx!1?ttEaFzkR%_dz~-h8S$D?iTzJ3M-V6;G$be1f(|BwgyCzyY+~E)= zyP2K;%gl)IH0P%ENW&AbA@D&vPhe#q7oY5KT4PkwT;J*9bMpjlKY_9Kjp^w1n$NT_ z;zNFhmNBvnm_O7Z1JB8}%T_QQJD=vIzb6HzMIfIpjS5aDxx}vPRD3S%6tjb$-Jj6enRR$m?Of|G*GQj%IArGONYB#ub=J_Z zfCw#Yn$>l+=X{vTWs&fvTib)qKnQi+>5TDh{B$Ny44cUa-D3CThdR@AW~F4yn3=+x zZS4`ah!&+`)171IptaU2j_-6kkGvv9-(0ho-;osFJhO*iLke%cwKHUdr}-kA#sWL{ ztuuMzG!|NYUuPc-yRde>%kLScgP+~YLAki{TZAQKlet^xh;0? zz_;<4z_hc}?hWzr%|vF&^3(bsYS*@dnds(I_$^)yY<XP%O4zlTBtr zSe?jNVe_07BrrcUzc7)V*20Rg)%-8JHc<1vkicKD`48rWBb%&+l`u26^qn{JUd2fQ3~shyM@W4iM6E8dB`%ogHAT zE7Kxc^|!FkX^n22?hGW>x7hR3izy{nRx{z2ww-+bb=LfiB$vz7E8R80QkvtL7r}6MOZ(K+m?T@#nt+kc= z8n~%pZbN%}AKbc-j(%NzYyEC+VCb8;m)CdZwpDjD>}lGUD;#B8W6m_UweHR~wb~md zIy-Y+bt_DFYiHB$)?6dtu54#lz48mVflC;=vJKo5k)4&>muu}xL0Y);0OIq@l`ASL zD?4)S%?CE;8gfvwk(c_8oW1Fy-WFxSAUEXI5AhVl>&&$_7Kk!QYiF)wU#_FB5sI63 zHRU?e`Rme^8;+2?JnnC4u2zZknr`*ZwvMi2Wh9yRRk^O{nvJzhonZk+Fk86LlI!Ta z?D903t=%mVT4%2m)wH#=G`%d6jw=sMuIvu1Zi{Gk&A=D!ihOFD8f)6R)j&?@Dw3X6 zZ*MtKuPFSfva&F|0D5*-eS1>@xKgOB+|atBsgt&&PHtA^T5}yu4RN2(&hnq=54}dg z-5>V0lA8MF=AHEoSDMZ}w32Msf%cqHkF2a*exNJ2rK=-X-%?q*Ial9UM}6x;kLdS)i{dJH6s>X!UtI!TO0BqU9#FbAO^>1+VI@((?6l6d?v93>(YF{qzj!=SB3KyR2{p6ujvBSA&5lFaOKX&@ z%nC6d`yTApg>Mb!d@}Vj#+w~#8;03%LcsJ$PQ-icVKI z`K&X_w#`~EUyl*gmgb4EsKmJKt`Slrs_-`oRhVZaCCd(F^NW4~5b z(#C7LJGO%0AX~cXTiU~qO`R*+T61P+TU&FwEIPVd;~WcgVryEjsR;ReT zEyOsCjcp?rt+jM!ry&OOG+Q>*tf}3aRY!?N#;D0>r!{hoTHQu3Md)QC;zYV9h}pC; z(2`D^@5)Ls>=ZXvD@}(KWNofTmbsR$0damqch~N=rqw5zB(^S|t(!FBHO zMC5@pJ1D?K`-j4j$ckpmSb(TXVB- zavm*FR|&5#P>MRN#)kF-%2E_+c@y>C=?3T2hx&$wTzgkdbCXo3R9!iy5yh|yHOVsj zRDW%$-!EXbjfH}WtGY8?sUWKAg}gD>5u^3MQa9>}mCQ>m->j&g!mn>^T%Wr-#z=kCm>!u1!XCY=F@?i`XDRAY zAijmi8MDnTETRTm+jAtde?*7t9^0kp_UK zLw8T=JCU64Fr)V31ONwY&0W3Ri2!*>GDbMzz>a7!F{(>{D`LTcju>r->h7+#WGHI% z!upOT8n{%YuD0++RA;9VDg@ZC$&l%odIXj_nvO12jLEXAth^!ln!>vwPO=9DsC>!H z^!QGLM6GP`TDWaOQE5vMi=$2}S?M?5*OL@RRhXYea*_|~L6sG_kJ>&$h0apk+0`gX zw*zJuB^wjIuDdJ8QaJZWq54Q-R8$^@N7tVAwKX-`-i-p9YPZSq@n3p0G&n}b)g7qm zwG6Gv_$hDWV)lur%d8{OT|6C8a@GLnLKSSL-K|cAOjr%t+P%f#yjb5Z)Z2VgM=kM= zJ)I{wxK?lV782b|8+zNDB3n&G9!!#651Y!|1azGZrtHXHGeFdXWcXQPKedA4pahA>#Y7SuS4-^)s;q1a`)vPSEN;-V^Ve+HTw9OU{sT@gx$s})x(nvxj=!pF$Lg#&Eo;?a_jp+FiV_>vVct)F011+_Qz+k3h z17Kt88C0T4GToN#`H{73C+msGTee@kZmkV=Vk4s;XQ|F}3-yIi3cv&z%4MsMI%5^f z3gOHotT&%sM1wnqh2B3OH61l-BnCH)tu-P?i%G~0VFP1vqAF`2nnYX2xlvIv_m!N- zOur$)9rbIAbg0AzK?4{%mC>OJQV+Sc>kKp117* zAWO%A)3RN_L z(PWf@7k)zgo*-XN$AOpM2nxm3vR%{7g};RLdV;Jul&a~<=t>(mtly$hDr~l{r^LO} zzo$RLp?x3d<#W^v{Pz>%IhcjRsW(3xZEDss!vwk8x5M4fTIA+_!x`X~?W~PW&k$4A zZC&-voBfRQE2blw%%b$R)@8~6RI_op%B^}W|5tC_pmA42ft%$`ctsEWjoEglSz`>>gInF~YZ`1z zw*a~wY0{{zSPYUTzWA$~GD_z_(+z2esMyt!%dN)#SorHsOem%uPUq>|?)~~O%8YK0T3Y>nUEwPTVyT^p3 zgT}fY>i@#RAw5|jq>>3EUZ2~|L^2b|J*P`)#fizQID3WWui~$E3hU_M@+miW*jcIvHh zWk*}fy4^jd?-|ze5Yid(6Jz<)@5z!ww4>w1kYpE1k?nd>jHv$7-jUlEL-NUITy_)n zsdyAlNv;V^l}C#}2^<$3#JbXPbxK6j;tMUT6m4m~Sg79jcpjOK zs0-%SGjBVYjG-AjrkW05KdsN@8hdgI+Ll}L0X@Fpk}C@eWUpbL=0ba>&(vjyU0Nj% z!+KAQhO|AuN8E|;J$hivb~-7!%Ik)GG30uN1}~Q=u)2EvinXrsXDpSKJGF9!28ANv7UP|E*;$J&PgG5!wbEhh_s0ck z2i8JyCZ>N_))xvAg)kHIK*zweOViY`ZKpn3oN3I6R}@OV=X6qU8IR_pR^*!N(`$bc z<(`@}JMN0~3?d~LLz!mR3N8F$tmdA?C9)f+gaPg^L7mC)1RLmy}_^Ob&91 zFj0A{el3Sje2m*>2TE+XrODE@pv~2nY~NCMDYNDC7cT0(c>O$Xuf=a;?DeZygDXJQi5BVf zikez?l_1)N=$Vr!e?14KxPjYXQCsLW>D?(RQzR;`9stA3^0{+w?3+~z$F*25pXv8XVP$1~ zMpaf4U|Vq#py{lQ z-7dFa8m`Y+i@T15acxrjgWh#=?9S?H0hza#LWYqphoBWz+s#!XYV}#>nN`M|JkdnYBkGE?$>hflH84pWJ$J#ExAap7-U(NLBVUu`r#NM)}_WyNv?xLvrSH#>IfmW=TYfF=G2MEF*R%cZEpWQLY_8!=g zDTH*{w(=%Uo<7}cClql+(Rv+UV?|}`V#1AK%=_JQ!gh%-5TtWp!njC&bw^H#-~^2< z%53rRQyog&mct_vaYPlH8iT={p!rPjaZ^>6E;#MW^8Z$70CADnu>@HKE0naWwPW|3 zWK2F4(?p#}7r8{BUH3XX-)soF-lYMTT$nDN=`Zcum~`G)uc*8o9h?W*CB7JaLXDaK>+&|kSg%u5IgA|cJR>=@T}NFTS~_u z9a@LBRyAwUOuEZybSuPR*|VJXRPeO#1HtfU<4O(OslqC@?f$lYszDqHlVYVS4x2#I zvPzp3yZ4y(jaKQAfhU?P(sI?GjzI2B+Gq(Ej8o>P44JVpM}~TsHL=ynCcFP%N9_?jo*o6T_qFr zm*E=Y(*-|Vqw;V(MPc!}N5G52*Mi-V$Yf{?j*_b@ZM4WJrYo%#6NSOtJptg+DJEI= zV3Ln2Y6eqsxH5dP%w*K=w;dj$ln-8nNS`)P_Z)@8MGGCgIh@L&H{>~@;}yIj8~&?c z;bG79+ufd=!BV9qfmO6m|BEd}#vrclWDmj9=hzC8r_Gj?nmp{ZGYv^WRlUQ$8P!*D zif7$5P3js~>3g`gZejJRrOhqP^$m5)Ry8-()ijwY<%qkxa@hrCQr@?^rlxLrGm}OV zvZ`@Os} zlv0F9rP`#QzJ5+i)4HbSx(1S|UQJKjp1X(X|_l`EHFu*YH6 zH?FQ;T3_3;98H#nIxvD4KKX;6O{<`EQxnx-SF`F|oyIL5mM>k$5~8L~JGj-WYU`WX zgDbD7Nb|O4Swn++T|Oht>*Xu!$VOd@)jLG5hLwk+DxdD-x>ZUtsRhec+N8>-Mcy~n zHP*INCtp?u+O*Noi%_;rsqZYUZz3ubZQUX%QX)U5;9WEtzeJJ6RVV|8!_$>9yauy@ z(`61i%!-sVphJkLQzHmAs?giC#Y>lzPcl~yRcMPpZJLTH0U5$1N>`?t0b-P1u3l!O zf0-_xw6tleTgl3_#nl>Zt=unnI8&(>Ff&4xfNbd!Q)8PF!L~F=hnl9P_@tf{EnK)3 zf`zs;y~AaAXM<`plD{00wZVT{U2=VZcGzRO7OYz6HpI*KR%$sP{H`>W)25rIZ3xAh zJ)L@t@w{;=`B)Cz-rkDbqBtlV3CTfYR-^#$shlOc{q)1tHPZs6!XK=q(*WPBfU!(;Sr)qX(Fc!6w*{)h&U&0^v7CT}_$U;eS+UtQ(=TZmIO#RT7v|2dzA zvSs{rpXRwxy4f$wD9UoKUtb0IC;Dk+kk(B;t>%#Di~X_`;@`W&#ZPo5v(5Q)plt>= zI+U(Qx}WpIE(QN*e%YttpX0}$NBl4OG@l5~Wy4ruhfuCrK23%~lSXV|aH6^?Uw@r< ztKWu8X`w&%%VIc@UiKLjwl8$ZD{}R9+rJ<1w)th$8T|KDIh+&8+X6oiS>&P251Ws_ z-iK%7f6&kW2=XjD0*ZeE@jvgU+Xoun=F_AnI5j<-y|=~WbGaW+Ch^=v<`tG~nXgaK zGj2@6aK5`9SJ`kSxxDaUImC-;0oe&i!m_Xs*P{Sf2rrxVbuGcbI~atG6Ze_4zmm_l zS)1TWBa{16!t?Ep3nse*)+U1=-y~qA*m(LPcv<)r-z4Mggj~QO_r=6p#d8uPP7Al% zcnTKB^5$~WlSu4&_~ljLWpWPxDpL`GWnm{^y=`kLyliU^@@_I^E>f4V38ebQeg`*l`+$NpK|0)8G^k)q9K)?Pr949<;_Gc~b4>U1=U{!T-I0&d-g*j;@v?%}cq#WelYJO{ zvVwMa8n?!g6kaK|11_>-X$scg+G>0-f;RvwS(lk-Bd~#3;JVzLQXYq>3B{gzA@JJ<4X~|vDVJxCnMz; zXYDsW5P^-yve@~iG!k|KR@ru8TO^$4iC7yu$Ij6`)rM?2CRtmYZzwNG*kp4h_txTY zdnvc}SpHrVhE-q*?i4d9!0WBHQE6>ro)PLZ6@0|X#?94*eprh)m2rK)Sr@^ZX6?^t z4kk)#^SQ!Ix3)OfnlLWJ^q%oGMjwe` z<2Z&@ac7fVc1&dBWHe4A0k-gDqXOG2)@B~IH)52}{Ze#>@>Y^Y%K9qPmeGp-lO zre80feUi2+WMkrG`mE*y*?j*P{zq|w%RK|#U&P7Z4m@)ZV*}4W4|Mh}K0=szyq7Jr zyQoV&WydRUzhiwAj(cu_F=J>OKOCS`YA{(jKn`gP8q2|Z@baQ<<;`NnwX&t+VCWR>%4KFaRt=D~ZP`K$TW zJO_^x&zKPbPLWYxRs18F_hoZNe%1ZdM&~c2PO?@8_=Bv?c;RFd&rkfcdXZLVuEWV^ zrao&*;O}RSrM$w=WLC)?=*iJdHC!7JZF*TzJ6MxN$aZPU7Q11S-kA$c@$}VigutpXfBiuZ}}_9kL)DN z--Q3Jh0foLwykkU@UhV9F+b1!i02=EoI~+n>(haikeTGuEr&Kdm%32cSIK)0Pm^$K zngsR>RR)z;ureMKOdq>$5ndHAniH-6GPh1pEIv&0zg;JcFHFLc>jc6Cc$)wHbwU!R z{Mj{uNyV4Pte4H$uJNO)TyuB^`6)9KfsuVX9!_E%AX`iI5m+YeXJo{-Z8>QUz|M`@ zLa?4F$EOv=j$VEmBveirp63>QY`PYfV}8z^OP@)>^0Bz{L%V(zOg7%j`3m|E?p1z# z4pxZ0Ap{HQw%HKdc2VHGpj(+8|1s7MztTl8hY?)n)Y>k8+Zs(SVloyrF=6M8`xN6O6 zpMG>b$}!UP#uj&PpMDND8oOFOy^08Itm)vgk2F!dRmmrCqoyjBJZ@P(l zaZh7ZDt|Lfu9xd&Mqo3s%9ZKujlgD^9$pVm-xrpCrJ~C*<~8o)1DLIkIVQu)@a()U z8YF}_*N$Vc?_#q|b9V`I`GFYzKKPk4Utzw_U_Sq~Y?EQLOmiryxHW+0cjn>`G8b=P z?%l>b-OBvk#hl&ByxXpMUUNEga!m96RNNTszy|98&D~lTF!$e}wE*+|7g#Gy>Py

V3BdG}yN322%W&f{26#kPjM+v@-Lyi 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 o&Qjnk1H?hx><-NbF2q_J}$SVC*>##y@dI^Inh zH>p&FL?s>&R0x$m&>|s(gt$ovc&G}BgcKf1LLVc9=mSum$^(}`+bqBTH{W=_UGIMW zymq5R^{oE;&CczdnK|doIrHtctE>L}-Jh*}(^RB=rpeqaE;b(ulsAwUytLAoMl!<9 zVzFoojUl^`?w}QT4_=$uypI6w^<7{QxEm}6OTiLw4_FSCffe9hfC!jXU^Tc8NDl7z zpKb|MwvcY$6*y{gd%R~BZvIi}%Z9G?dK)tU<-B>y9AwNq^p5c@9$dMl;y14H z*aUs)o^&@Vec5d3xRUfU2(9Cje!1Gn21x&92V?`J|E|5((B<7z`o9KfPb3f8X3h0u zU>#Twc7g{$415~2fQ?`i*bE*54}*Q+DT%M+v zl-CD;{Uad>t3OGX=91KZ3?z_}L3Xs0?{VKIrP-AN`Z$P`ob&S58VpdMq*tDulCI8F zzn|8lwCrO1URoP`E2~uvC4Y*Nxg?GF9B}iHRUPs895pc{I)gov%^F04Gt5Qxc@PKZ zm`jRZ33G-v!&oEDDq33S+dugPlGiA`B-^f??C%g9jPMcF6RcGM9>mE^wohZk@Id9i z$nHd?ueEZ5UP(U=4{3OK3Mt63QaTgE_;>{RvXioTQR$1{UHT$b(%1Pn3qe&Y;Dloc#yrwvS+8^ro@T+efw}^`P3TCchcU={aAL^mX>UWd({jVuz}#=UvV3yUKqDcY7aKoQ&g%3{d}m<=DYZ5PqCE@ChF`i*H&jG>^ZHKTI5Br(Rh;>EI-u$$JgGz zr|+wqU;K6B%lF^-17+rK_icXTCmT2J|HWV4eD>j?(N53CE&tux?7NFM9{zgq`5RX+ zf3K%OV%!G81C;Urgk{rdF~Gj-#v#ED>pnx;k1cKCtK3A(Y*&sjsn}m5JQ*|Q2Xwe~ z(bH_E+Q!|^FxJ%GG1=SeJBM4An7fmpCmxLCRIB;}>_QS9l@B?+-k6s{cSpM~8<6*W zz%*yk?5vRPpJdNM6aL-%ymZLqzwE7i%DD|jd3 z7$=q@Q-2w`$5>?kDN96JWd1dk`?sH4YHoPBCi5Sj>eXcaJJsrcQ@MAha_>&%-t%)y zP0`QkCU8Hz*!x;VEx~hpI+u1H$7vOZ>tW7YMfhnfm~OvqgsD~OVZ>C~SXMqO?|s+N z)_G9VPtb)`tG;U0*8k*Hc~469t-oU572WCcnc;LSksB*aKY#?oVU>}4l1W2xNJ`BL-d0|R{rHL>N1Y-W5Ymz+q&j%LP2RCM?L z^jLZ#=?R|Rd&t|YPimw2HhYbYAf|gu?mdHh|Im-mCmXCgIKBVyW-gX%qMk&yD0b=d!I#@pl@?)tsu+V(G61TkF}>*u9( zLd_l6;+Qd zYU|%j?+#|FFL%rbr@VU0Q|0e!{&2W|I1~Mu>gUEEn=lU^up*W6H#Q}%ZiWBzD`wG( zoaMM>8O8IEj}b$fVwB3-N`~_MYVkbLVOnIT%3HivdKV#^Y+EUEZKuDj8=<{!Z){x; zZ*MzzTY3_E){2kv1aB>Sy&GKH`T}ir$J;`Wv$XsIe4Swgt&cQ8wyq63tX3`Xz2LXW zI()Fb-AXGG{2lm5n3UB|4Lk)MGB1MR+va{i9=>in+mQOwjj(Qp9{~E-g7{W)Py5S$ ztL&H8R`1DPzP9S;ar4Ti$KR5Ykcv0;ty@SNLmcKTQ4FhSR{H6s^25H3Wf@=phH8Se zf_d9*`nOIlwX4?Fm22(43BuPtc)Oq&Dh0pp20;Fgjg1(lMpFDQilP?P|2an6Ej7lg zr&x4ds;B>4`#9Qq&ULJM`p<=a`2E9tpYFPglb7qF3O)62m)Yyxl-|ts1X^RSlBC6zcQ4xd-Z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.cpp new file mode 100644 index 00000000..e3400df0 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.cpp @@ -0,0 +1,283 @@ +//////////////////////////////////////////////////////////////////////////////// +// The author of this code is Justin Randall +// +// I have made modifications to the ByteStream +// and AutoByteStream classes in order to make them suitable +// for use in messaging systems which require objects that +// are copyable and assignable. It is also desirable for +// the ByteStream object to use a flexible allocator system +// that may support multi-threaded programming models. + + +#include "Archive.h" + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +//////////////////////////////////////////////////////////////////////////////// + + +#if defined(USE_ARCHIVE_MUTEX) + CMutex ByteStreamMutex; +#endif + +#if defined (PASCAL_STRING) +#pragma message ("--- Packing pascal style strings ---") + void get(Base::ByteStream::ReadIterator& source, std::string& target) + { + unsigned int size = 0; + Base::get (source, size); + + const unsigned char *buf = source.getBuffer(); + + target.assign((const char *)buf, (const char *)(buf + size)); + + const unsigned int readSize = size * sizeof(char); + source.advance(readSize); + } + + void put(ByteStream& target, const std::string& source) + { + const unsigned int size = source.size(); + put(target, size); + target.put(source.data(), size * sizeof (char)); + } + +#else +#pragma message ("--- Packing c style strings ---") + void get(ByteStream::ReadIterator & source, std::string & target) + { + target = reinterpret_cast(source.getBuffer()); + source.advance(target.length() + 1); + } + + + void put(ByteStream & target, const std::string & source) + { + target.put(source.c_str(), source.size()+1); + } +#endif + + ByteStream::ReadIterator::ReadIterator() : + readPtr(0), + stream(0) + { + } + + ByteStream::ReadIterator::ReadIterator(const ReadIterator & source) : + readPtr(source.readPtr), + stream(source.stream) + { + } + + ByteStream::ReadIterator::ReadIterator(const ByteStream & source) : + readPtr(0), + stream(&source) + { + } + + ByteStream::ReadIterator::~ReadIterator() + { + stream = 0; + } + + ByteStream::ByteStream() : + allocatedSize(0), + beginReadIterator(), + data(NULL), + size(0), + lastPutSize(0) + { + data = Data::getNewData(); + beginReadIterator = ReadIterator(*this); + } + + ByteStream::ByteStream(const unsigned char * const newBuffer, const unsigned int bufferSize) : + allocatedSize(bufferSize), + data(0), + size(bufferSize), + lastPutSize(0) + { + data = Data::getNewData(); + if(data->size < size) + { + delete[] data->buffer; + data->buffer = new unsigned char[size]; + data->size = size; + } + memcpy(data->buffer, newBuffer, size); + beginReadIterator = ReadIterator(*this); + } + + ByteStream::ByteStream(const ByteStream & source): + allocatedSize(source.getSize()), // only allocate what is really there, be opportinistic when grow()'ing + data(source.data), + size(source.getSize()), + lastPutSize(source.lastPutSize) + { + source.data->ref(); + beginReadIterator = ReadIterator(*this); + } + + ByteStream::ByteStream(ReadIterator & source) : + allocatedSize(0), + size(0), + lastPutSize(0) + { + data = Data::getNewData(); + put(source.getBuffer(), source.getSize()); + source.advance(source.getSize()); + beginReadIterator = ReadIterator(*this); + } + + ByteStream::~ByteStream() + { + data->deref(); + allocatedSize = 0; + data = 0; //lint !e672 (data deref insures the data is deleted if no one references it) + size = 0; + } + + ByteStream & ByteStream::operator=(const ByteStream & rhs) + { + if(this != &rhs) + { + data->deref(); // deref local data + rhs.data->ref(); + allocatedSize = rhs.allocatedSize; + size = rhs.size; + data = rhs.data; //lint !e672 (data is ref counted) + } + return *this; + } + + void ByteStream::get(void * target, ReadIterator & readIterator, const unsigned long int targetSize) const + { + assert(readIterator.getReadPosition() + targetSize <= allocatedSize); + memcpy(target, &data->buffer[readIterator.getReadPosition()], targetSize); + } + + void ByteStream::put(const void * const source, const unsigned int sourceSize) + { + if(data->getRef() > 1) + { + const unsigned char * const tmp = data->buffer; + data->deref(); + data = Data::getNewData(); + if(data->size < sourceSize) + { + delete[] data->buffer; + data->buffer = new unsigned char[size]; + data->size = size; + } + memcpy(data->buffer, tmp, size); + allocatedSize = size; + } + growToAtLeast(size + sourceSize); + memcpy(&data->buffer[size], source, sourceSize); + size += sourceSize; + if (sourceSize > 0) + lastPutSize = sourceSize; + } + + bool ByteStream::overwriteEnd(const void * const source, const unsigned int sourceSize) + { + if(data->getRef() <= 1 && + lastPutSize == sourceSize && + sourceSize <= data->size) + { + memcpy(&data->buffer[size-sourceSize], source, sourceSize); + return true; + } + else + { + return false; + } + } + + void ByteStream::reAllocate(const unsigned int newSize) + { + allocatedSize = newSize; + if(data->size < allocatedSize) + { + unsigned char * tmp = new unsigned char[newSize]; + if(data->buffer != NULL) + memcpy(tmp, data->buffer, size); + delete[] data->buffer; + data->buffer = tmp; + data->size = newSize; + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + AutoByteStream::AutoByteStream() : + members() + { + } + + AutoByteStream::~AutoByteStream() + { + } + + void AutoByteStream::addVariable(AutoVariableBase & newVariable) + { + members.push_back(&newVariable); + } + + const unsigned int AutoByteStream::getItemCount() const + { + return members.size(); + } + + void AutoByteStream::pack(ByteStream & target) const + { + std::vector::const_iterator i; + unsigned short packedSize=static_cast(members.size()); + put(target,packedSize); + for(i = members.begin(); i != members.end(); ++i) + { + (*i)->pack(target); + } + } + + void AutoByteStream::unpack(ByteStream::ReadIterator & source) + { + std::vector::iterator i; + unsigned short packedSize; + get(source,packedSize); + for(i = members.begin(); i != members.end(); ++i) + { + (*i)->unpack(source); + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + AutoVariableBase::AutoVariableBase() + { + } + + AutoVariableBase::~AutoVariableBase() + { + } + + +//////////////////////////////////////////////////////////////////////////////// + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h new file mode 100644 index 00000000..f12fb37d --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.h @@ -0,0 +1,746 @@ +//////////////////////////////////////////////////////////////////////////////// +// The author of this code is Justin Randall +// +// I have made modifications to the ByteStream +// and AutoByteStream classes in order to make them suitable +// for use in messaging systems which require objects that +// are copyable and assignable. It is also desirable for +// the ByteStream object to use a flexible allocator system +// that may support multi-threaded programming models. + + +#ifndef BASE_ARCHIVE_H +#define BASE_ARCHIVE_H + + +#include +#include +#include +#include "Platform.h" + + +//#if !defined PLATFORM_BASE_SINGLE_THREAD && ( defined _MT || defined _REENTRANT ) +//# define USE_ARCHIVE_MUTEX +//# include "Mutex.h" +//#endif + +#ifdef WIN32 +# include "win32/Archive.h" +#elif linux +# include "linux/Archive.h" +#elif sparc +# include "solaris/Archive.h" +#else + #error /Base/Archive.h: Undefine platform type +#endif + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +const unsigned MAX_ARRAY_SIZE = 1024; + + +//////////////////////////////////////////////////////////////////////////////// + +#if defined(USE_ARCHIVE_MUTEX) + extern CMutex ByteStreamMutex; +#endif + + class ByteStream + { + public: + class ReadIterator + { + public: + ReadIterator(); + ReadIterator(const ReadIterator & source); + explicit ReadIterator(const ByteStream & source); + ~ReadIterator(); + + ReadIterator & operator = (const ReadIterator & source); + void advance (const unsigned int distance); + void get (void * target, const unsigned long int readSize); + const unsigned int getSize () const; + const unsigned char * const getBuffer () const; + const unsigned int getReadPosition () const; + + private: + unsigned int readPtr; + const ByteStream * stream; + }; + + private: + class Data + { + friend class ByteStream; + friend class ReadIterator; + public: + ~Data(); + + static Data * getNewData(); + + const int getRef () const; + void deref (); + void ref (); + protected: + unsigned char * buffer; + unsigned long size; + private: + struct DataFreeList + { + ~DataFreeList() + { + std::vector::iterator i; + for(i = freeList.begin(); i != freeList.end(); ++i) + { + delete (*i); + } + }; + std::vector freeList; + }; + Data(); + //explicit Data(unsigned char * buffer); + static std::vector & getDataFreeList(); + static void releaseOldData(Data * oldData); + private: + int refCount; + }; + + friend class ReadIterator; + public: + ByteStream(); + ByteStream(const unsigned char * const buffer, const unsigned int bufferSize); + ByteStream(const ByteStream & source); + virtual ~ByteStream(); + + public: + ByteStream(ReadIterator & source); + ByteStream & operator = (const ByteStream & source); + ByteStream & operator = (ReadIterator & source); + const ReadIterator & begin() const; + void clear(); + const unsigned char * const getBuffer() const; + const unsigned int getSize() const; + void put(const void * const source, const unsigned int sourceSize); + bool overwriteEnd(const void * const source, const unsigned int sourceSize); + + private: + void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const; + void growToAtLeast(const unsigned int targetSize); + void reAllocate(const unsigned int newSize); + + private: + unsigned int allocatedSize; + ReadIterator beginReadIterator; + Data * data; + unsigned int size; + unsigned int lastPutSize; + + }; + + inline ByteStream::Data::Data() : + buffer(0), + size(0), + refCount(1) + { + } + + inline ByteStream::Data::~Data() + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + refCount = 0; + delete[] buffer; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + } + + inline void ByteStream::Data::deref() + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + refCount--; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + + if(refCount < 1) + releaseOldData(this); + } + + inline std::vector & ByteStream::Data::getDataFreeList() + { + static DataFreeList freeList; + return freeList.freeList; + } + + inline ByteStream::Data * ByteStream::Data::getNewData() + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + Data * result = 0; + if(getDataFreeList().empty()) + { + result = new Data; + } + else + { + result = getDataFreeList().back(); + getDataFreeList().pop_back(); + } + result->refCount = 1; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + + return result; + } + + inline const int ByteStream::Data::getRef() const + { + return refCount; + } + + inline void ByteStream::Data::ref() + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + refCount++; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + } + + inline void ByteStream::Data::releaseOldData(ByteStream::Data * oldData) + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + getDataFreeList().push_back(oldData); + oldData->refCount = 0; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + } + + inline ByteStream::ReadIterator & ByteStream::ReadIterator::operator = (const ByteStream::ReadIterator & rhs) + { + if(&rhs != this) + { + readPtr = rhs.readPtr; + stream = rhs.stream; + } + return *this; + } + + inline void ByteStream::ReadIterator::get(void * target, const unsigned long int readSize) + { + assert(stream); + stream->get(target, *this, readSize); + readPtr += readSize; + } + + inline const unsigned int ByteStream::ReadIterator::getSize() const + { + assert(stream); + return stream->getSize() - readPtr; + } + + inline const ByteStream::ReadIterator & ByteStream::begin() const + { + return beginReadIterator; + } + + inline void ByteStream::ReadIterator::advance(const unsigned int distance) + { + readPtr += distance; + } + + inline const unsigned int ByteStream::ReadIterator::getReadPosition() const + { + return readPtr; + } + + inline const unsigned char * const ByteStream::ReadIterator::getBuffer() const + { + if(stream) + return &stream->data->buffer[readPtr]; + + return 0; + } + + inline void ByteStream::clear() + { +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Lock(); +#endif + + size = 0; + +#if defined(USE_ARCHIVE_MUTEX) + ByteStreamMutex.Unlock(); +#endif + } + + inline const unsigned char * const ByteStream::getBuffer() const + { + return data->buffer; + } + + inline const unsigned int ByteStream::getSize() const + { + return size; + } + + inline void ByteStream::growToAtLeast(const unsigned int targetSize) + { + if(allocatedSize < targetSize) + { + reAllocate(allocatedSize + allocatedSize + targetSize); + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + class AutoVariableBase + { + public: + AutoVariableBase(); + virtual ~AutoVariableBase(); + + virtual void pack(ByteStream & target) const = 0; + virtual void unpack(ByteStream::ReadIterator & source) = 0; + }; + + +//////////////////////////////////////////////////////////////////////////////// + + + class AutoByteStream + { + public: + AutoByteStream(); + virtual ~AutoByteStream(); + void addVariable(AutoVariableBase & newVariable); + virtual const unsigned int getItemCount() const; + virtual void pack(ByteStream & target) const; + virtual void unpack(ByteStream::ReadIterator & source); + protected: + std::vector members; + private: + AutoByteStream(const AutoByteStream & source); + }; + + +//////////////////////////////////////////////////////////////////////////////// + + + template + class AutoVariable : public AutoVariableBase + { + public: + AutoVariable(); + explicit AutoVariable(const ValueType & source); + virtual ~AutoVariable(); + + const ValueType & get() const; + virtual void pack(ByteStream & target) const; + void set(const ValueType & rhs); + virtual void unpack(ByteStream::ReadIterator & source); + + private: + ValueType value; + }; + + template + AutoVariable::AutoVariable() : + AutoVariableBase(), + value() + { + } + + template + AutoVariable::AutoVariable(const ValueType & source) : + AutoVariableBase(), + value(source) + { + } + + template + AutoVariable::~AutoVariable() + { + } + + template + const ValueType & AutoVariable::get() const + { + return value; + } + + template + void AutoVariable::pack(ByteStream & target) const + { + Base::put(target, value); + } + + template + void AutoVariable::set(const ValueType & rhs) + { + value = rhs; + } + + template + void AutoVariable::unpack(ByteStream::ReadIterator & source) + { + Base::get(source, value); + } + + +//////////////////////////////////////////////////////////////////////////////// + + + template + class AutoArray : public AutoVariableBase + { + public: + AutoArray(); + AutoArray(const AutoArray & source); + ~AutoArray(); + + const std::vector & get() const; + void set(const std::vector & source); + + virtual void pack(ByteStream & target) const; + virtual void unpack(ByteStream::ReadIterator & source); + + private: + std::vector array; + }; + + template + inline AutoArray::AutoArray() + { + } + + template + inline AutoArray::AutoArray(const AutoArray & source) : + array(source.array) + { + } + + template + inline AutoArray::~AutoArray() + { + } + + template + inline const std::vector & AutoArray::get() const + { + return array; + } + + template + inline void AutoArray::set(const std::vector & source) + { + array = source; + } + + template + inline void AutoArray::pack(ByteStream & target) const + { + unsigned int arraySize = array.size(); + Base::put(target, arraySize); + + typename std::vector::const_iterator i; + for(i = array.begin(); i != array.end(); ++i) + { + ValueType v = (*i); + Base::put(target, v); + } + } + + template + inline void AutoArray::unpack(ByteStream::ReadIterator & source) + { + unsigned int arraySize; + Base::get(source, arraySize); + ValueType v; + + if (arraySize > MAX_ARRAY_SIZE) + arraySize = 0; + + for(unsigned int i = 0; i < arraySize; ++i) + { + Base::get(source, v); + array.push_back(v); + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + inline void get(ByteStream::ReadIterator & source, ByteStream & target) + { + target.put(source.getBuffer(), source.getSize()); + source.advance(source.getSize()); + } + + inline void get(ByteStream::ReadIterator & source, double & target) + { + source.get(&target, 8); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, float & target) + { + source.get(&target, 4); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, uint64 & target) + { + source.get(&target, 8); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, int64 & target) + { + source.get(&target, 8); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, uint32 & target) + { + source.get(&target, 4); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, int32 & target) + { + source.get(&target, 4); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, uint16 & target) + { + source.get(&target, 2); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, int16 & target) + { + source.get(&target, 2); + target = byteSwap(target); + } + + inline void get(ByteStream::ReadIterator & source, uint8 & target) + { + source.get(&target, 1); + } + + inline void get(ByteStream::ReadIterator & source, int8 & target) + { + source.get(&target, 1); + } + + inline void get(ByteStream::ReadIterator & source, unsigned char * const target, const unsigned int targetSize) + { + source.get(target, targetSize); + } + + inline void get(ByteStream::ReadIterator & source, bool & target) + { + source.get(&target, 1); + } + + +//////////////////////////////////////////////////////////////////////////////// + + + inline void put(ByteStream & target, ByteStream::ReadIterator & source) + { + target.put(source.getBuffer(), source.getSize()); + source.advance(source.getSize()); + } + + inline void put(ByteStream & target, const double value) + { + double temp = byteSwap(value); + target.put(&temp, 8); + } + + inline void put(ByteStream & target, const float value) + { + float temp = byteSwap(value); + target.put(&temp, 4); + } + + inline void put(ByteStream & target, const uint64 value) + { + uint64 temp = byteSwap(value); + target.put(&temp, 8); + } + + inline void put(ByteStream & target, const int64 value) + { + int64 temp = byteSwap(value); + target.put(&temp, 8); + } + + inline void put(ByteStream & target, const uint32 value) + { + uint32 temp = byteSwap(value); + target.put(&temp, 4); + } + + inline void put(ByteStream & target, const int32 value) + { + int32 temp = byteSwap(value); + target.put(&temp, 4); + } + + inline void put(ByteStream & target, const uint16 value) + { + uint16 temp = byteSwap(value); + target.put(&temp, 2); + } + + inline void put(ByteStream & target, const int16 value) + { + int16 temp = byteSwap(value); + target.put(&temp, 2); + } + + inline void put(ByteStream & target, const uint8 value) + { + target.put(&value, 1); + } + + inline void put(ByteStream & target, const int8 value) + { + target.put(&value, 1); + } + + inline void put(ByteStream & target, const bool & source) + { + target.put(&source, 1); + } + + + inline void put(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize) + { + target.put(source, sourceSize); + } + + inline void put(ByteStream & target, const ByteStream & source) + { + target.put(source.begin().getBuffer(), source.begin().getSize()); + } + + void get(ByteStream::ReadIterator & source, std::string & target); + void put(ByteStream & target, const std::string & source); + + +//////////////////////////////////////////////////////////////////////////////// + + + inline bool overwriteEnd(ByteStream & target, const double value) + { + double temp = byteSwap(value); + return target.overwriteEnd(&temp, 8); + } + + inline bool overwriteEnd(ByteStream & target, const float value) + { + float temp = byteSwap(value); + return target.overwriteEnd(&temp, 4); + } + + inline bool overwriteEnd(ByteStream & target, const uint64 value) + { + uint64 temp = byteSwap(value); + return target.overwriteEnd(&temp, 8); + } + + inline bool overwriteEnd(ByteStream & target, const int64 value) + { + int64 temp = byteSwap(value); + return target.overwriteEnd(&temp, 8); + } + + inline bool overwriteEnd(ByteStream & target, const uint32 value) + { + uint32 temp = byteSwap(value); + return target.overwriteEnd(&temp, 4); + } + + inline bool overwriteEnd(ByteStream & target, const int32 value) + { + int32 temp = byteSwap(value); + return target.overwriteEnd(&temp, 4); + } + + inline bool overwriteEnd(ByteStream & target, const uint16 value) + { + uint16 temp = byteSwap(value); + return target.overwriteEnd(&temp, 2); + } + + inline bool overwriteEnd(ByteStream & target, const int16 value) + { + int16 temp = byteSwap(value); + return target.overwriteEnd(&temp, 2); + } + + inline bool overwriteEnd(ByteStream & target, const uint8 value) + { + return target.overwriteEnd(&value, 1); + } + + inline bool overwriteEnd(ByteStream & target, const int8 value) + { + return target.overwriteEnd(&value, 1); + } + + inline bool overwriteEnd(ByteStream & target, const bool & source) + { + return target.overwriteEnd(&source, 1); + } + + inline bool overwriteEnd(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize) + { + return target.overwriteEnd(source, sourceSize); + } + +//////////////////////////////////////////////////////////////////////////////// + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/Archive.o new file mode 100644 index 0000000000000000000000000000000000000000..0d8839cd04462072e96cea15b4597f0245676974 GIT binary patch literal 22488 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 nL + + +#ifdef WIN32 + #include "win32/Platform.h" +#elif linux + #include "linux/Platform.h" +#elif sparc + #include "solaris/Platform.h" +#else + #error /Base/Platform.h: Undefine platform type +#endif + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + template inline T rotlFixed(T x, unsigned int y) + { + assert(y < sizeof(T)*8); + return (T)((x<>(sizeof(T)*8-y))); + } + + template inline T rotrFixed(T x, unsigned int y) + { + assert(y < sizeof(T)*8); + return (x>>y) | (x<<(sizeof(T)*8-y)); + } + + template inline T rotlMod(T x, unsigned int y) + { + y %= sizeof(T)*8; + return (x<>(sizeof(T)*8-y)); + } + + template inline T rotrMod(T x, unsigned int y) + { + y %= sizeof(T)*8; + return (x>>y) | (x<<(sizeof(T)*8-y)); + } + + inline uint16 byteReverse16(void * data) + { + uint16 value = *static_cast(data); + return *static_cast(data) = rotlFixed(value, 8U); + // return rotlFixed(value, 8U); + } + + inline uint32 byteReverse32(void * data) + { + uint32 value = *static_cast(data); + return *static_cast(data) = (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); + // return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); + } + inline uint64 byteReverse64(void * data) + { + uint64 value = *static_cast(data); + return *static_cast(data) = ( + uint64((rotrFixed(uint32(value), 8U) & 0xff00ff00) | (rotlFixed(uint32(value), 8U) & 0x00ff00ff)) << 32) | + (rotrFixed(uint32(value>>32), 8U) & 0xff00ff00) | (rotlFixed(uint32(value>>32), 8U) & 0x00ff00ff); + // return (uint64(byteReverse(uint32(value))) << 32) | byteReverse(uint32(value>>32)); + } + + inline uint32 strlen(const unsigned short * string) + { + if (string == 0) + return 0; + + uint32 length=0; + while (*(string+length++) != 0); + + return length-1; + } + + inline double getTimerLatency(Base::uint64 startTime, Base::uint64 finishTime=0) + { + Base::int64 requestAge; + Base::int64 freq = Base::getTimerFrequency(); + Base::uint64 finish = (finishTime ? finishTime : Base::getTimer()); + if (finish < startTime) + requestAge = (0 - 1) - startTime - finish; + else + requestAge = finish - startTime; + return (double)requestAge/freq; + } + + +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // BASE_PLATFORM_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Archive.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Archive.h new file mode 100644 index 00000000..bb623b49 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Archive.h @@ -0,0 +1,44 @@ +#ifndef BASE_LINUX_ARCHIVE_H +#define BASE_LINUX_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif + +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse(&value); return value; } + inline float byteSwap(float value) { byteReverse(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + + +} +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.cpp new file mode 100644 index 00000000..36fe5b29 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.cpp @@ -0,0 +1,40 @@ +//////////////////////////////////////// +// Mutex.cpp +// +// Purpose: +// 1. Implementation of the CMutex class. +// +// Revisions: +// 07/10/2001 Created +// + +#if defined(_REENTRANT) + + +#include "Mutex.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +CMutex::CMutex() + { + mInitialized = (pthread_mutex_init(&mMutex, 0) == 0); + } + +CMutex::~CMutex() + { + if (mInitialized) + pthread_mutex_destroy(&mMutex); + } + +} +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_REENTRANT) diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.h new file mode 100644 index 00000000..dd56e3fc --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Mutex.h @@ -0,0 +1,79 @@ +//////////////////////////////////////// +// Mutex.h +// +// Purpose: +// 1. Declair the CMutex class that encapsulates the functionality of a +// mutually-exclusive device. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_LINUX_MUTEX_H +#define BASE_LINUX_MUTEX_H + +#if !defined(_REENTRANT) +# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" ) +#else + + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CMutex + // + // Purpose: + // Encapsulates the functionality of a mutually-exclusive device. + // This class is valuable for protecting against race conditions + // within threaded applications. The CMutex class can be used to + // only allow a single thread to run within a specified code + // segment at a time. + // + // Public Methods: + // Lock() : Locks the mutex. If the mutex is already locked, the + // operating system will block the calling thread until another + // thread has unlocked the mutex. + // Unlock() : Unlocks the mutex. + // + class CMutex + { + public: + CMutex(); + ~CMutex(); + + void Lock(); + void Unlock(); + private: + pthread_mutex_t mMutex; + bool mInitialized; + }; + + inline void CMutex::Lock(void) + { + if (mInitialized) + pthread_mutex_lock(&mMutex); + } + + inline void CMutex::Unlock(void) + { + if (mInitialized) + pthread_mutex_unlock(&mMutex); + } + +} +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // #if defined(_MT) + +#endif // BASE_LINUX_MUTEX_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.cpp new file mode 100644 index 00000000..eeadd498 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.cpp @@ -0,0 +1,55 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + // Implementation of microsoft strlwr extension + // This non-ANSI function is not supported under UNIX + void strlwr(char * s) + { + while (*s) + { + *s = tolower(*s); + s++; + } + } + + // Implementation of microsoft strlwr extension + // This non-ANSI function is not supported under UNIX + void strupr(char * s) + { + while (*s) + { + *s = toupper(*s); + s++; + } + } + + + CTimer::CTimer() : + mTimer(0) + { + } + + +} +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.h new file mode 100644 index 00000000..9e6d51b4 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.h @@ -0,0 +1,112 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// strlwr() : Alters the contents of a string, making it all lower-case. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_LINUX_PLATFORM_H +#define BASE_LINUX_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + uint64 getTimer(void); + uint64 getTimerFrequency(void); + void sleep(uint32 ms); + + inline uint64 getTimer(void) + { + uint64 t; + struct timeval tv; + + gettimeofday(&tv, 0); + t = tv.tv_sec; + t = t * 1000000; + t += tv.tv_usec; + return t; + } + + inline uint64 getTimerFrequency(void) + { + uint64 f = 1000000; + return f; + } + + inline void sleep(uint32 ms) + { + usleep(static_cast(ms * 1000)); + } + + void strlwr(char * s); + void strupr(char * s); + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } + + +} +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // BASE_LINUX_PLATFORM_H diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Platform.o new file mode 100644 index 0000000000000000000000000000000000000000..886b664b0e70c4766861e5101bd9df15ab234ac8 GIT binary patch literal 1356 zcmbVMO=}ZT6n#mi8a37`T@+NzLM26gOwy!a-DqPPg|@_xLN{SLO{b=ibcV^qR46J0 zp&=U={){gC1#S$u@oxwfx)H>c5YNfXi<4|BUbs2;5EgxAyV$vu-*5_MY%&-nV-{FMNuXj(+$1{exJ(-J3$Z`Mp~{ z>KvCpcYgf`zgviZ8T4X>c+j1nrKhEy22KrQk^Oi=(+-fljo3^Omq3jRCgbm-S`^0l z2~7jE;~LjW{E+_$s?&#_#J>X09&`iB8smIX%;y)9sp9I|Y%(M7=Hy&5qw8sXE}cuJ zT&rf84Qm#y8n5b}xe4@KAFIj&NqW|vC*+ptnL=(h8ba>co+TtxR@K;c%{sh_U9Vfa z9zNn9KKd~HC696oO8!Ya z9h}opC9F5C93XpB7NE3My&mijP$jDGJObf;WU&w44eo<8Q2TfYTh)ds*5TZw5s1oN zgs*xs^%{wlfJ0C`B5#|LLoPz_9Du#qm$T-#h3g$6@e(m5s-E%{hU1#}(N}Te=qsil z?m%A?li>x!ul9p6Oy=rHUfmXz#}Gpj!^z$W`P^47@cEuDp?+a3&zbS8RlYoyx8QF; zS&QpMsb+fHwp*7K#}O|om5hPA@9fm9Eh!9R>FI-&g0WaAK3+8p_+HhuTLRCi)^ZIa zyNDN8stC`n*)7Xuyy=X@n~sCHVLZtUxbykvJ9Py7yAnfi literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h new file mode 100644 index 00000000..bc869bac --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/linux/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_LINUX_TYPES_H +#define BASE_LINUX_TYPES_H + +#include + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif + +namespace Base +{ +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; + +typedef int32_t int32; +typedef u_int32_t uint32; +typedef int64_t int64; +typedef u_int64_t uint64; +} +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // BASE_LINUX_TYPES_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h new file mode 100644 index 00000000..30ddce43 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp new file mode 100644 index 00000000..3b52563e --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h new file mode 100644 index 00000000..aaee37b7 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h new file mode 100644 index 00000000..0c64cb2c --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.cpp new file mode 100644 index 00000000..ca8a9b75 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.cpp @@ -0,0 +1,44 @@ +#include "Character.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + + +namespace Base +{ + +void get(ByteStream::ReadIterator & source, AuctionTransfer::Character & target) +{ + std::string tmpStr; + unsigned tmpNum; + + //name + get(source, tmpStr); + target.setName(tmpStr); + + // id + get(source, tmpNum); + target.setID(tmpNum); + + // data + get(source, tmpStr); + target.setData(tmpStr); +} + +void put(ByteStream & target, const AuctionTransfer::Character &source) +{ + put(target, source.getName()); + put(target, source.getID()); + put(target, source.getData()); +} + +}; + + +#ifdef EXTERNAL_DISTRO +}; +#endif + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.h new file mode 100644 index 00000000..61409ac0 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.h @@ -0,0 +1,70 @@ +#ifndef CHARACTER_H +#define CHARACTER_H + +#include "Base/Archive.h" + +namespace AuctionTransfer +{ + + +class Character +{ +public: + // constructors + Character() + : m_name(""), m_id(0), m_XMLdata("") + { + } + + Character(const std::string &name, unsigned id, const std::string &xmlData) + : m_name(name), m_id(id), m_XMLdata(xmlData) + { + } + + Character(const Character &character) + : m_name(character.getName()), m_id(character.getID()), m_XMLdata(character.getData()) + { + } + + // destructor + ~Character() + { + } + + // accessor methods + std::string getName() const { return m_name; } + unsigned getID() const { return m_id; } + std::string getData() const { return m_XMLdata; } + + void setName(const std::string name) { m_name = name; } + void setID(unsigned id) { m_id = id; } + void setData(const std::string data) { m_XMLdata = data; } + +protected: + std::string m_name; + unsigned m_id; + std::string m_XMLdata; +}; + +}; // namespace AuctionTransfer + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + + +namespace Base +{ + + void get(ByteStream::ReadIterator & source, AuctionTransfer::Character & target); + void put(ByteStream & target, const AuctionTransfer::Character & source); +}; + + +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif //CHARACTER_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Character.o new file mode 100644 index 0000000000000000000000000000000000000000..8589e6badd351bef4847946a79ffd45b8d1746bd GIT binary patch literal 15012 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 KU2f2q2=RY*=ZY}^ literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp new file mode 100644 index 00000000..8ccadac0 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.cpp @@ -0,0 +1,231 @@ +#include "Request.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ +void put(Base::ByteStream &msg, const Blob &source); + +////////////////////////////////////////////////////////////////////////////////////// + Blob::Blob(const unsigned char *data, unsigned len) + : m_data(NULL), + m_len(len) + { + if (m_len > 0) + { + m_data = new unsigned char [m_len]; + memcpy(m_data, data, m_len); + } + } + + +////////////////////////////////////////////////////////////////////////////////////// + Blob::Blob(const Blob &cpy) + : m_data(NULL), + m_len(cpy.m_len) + { + if (m_len > 0) + { + m_data = new unsigned char [m_len]; + memcpy(m_data, cpy.m_data, m_len); + } + } + +////////////////////////////////////////////////////////////////////////////////////// + Blob::~Blob() + { + if (m_data) + { + delete [] m_data; + } + } + +////////////////////////////////////////////////////////////////////////////////////// + Blob & Blob::operator =(const Blob &cpy) + { + if (this != &cpy) + { + //copy + if (m_data) + { + delete [] m_data; + m_data = NULL; + } + + m_len = cpy.m_len; + + if (m_len > 0) + { + m_data = new unsigned char [m_len]; + memcpy(m_data, cpy.m_data, m_len); + } + } + return *this; + } +////////////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////////////// +ReplyRequest::ReplyRequest( RequestTypes type, unsigned serverTrack, unsigned responseCode ) + : GenericRequest((short)type, serverTrack), m_responseCode(responseCode) +{ +} + +void ReplyRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_server_track); + put(msg, m_responseCode); +} + +////////////////////////////////////////////////////////////////////////////////////// +CommonRequest::CommonRequest( RequestTypes type, unsigned serverTrack, long long transactionID ) + : GenericRequest((short)type, serverTrack), m_transactionID(transactionID) +{ +} + +void CommonRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_transactionID); +} + +////////////////////////////////////////////////////////////////////////////////////// +GetIDRequest::GetIDRequest( RequestTypes type, unsigned serverTrack ) + : GenericRequest((short)type, serverTrack) +{ +} + +void GetIDRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); +} + +////////////////////////////////////////////////////////////////////////////////////// +SendPrepareCompressedRequest::SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *xmlAsset, unsigned length) + : GenericRequest((short)type, serverTrack), + m_transactionID(transactionID), + m_stationID(stationID), + m_characterID(characterID), + m_assetID(assetID), + m_serverID(serverID), + m_data(xmlAsset, length) +{ +} + +void SendPrepareCompressedRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_serverID); + put(msg, m_transactionID); + put(msg, m_stationID); + put(msg, m_characterID); + put(msg, m_assetID); + put(msg, m_data); +} + +////////////////////////////////////////////////////////////////////////////////////// +SendPrepareRequest::SendPrepareRequest( RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xml ) + : GenericRequest((short)type, serverTrack), + m_transactionID(transactionID), + m_stationID(stationID), + m_characterID(characterID), + m_assetID(assetID), + m_xml(xml), + m_serverID(serverID) +{ +} + +void SendPrepareRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_serverID); + put(msg, m_transactionID); + put(msg, m_stationID); + put(msg, m_characterID); + put(msg, m_assetID); + put(msg, m_xml); +} + +////////////////////////////////////////////////////////////////////////////////////// +ReplyGetCharacterListRequest::ReplyGetCharacterListRequest(RequestTypes type, unsigned serverTrack, unsigned responseCode, const Character characters[], unsigned numCharacters) +: GenericRequest((short)type, serverTrack), m_responseCode(responseCode) +{ + for(unsigned i = 0; i < numCharacters; i++) + { + m_characters.push_back(characters[i]); + } +} + +void ReplyGetCharacterListRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_server_track); + put(msg, m_responseCode); + put(msg, (unsigned)m_characters.size()); + for(unsigned i = 0; i < m_characters.size(); i++) + { + put(msg, m_characters[i]); + } +} + +////////////////////////////////////////////////////////////////////////////////////// +IdentifyServerRequest::IdentifyServerRequest(RequestTypes type, unsigned serverTrack, const char *serverID[], unsigned numIDs) +: GenericRequest((short)type, serverTrack) +{ + for(unsigned i = 0; i < numIDs; i++) + { + m_serverIDs.push_back(serverID[i]); + } +} + +void IdentifyServerRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, (unsigned)m_serverIDs.size()); + for(unsigned i = 0; i < m_serverIDs.size(); i++) + { + put(msg, m_serverIDs[i]); + } +} + +////////////////////////////////////////////////////////////////////////////////////// +SendAuditRequest::SendAuditRequest( RequestTypes type, unsigned serverTrack, const char *gameCode, const char *serverCode, + long long inGameAssetID, unsigned stationID, const char *event, const char *message) +: GenericRequest((short)type, serverTrack), m_gameCode(gameCode), m_serverCode(serverCode), m_assetID(inGameAssetID), + m_userID(stationID), m_event(event), m_message(message) +{ +} + +void SendAuditRequest::pack(Base::ByteStream &msg) +{ + put(msg, m_type); + put(msg, m_track); + put(msg, m_gameCode); + put(msg, m_serverCode); + put(msg, m_assetID); + put(msg, m_userID); + put(msg, m_event); + put(msg, m_message); +} + +void put(Base::ByteStream &msg, const Blob &source) +{ + put(msg, source.getLen()); + + if (source.getLen() > 0) + { + put(msg, source.getData(), source.getLen()); + } +} + + +}; // namespace +////////////////////////////////////////////////////////////////////////////////////// + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h new file mode 100644 index 00000000..f848c26b --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.h @@ -0,0 +1,147 @@ +#ifndef REQUEST_H +#define REQUEST_H + +#include +#include +#include "AuctionTransferEnum.h" +#include "Character.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + + class Blob + { + public: + Blob() : m_data(0), m_len(0) {} + Blob(const unsigned char *data, unsigned len); + Blob(const Blob &cpy); + ~Blob(); + + Blob & operator =(const Blob &cpy); + + const unsigned char *getData() const { return m_data; } + unsigned getLen() const { return m_len; } + + unsigned char *m_data; + unsigned m_len; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class ReplyRequest: public GenericRequest + { + public: + ReplyRequest(RequestTypes type, unsigned serverTrack, unsigned responseCode); + virtual ~ReplyRequest() {}; + + void pack(Base::ByteStream &msg); + private: + unsigned m_responseCode; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class CommonRequest: public GenericRequest + { + public: + CommonRequest(RequestTypes type, unsigned serverTrack, long long transactionID); + virtual ~CommonRequest() {}; + + void pack(Base::ByteStream &msg); + private: + long long m_transactionID; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class GetIDRequest: public GenericRequest + { + public: + GetIDRequest(RequestTypes type, unsigned serverTrack); + virtual ~GetIDRequest() {}; + + void pack(Base::ByteStream &msg); + private: + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class SendPrepareRequest: public GenericRequest + { + public: + SendPrepareRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const char *xmlAsset); + virtual ~SendPrepareRequest() {}; + + void pack(Base::ByteStream &msg); + private: + long long m_transactionID; + unsigned m_stationID; + unsigned m_characterID; + long long m_assetID; + std::string m_xml; + std::string m_serverID; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class SendPrepareCompressedRequest: public GenericRequest + { + public: + SendPrepareCompressedRequest(RequestTypes type, unsigned serverTrack, const char *serverID, long long transactionID, unsigned stationID, unsigned characterID, long long assetID, const unsigned char *xmlAsset, unsigned length); + virtual ~SendPrepareCompressedRequest() {}; + + void pack(Base::ByteStream &msg); + private: + long long m_transactionID; + unsigned m_stationID; + unsigned m_characterID; + long long m_assetID; + //std::string m_xml; + std::string m_serverID; + Blob m_data; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class ReplyGetCharacterListRequest: public GenericRequest + { + public: + ReplyGetCharacterListRequest(RequestTypes type, unsigned serverTrack, unsigned responseCode, const Character characters[], unsigned numCharacters); + virtual ~ReplyGetCharacterListRequest() {}; + + void pack(Base::ByteStream &msg); + private: + unsigned m_responseCode; + std::vector m_characters; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class IdentifyServerRequest: public GenericRequest + { + public: + IdentifyServerRequest(RequestTypes type, unsigned serverTrack, const char *serverID[], unsigned numIDs); + virtual ~IdentifyServerRequest() {}; + + void pack(Base::ByteStream &msg); + private: + std::vector m_serverIDs; + }; + + ////////////////////////////////////////////////////////////////////////////////////// + class SendAuditRequest : public GenericRequest + { + public: + SendAuditRequest( RequestTypes type, unsigned serverTrack, const char *gameCode, const char *serverCode, + long long inGameAssetID, unsigned stationID, const char *event, const char *message); + ~SendAuditRequest() {}; + void pack(Base::ByteStream &msg); + private: + std::string m_gameCode; + std::string m_serverCode; + long long m_assetID; + unsigned m_userID; + std::string m_event; + std::string m_message; + + }; +}; // namespace +////////////////////////////////////////////////////////////////////////////////////// + + +#endif //REQUEST_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Request.o new file mode 100644 index 0000000000000000000000000000000000000000..9b1fd362ce0875f14369f85bef3e0d49e52ac69f GIT binary patch literal 61168 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.cpp new file mode 100644 index 00000000..781ec318 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.cpp @@ -0,0 +1,17 @@ +#include "Response.h" + +namespace AuctionTransfer +{ + GetIDResponse::GetIDResponse(RequestTypes type, void *user) + : GenericResponse( (short)type, TRANSFER_SERVER_TIME_OUT, user), m_transactionID(-1) + { + } + + void GetIDResponse::unpack(Base::ByteStream::ReadIterator &iter) + { + get(iter, m_type); + get(iter, m_track); + get(iter, m_result); + get(iter, m_transactionID); + } +}; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h new file mode 100644 index 00000000..c7352fa2 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.h @@ -0,0 +1,35 @@ +#ifndef RESPONSE_H +#define RESPONSE_H + +#include +#include +#include "AuctionTransferEnum.h" + +////////////////////////////////////////////////////////////////////////////////////// +namespace AuctionTransfer +{ + + class CommonResponse : public GenericResponse + { + public: + CommonResponse(RequestTypes type, void *user) : GenericResponse((short)type, TRANSFER_SERVER_TIME_OUT, user) {} + virtual ~CommonResponse() {} + }; + +////////////////////////////////////////////////////////////////////////////////////// + class GetIDResponse : public GenericResponse + { + public: + GetIDResponse(RequestTypes type, void *user); + virtual ~GetIDResponse() {} + long long getNewID() { return m_transactionID; } + virtual void unpack(Base::ByteStream::ReadIterator &iter); + private: + long long m_transactionID; + }; + + +}; // namespace AuctionTransfer +////////////////////////////////////////////////////////////////////////////////////// + +#endif //RESPONSE_H diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Response.o new file mode 100644 index 0000000000000000000000000000000000000000..79ee8ecbb0909d349719ad1d826cd104999f6991 GIT binary patch literal 23016 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 + +#ifdef WIN32 + #include +#else //WIN32 + #include + #include + #include +#endif + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +Clock::Clock() +: m_lastStart(0), + m_totalRunTime(0) +{ +} + +ClockStamp Clock::getCurTime() +{ +#if defined(WIN32) + static int sClockHigh = 0; + static ClockStamp sClockLast = 0; + + int high = sClockHigh; + DWORD low = GetTickCount(); + ClockStamp holdLast = sClockLast; // this should be interlocked too + ClockStamp ret = ((ClockStamp)high << 32) | low; + + // crazy trick to allow threading to work, by putting in a 1000 second fudge factor, we effective say + // that it is ok to time-slice us at a bad point and we will still handle it, provided that our thread + // gets processing time again within 1000 seconds + if (ret < holdLast - 1000000) + { + sClockHigh = high + 1; + ret = ((ClockStamp)high << 32) | low; + } + + sClockLast = ret; // this really should be interlocked to be totally safe since it is a 64 bit value, but I don't see a way to do that and am not sure it would mess up anything but the one call anyways + + return ret; +#else + struct timeval tv; + int err; + err = gettimeofday(&tv, NULL); + return (static_cast(tv.tv_sec) * 1000 + static_cast(tv.tv_usec / 1000)); +#endif +} + +ClockStamp Clock::getElapsedSinceLastStart() +{ + if (m_lastStart == 0) + { + //hasn't been started + return 0; + } + + ClockStamp elapsed = getCurTime() - m_lastStart; + + if (elapsed > 2000000000) // only time differences up to 23 days can be measured with this function + elapsed = 2000000000; + + return elapsed; +} + +void Clock::start() +{ + if (m_lastStart != 0) + { + //already started + return; + } + + //set last start to curtime + m_lastStart = getCurTime(); +} + +void Clock::stop() +{ + if (m_lastStart == 0) + { + //need to start before stoping + return; + } + + m_totalRunTime += (unsigned)getElapsedSinceLastStart(); //rlsmith - explicit cast to prevent compiler warning + m_lastStart = 0; +} + + +bool Clock::isDone(unsigned runTime) +{ + if (m_lastStart == 0) + { + //never started, so say no + return false; + } + + ClockStamp totalElapsed = getElapsedSinceLastStart() + m_totalRunTime; + + return (totalElapsed >= runTime); +} + +void Clock::reset() +{ + m_lastStart = 0; + m_totalRunTime = 0; +} + + + +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.h new file mode 100644 index 00000000..89eb2c2a --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.h @@ -0,0 +1,71 @@ +#ifndef CLOCK_H +#define CLOCK_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + + +#if defined(WIN32) + typedef __int64 ClockStamp; +#else + typedef long long ClockStamp; +#endif + +/** + * @brief A Clock can be used as a millisecond timer. + */ +class Clock +{ +public: + + /** + * @brief Creates a clock, must still be started with Clock::start method. + * + * Once created, a clock can be started, and stoped as often as possible. + */ + Clock(); + + + /** + * @brief Starts the timer running. + */ + void start(); + + /** + * @brief Stops the timer from running (note: can still be started again later). + */ + void stop(); + + /** + * @brief Tells you if the timer has been in the started state for longer than runTime. + * + * @param runTime The amount of time to test if this timer has ran longer than. + * + * @return 'true' if timer has ran for longer than or equal to runTime, false otherwise. + */ + bool isDone(unsigned runTime); + + /** + * @brief Resets this clock (as if it were never started). + */ + void reset(); + +private: + ClockStamp m_lastStart; + unsigned m_totalRunTime; + + ClockStamp getCurTime(); + ClockStamp getElapsedSinceLastStart(); +}; + + +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif //CLOCK_H + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/Clock.o new file mode 100644 index 0000000000000000000000000000000000000000..0d384be5f7bd33e3c6af75eb069dea6a5b49b846 GIT binary patch literal 1976 zcma)6OK1~O6ur|t>)6Ip#f6`uK~P#hL(*EYejplS5p5A;RVXz~)6qtoCS<0qf>0s& z8DqhPAnshaaM_iJ3$a?7E?h_y6!$_=DGH)Rgm~_BUNRPc7w(*Q?mh3$dw1TO(dgj= zilUG-g?v{+{cC!$78w4 zxwACZGZ&lrQ7V=49dq_{{*ZV)gZkfQ?J4{9qn91M_4f3)_Y>c%?dgfRbxlw07k89T z%f62pZ@N##J@r<^@;z$aR~r#S)uAV$;)nIQ$uIMTH~ZGa#O31XlA*dibgOk_c=1Dq zP%+;#!xfzMc;?rYXWBkHCR~-f?uyP@Rn{pHwcs?R5OKEaP8l1fg|)>veb`!_=ZmPh zBH0u9sNa4$6)jPy*!Fg`W=OP6j|gz(dbIRQt-th@$Z0XU%-<>)(t;siJ)BJ;<)Z2r z;u?|-;47Ud(ORJ333ck_Dp7^O(nUM)WDmeQ;S2ME_jt9&316voAm`4V?G)KYG^q;RpYsUydBt=iY3C_9Xmw zy`lC%ny%cg2q9|jI{z%^{ou{C&l zZ|up%M2(2mz*)|pm(S7$m%G=U9(rma<>(kU!&(0?T@V_)s%%`3&w(^qekTGvmi3;4 z9Fa-Hoht_14)^Zk5{mP=<$Z7uE{>~g*z%h8oxzyO^870el>vA!FgfrsIozX%+M^EY6A z9VqWJ^V{I^zB0cLF7G3AiVUO^=d?s7LuV3+<~S}&COKgAX%vqiIJ&nZ8s8UfKiC9TlmP{GmkOiJT-KSsRd~`t1m_}bLIhZgG>!ua6^sH4@n+sSv zQ%)t#{prDS-L52M4b!O1Bx=Dvs+JPnVDuABxj4&+AKXT4jgkLB3J%zA7tg!Mec(9v Micy80afgdP0i?b@4FCWD literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.cpp new file mode 100644 index 00000000..e1f45c15 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.cpp @@ -0,0 +1,33 @@ +#include "IPAddress.h" + +#if defined(WIN32) + #include + typedef int socklen_t; +#else // for non-windows platforms (linux) + #include + #include + #include +#endif + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +IPAddress::IPAddress(unsigned int ip) +: m_IP(ip) +{ +} + +char *IPAddress::GetAddress(char *buffer) const +{ + struct sockaddr_in addr; + addr.sin_addr.s_addr = m_IP; + strcpy(buffer, inet_ntoa(addr.sin_addr)); + return(buffer); +} + + +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.h new file mode 100644 index 00000000..f6d5f886 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.h @@ -0,0 +1,51 @@ +#ifndef TCPIPADDRESS_H +#define TCPIPADDRESS_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +/** + * @brief Container object for IP Address. + */ +class IPAddress +{ +public: + + /** + * @brief Constructor, sets the ip address if specified. + */ + IPAddress(unsigned int ip = 0); + + /** + * @brief Sets the ip address. + */ + void SetAddress(unsigned int ip){ m_IP = ip; } + + /** + * @brief Returns the unsigned int representation of this address. + */ + unsigned int GetAddress() const { return m_IP; } + + /** + * @brief Used to retreive the the dot-notation represenatatiion of this address. + * + * @param buffer A pointer to the buffer to place the ip address into. + * Must be at least 17 characters long, will be null terminated. + * + * @return A pointer to the buffer the address was placed into. + */ + char *GetAddress(char *buffer) const; + +private: + unsigned int m_IP; +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif //TCPIPADDRESS_H + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/IPAddress.o new file mode 100644 index 0000000000000000000000000000000000000000..b4eef7edf95a181e31b3d82dd23e94ec9473171d GIT binary patch literal 1220 zcma)6&1w@-6h4zoYpQAeK}1kA3zZgSNYX}Zanq*LP_QLfvJAs?W;B83hs>ZY2rh!) zF!~lgf^T3Sz-3=RaM6WA7cPYOeaXE^>P8Qo`OZ1tx#!$_a&O++&$bN15G{tJW#WnW z%2^pEEJ{}9q!xcmYMI2&#;N#gd|LnV@fBnJ(|d`X*-Pr#{_(H=@mV6VeOCScdoUPO z_l6LkB=r+65Xq>9ET1n}`2z6DIA*-bWKHuu$lHkBRPn1olM5Cy?^0$8#{A49e4jwC zLoMjvym*`OvRhlq6|L2hwVW&F^M(9!p_E(f1qXo}21`f{k6Mwt z4~%*vY-kHfRumjYV)<_5inSkxVzoO_AQq{h;k@X%EqGq1)e71Xdj6-}MIMhgtMWPX z4P_HdW#0nMDVy*K1dnzR%Jt0SeD5ni4Wt~7VEonf9wNg0f92(o!*Ob1J(U>^6i3Dvb>$`9xR8cHgB`9aezT5}*HeGK8L>DnFx}NqmPRC98InZ(9`PW5%x&wVvcvmMfU5)&#+?kND z^lcdh(=v08O=E(57g~5O&Yi+}UBgstpngB}9g<3z-_#C}zHC?5eZLokq2+bE^3wB) z4laAQc@X%PIL_Ad^&Q*Uuq)fUjsrhx^g6GBtK)UGrc{DR6>*&MgsFPcYzL9kjykU3 b$$8zQ;r>(eA|J=-H?SS literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.cpp new file mode 100644 index 00000000..6d476d78 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.cpp @@ -0,0 +1,94 @@ +#include "TcpBlockAllocator.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +TcpBlockAllocator::TcpBlockAllocator(const unsigned initSize, const unsigned initCount) +: m_freeHead(NULL), m_blockCount(initCount), m_blockSize(initSize), m_numAvailBlocks(0) +{ + realloc(); +} + +TcpBlockAllocator::~TcpBlockAllocator() +{ + while(m_freeHead) + { + data_block *tmp = m_freeHead; + m_freeHead = m_freeHead->m_next; + delete[] tmp->m_data; + delete tmp;m_numAvailBlocks--; + } +} + +data_block *TcpBlockAllocator::getBlock() +{ + data_block *tmp; + + if(!m_freeHead) + { + realloc(); + } + + tmp = m_freeHead; + m_freeHead = m_freeHead->m_next; + tmp->m_next = NULL; + m_numAvailBlocks--; + return(tmp); +} + +void TcpBlockAllocator::returnBlock(data_block *b) +{ + b->m_usedSize = 0; + b->m_sentSize = 0; + + if (m_numAvailBlocks >= m_blockCount) + { + delete[] b->m_data; + delete b; + return; + } + + b->m_next = m_freeHead; + m_freeHead = b; m_numAvailBlocks++; +} + +void TcpBlockAllocator::realloc() +{ + data_block *tmp = NULL, *cursor = NULL; + + tmp = new data_block; m_numAvailBlocks++; + cursor = tmp; + memset(cursor, 0, sizeof(data_block)); + cursor->m_data = new char[m_blockSize]; + cursor->m_totalSize = m_blockSize; + + for(unsigned i = 1; i < m_blockCount; i++) + { + cursor->m_next = new data_block; m_numAvailBlocks++; + cursor = cursor->m_next; + memset(cursor, 0, sizeof(data_block)); + cursor->m_data = new char[m_blockSize]; + cursor->m_totalSize = m_blockSize; + } + + if(m_freeHead) + { + cursor->m_next = m_freeHead; + m_freeHead = tmp; + } + else + { + m_freeHead = tmp; + } +} + + +#ifdef EXTERNAL_DISTRO +}; +#endif + + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.h new file mode 100644 index 00000000..d34509a0 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.h @@ -0,0 +1,44 @@ +#ifndef TCPBLOCKALLOCATOR_H +#define TCPBLOCKALLOCATOR_H + +#include + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +struct data_block +{ + unsigned m_usedSize; + unsigned m_sentSize; + unsigned m_totalSize; + char *m_data; + data_block *m_next; +}; + +class TcpBlockAllocator +{ +public: + TcpBlockAllocator(const unsigned initSize, const unsigned initCount); + ~TcpBlockAllocator(); + data_block *getBlock(); + void returnBlock(data_block *); + +private: + void realloc(); + data_block *m_freeHead; + unsigned m_blockCount; + unsigned m_blockSize; + unsigned m_numAvailBlocks; +}; + + +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif //TCPBLOCKALLOCATOR_H + + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpBlockAllocator.o new file mode 100644 index 0000000000000000000000000000000000000000..d47d83396b823461fb94883c08051c24adad3cd5 GIT binary patch literal 2176 zcma)6O>7%g5Pr5d?l#?4OB+GOuO)tzmTG0E1Zay;>%|U;HVOo{NKv}7oh5OwooKxd zAR$1Q0;{D`u81oK#Hj}k+=_&yaEv(h$N{8C?Ez4glZE?zyZgFZ;tEC@&(6#@^JeC~ z@yDg}o)&M1*JiNBpAhWwwesOB%kev6O9w zc)MYYUs2J97B;YDD#ZCkx;gHrJ=Fg2uoxsw^ru}48|>d+od_pT8ua>u zVHv=|>cpz>ZiH?6WwqDO-R;`13_K(&t6ovP&f7rWXFgIornd`>%w_6Kw15ExxuQPr z&E%Ou8WZXD8KiKo`&kTl90mKOftS5G#KnLxwbIqvRABkoN5bNeXZ59+b)j%pY#N9ypn8$KMT1{LqupjphxhV+~_|s zpB31~!GyDYzKN$JJ^DKkIF8VLdkQ$-l_YuY z^Drd)cpF7b!p1&01KGzb_)dh2myq}w*d$5c12D)l>8nAxAVH84N0}VOCZ5Jw7!SbC zvw1FO&DxUrwo%k$G6{T%PiQeE?TYwo7<-s6>7|}Lfx05NNHP5zpS`E|__c%)8NqiR zQwBH7Ig_~ahjIQKq}(0qE$DK`secAt66f%>R3NE;58ecGw~7A+vJd9&Qs0G?M0~J_ zk%9VwL`&4gTlMu~bFKdFxh8(A?wVuN*Vn~zy*_1OiPjrUd&v-%Retl_g_2b)&Ac{i zSJytqr?wE#Z#<3mqFH!?NuLg^o_`*lyQp z-ybkn$n!75sYAbBmdu#|DVWy r9CJ=%DT + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + + +//used when want to open new connection with this socket +TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, const IPAddress &destIP, short destPort, unsigned timeout) +: m_nextConnection(NULL), + m_prevConnection(NULL), + m_socket(INVALID_SOCKET), + m_nextKeepAliveConnection(NULL), + m_prevKeepAliveConnection(NULL), + m_aliveListId(tcpManager->m_aliveList.m_listID), + m_nextRecvDataConnection(NULL), + m_prevRecvDataConnection(NULL), + m_recvDataListId(tcpManager->m_dataList.m_listID), + m_manager(tcpManager), + m_status(StatusNegotiating), + m_handler(NULL), + m_destIP(destIP), + m_destPort(destPort), + m_refCount(0), + m_sendAllocator(sendAlloc), + m_head(NULL), + m_tail(NULL), + m_bytesRead(0), + m_bytesNeeded(0), + m_params(params), + m_recvBuff(NULL), + m_connectTimeout(timeout), + m_connectTimer(), + m_wasConRemovedFromMgr(false) +{ + //start connection timer + m_connectTimer.start(); + + memset(&m_addr, 0, sizeof(m_addr)); + if (m_params.maxRecvMessageSize != 0) + { + m_recvBuff = new char[m_params.maxRecvMessageSize]; + } + + m_socket = socket(AF_INET, SOCK_STREAM, 0); + + + setOptions(); + + + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons(m_destPort); + m_addr.sin_addr.s_addr = m_destIP.GetAddress(); + + int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr)); + + if(err == SOCKET_ERROR) + { +#ifdef WIN32 + int sockerr = WSAGetLastError(); + if(sockerr != WSAEWOULDBLOCK) + { + //a real error + m_status = StatusDisconnected; + } + else + { + m_status = StatusNegotiating; + } + +#else // UNIX + + if (errno != EINPROGRESS) + { + m_status = StatusDisconnected; + } + else + { + m_status = StatusNegotiating; + } +#endif + } + else + { + //we are connected, wow + m_status = StatusConnected; + } + +} + +//used when server mode creates new connection object representing a connect request +TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, SOCKET socket, const IPAddress &destIP, short destPort) +: m_nextConnection(NULL), + m_prevConnection(NULL), + m_socket(socket), + m_nextKeepAliveConnection(NULL), + m_prevKeepAliveConnection(NULL), + m_aliveListId(tcpManager->m_aliveList.m_listID), + m_nextRecvDataConnection(NULL), + m_prevRecvDataConnection(NULL), + m_recvDataListId(tcpManager->m_dataList.m_listID), + m_manager(tcpManager), + m_status(StatusConnected), + m_handler(NULL), + m_destIP(destIP), + m_destPort(destPort), + m_refCount(0), + m_sendAllocator(sendAlloc), + m_head(NULL), + m_tail(NULL), + m_bytesRead(0), + m_bytesNeeded(0), + m_params(params), + m_recvBuff(NULL), + m_connectTimeout(0), + m_connectTimer(), + m_wasConRemovedFromMgr(false) +{ + memset(&m_addr, 0, sizeof(m_addr)); + if (m_params.maxRecvMessageSize != 0) + { + m_recvBuff = new char[m_params.maxRecvMessageSize]; + } + + + setOptions(); +} + +void TcpConnection::setOptions() +{ + if (m_socket != INVALID_SOCKET) + { +#if defined(WIN32) + unsigned long isNonBlocking = 1; + int outBufSize = m_params.outgoingBufferSize; + int inBufSize = m_params.incomingBufferSize; + int keepAlive = 1; + int reuseAddr = 1; + struct linger ld; + ld.l_onoff = 0; + ld.l_linger = 0; + + if (ioctlsocket(m_socket, FIONBIO, &isNonBlocking) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&outBufSize, sizeof(outBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&inBufSize, sizeof(inBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepAlive, sizeof(keepAlive)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) != 0 ) + { + //bummer, but no need to crash now.... ? + } + +#else // linux is to remain the default compile mode + unsigned long isNonBlocking = 1; + unsigned long keepAlive = 1; + unsigned long outBufSize = m_params.outgoingBufferSize; + unsigned long inBufSize = m_params.incomingBufferSize; + unsigned long reuseAddr = 1; + struct linger ld; + ld.l_onoff = 0; + ld.l_linger = 0; + + if (ioctl(m_socket, FIONBIO, &isNonBlocking) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &outBufSize, sizeof(outBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &inBufSize, sizeof(inBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) != 0) + { + //bummer, but no need to crash now.... ? + } +#endif + } + +} + +int TcpConnection::finishConnect() +{ + AddRef(); + int returnVal = 0; + /**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */ + switch (m_status) + { + case StatusDisconnected: + { + //something went wrong + Disconnect(false); + returnVal = -1; + } + break; + case StatusNegotiating: + { +#ifdef WIN32 + //try to finish connection + fd_set wrSet; + FD_ZERO(&wrSet); + +#pragma warning(push) +#pragma warning(disable : 4127) + FD_SET(m_socket, &wrSet); +#pragma warning(pop) + + timeval t; + t.tv_sec = 0; + t.tv_usec = 0; + + int err = select(m_socket + 1, NULL, &wrSet, NULL, &t); + + if (err == 0) + { + //needs more time + returnVal = 0; + } + else if (err == SOCKET_ERROR) + { + //huhoh, let's hope it needs more time + int sockerr = WSAGetLastError(); + if (sockerr == WSAEINPROGRESS + || sockerr == WSAEWOULDBLOCK + || sockerr == WSAEALREADY + || sockerr == WSAEINVAL) + { + //yep + returnVal = 0; + } + else + { + Disconnect(false); + returnVal = -1; + } + } + else + { + //check if write bit set for socket + if (FD_ISSET(m_socket, &wrSet)) + { + //connection complete + m_status = StatusConnected; + returnVal = 1; + } + else + { + //give it more time?? + returnVal = 0; + } + } + +#else // not WIN32 + int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr)); + + if(err == SOCKET_ERROR) + { + if (errno != EINPROGRESS && errno != EALREADY) + { + Disconnect(false); + returnVal = -1;//failure + } + else + { + returnVal = 0;//need to wait + } + } + else + { + m_status = StatusConnected; + returnVal = 1;//connect success + } +#endif + } + break; + case StatusConnected: + { + //wierd, shouldn't be trying to do this here + Disconnect(true); + returnVal = -1; + } + break; + } + + if (returnVal == 0 && m_connectTimeout != 0 && m_connectTimer.isDone(m_connectTimeout)) + { + Disconnect(false); + returnVal = -1; + } + else if (returnVal ==1/* && m_connectTimeout != 0*/) + { + //need to give, onConnect callback + if (m_manager->m_handler) + m_manager->m_handler->OnConnectRequest(this); + } + + Release(); + return returnVal; + +} + + +TcpConnection::~TcpConnection() +{ + if (m_recvBuff != NULL) + { + delete [] m_recvBuff; + } + + while(m_head != NULL) + { + data_block *tmp = m_head; + m_head = m_head->m_next; + m_sendAllocator->returnBlock(tmp); + } + + //TODO: need to notify app if are currently connected +} + +void TcpConnection::Send(const char *data, unsigned int dataLen) +{ +//add msg to buf + int totalLen = dataLen + sizeof(int); + + if(m_status == StatusDisconnected) + { + return; + } + + if (m_params.keepAliveDelay > 0 && m_aliveListId == m_manager->m_aliveList.m_listID) + { + m_aliveListId = m_manager->m_keepAliveList.m_listID; + + if (m_prevKeepAliveConnection != NULL) + m_prevKeepAliveConnection->m_nextKeepAliveConnection = m_nextKeepAliveConnection; + if (m_nextKeepAliveConnection != NULL) + m_nextKeepAliveConnection->m_prevKeepAliveConnection = m_prevKeepAliveConnection; + if (m_manager->m_keepAliveList.m_beginList == this) + m_manager->m_keepAliveList.m_beginList = m_nextKeepAliveConnection; + + m_nextKeepAliveConnection = m_manager->m_aliveList.m_beginList; + m_prevKeepAliveConnection = NULL; + if (m_manager->m_aliveList.m_beginList != NULL) + m_manager->m_aliveList.m_beginList->m_prevKeepAliveConnection = this; + m_manager->m_aliveList.m_beginList = this; + } + + + data_block *work = NULL; + + // this connection has no send buffer. Get a block + if(!m_tail) + { + m_head = m_sendAllocator->getBlock(); + m_tail = m_head; + } + work = m_tail; + + //send message len first + unsigned nLen = htonl(totalLen); + unsigned lenLength = sizeof(int); + unsigned lenIndex = 0; + while(lenIndex < lenLength) + { + if ((lenLength - lenIndex) <= (work->m_totalSize - work->m_usedSize)) + { + //size will fit in this block + memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, lenLength - lenIndex); + work->m_usedSize += (lenLength - lenIndex); + lenIndex += (lenLength - lenIndex); + } + else + { + //size will not fit in this block + memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, work->m_totalSize - work->m_usedSize); + lenIndex += work->m_totalSize - work->m_usedSize; + work->m_usedSize += work->m_totalSize - work->m_usedSize; + work->m_next = m_sendAllocator->getBlock(); + work = work->m_next; + m_tail = work; + } + } + + //now send message payload + unsigned messageIndex = 0; + while(messageIndex < dataLen) + { + if((dataLen - messageIndex) <= (work->m_totalSize - work->m_usedSize)) + { + // data will fit in this block + memcpy(work->m_data + work->m_usedSize, data + messageIndex, (dataLen - messageIndex)); + work->m_usedSize += (dataLen - messageIndex); + messageIndex += (dataLen - messageIndex); + } + else + { + // data will not fit in this block. Fill this block and get another block + memcpy(work->m_data + work->m_usedSize, data + messageIndex, work->m_totalSize - work->m_usedSize); + messageIndex += work->m_totalSize - work->m_usedSize; + work->m_usedSize += work->m_totalSize - work->m_usedSize; + work->m_next = m_sendAllocator->getBlock(); + work = work->m_next; + m_tail = work; + } + } + + + return; +} + + +void TcpConnection::Disconnect(bool notifyApplication) +{ + AddRef(); + m_status = StatusDisconnected; + if (!m_wasConRemovedFromMgr) + { + m_manager->removeConnection(this); + m_wasConRemovedFromMgr = true; + } + + + if(m_socket != INVALID_SOCKET) + { +#if defined(WIN32) + closesocket(m_socket); +#else + close(m_socket); +#endif + m_socket = INVALID_SOCKET; + } + + + if (notifyApplication && m_handler) + m_handler->OnTerminated(this); + + Release(); +} + + +void TcpConnection::AddRef() +{ + m_refCount++; +} + + +void TcpConnection::Release() +{ + if (--m_refCount == 0) + { + //make sure manager knows I'm gone + if (m_status != StatusDisconnected) + Disconnect(false); + delete this; + } +} + +int TcpConnection::processIncoming() +{ +/**< returns < 0 if fatal error and socket has been closed, + =0 if read anything (full or partial message), + >0 if nothing to read now, or would block so shouldn't try again immediately. */ + + if (m_status != StatusConnected) + { + //wait until connect succeeds + return 1; + } + + if (m_params.noDataTimeout > 0 && m_recvDataListId == m_manager->m_dataList.m_listID) + { + m_recvDataListId = m_manager->m_noDataList.m_listID; + + if (m_prevRecvDataConnection != NULL) + m_prevRecvDataConnection->m_nextRecvDataConnection = m_nextRecvDataConnection; + if (m_nextRecvDataConnection != NULL) + m_nextRecvDataConnection->m_prevRecvDataConnection = m_prevRecvDataConnection; + if (m_manager->m_noDataList.m_beginList == this) + m_manager->m_noDataList.m_beginList = m_nextRecvDataConnection; + + m_nextRecvDataConnection = m_manager->m_dataList.m_beginList; + m_prevRecvDataConnection = NULL; + if (m_manager->m_dataList.m_beginList != NULL) + m_manager->m_dataList.m_beginList->m_prevRecvDataConnection = this; + m_manager->m_dataList.m_beginList = this; + } + + + int newMsg = 0; + + + if (m_bytesRead < sizeof(int)) + { + //new msg + newMsg = 1; + //printf("socket: %d\n", m_socket); + int ret = recv(m_socket, ((char *)(&m_bytesNeeded) + m_bytesRead), + 4 - m_bytesRead, 0); + //fprintf(stderr, "READ: %d\n", ret); + if (ret == 0) + { + //We did a select, so there should be data. Socket was closed. + Disconnect(); + return -1; + } + else if (ret == -1) + { + if (translateRecvSocketEror()) + { + //fatal error + return -1; + } + else + { + //need to wait + return 1; + } + } + else + { + m_bytesRead += ret; + if (m_bytesRead < 4) + { + return 1;//need to wait + } + else + { + + m_bytesNeeded = ntohl(m_bytesNeeded); + + //printf("m_bytesNeeded = %i\n", m_bytesNeeded); + if (m_bytesNeeded == sizeof(int)) + { + //keepalive, ignore + m_bytesRead = 0; + m_bytesNeeded = 0; + return 0; + } + else if (m_bytesNeeded < sizeof(int)) + { + //major protocol violation + Disconnect(); + return -1; + } + else if (m_params.maxRecvMessageSize == 0) + { + if (m_recvBuff!=NULL) + delete [] m_recvBuff; + m_recvBuff = new char[m_bytesNeeded-4]; + } + else if (m_params.maxRecvMessageSize != 0 && (m_bytesNeeded-4) > m_params.maxRecvMessageSize) + { + //error, maxRecvMeessageSize exceeded, Disconnect + Disconnect(); + return -1; + } + } + } + } + + int msgBytesRead = m_bytesRead - 4; + int msgBytesNeeded = m_bytesNeeded - 4; + + int ret = recv(m_socket, (char *)(m_recvBuff + msgBytesRead), + msgBytesNeeded - msgBytesRead, 0); + if (ret == 0 && !newMsg) + { + //We did a select, so there should be data. Socket was closed. + Disconnect(); + return -1; + } + if (ret == -1) + { + if (translateRecvSocketEror()) + { + //fatal error + return -1; + } + else + { + //need to wait + return 1; + } + } else + { + m_bytesRead += ret; + } + + if (m_bytesRead == m_bytesNeeded) + { + m_bytesRead = 0; + m_bytesNeeded = 0; + if (m_handler) + { + AddRef();//could get deleted during this callback + m_handler->OnRoutePacket(this, (unsigned char *)m_recvBuff, msgBytesNeeded); + + if (m_status == StatusDisconnected) + { + Release(); + return -1; + } + Release(); + } + + //entire message received + return 0; + } + else + { + return 1;//couldn't get entire msg + } +} + +int TcpConnection::processOutgoing() +{ +/**< returns < 0 if fatal error and socket has been closed, + =0 if sent data, call again immediately if want to, + >0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */ + if (m_status != StatusConnected) + { + //wait until connect succeeds + return 0; + } + + + + int sendError = 1; + + // If m_head is not null, then this connection has something to send + + + if(m_head) + { + + + int amt = ::send(m_socket, m_head->m_data + m_head->m_sentSize, m_head->m_usedSize - m_head->m_sentSize, 0); + if(amt < 0) + { +#ifdef WIN32 + switch(WSAGetLastError()) + { + case WSAEWOULDBLOCK: + case WSAEINTR: + case WSAEINPROGRESS: + case WSAEALREADY: + case WSA_IO_PENDING: + case WSA_NOT_ENOUGH_MEMORY: + case WSATRY_AGAIN: + //try again + sendError = 1; + break; + default: + //assume broken, Disconnect + Disconnect(); + sendError = -1; + break; + } +#else //not WIN32 + + // error condition, EAGAIN is recoverable, otherwise raise an error condition. Break from loop + switch(errno) + { + case EAGAIN: + //try again + sendError = 1; + break; + default: + //assume broken, Disconnect + Disconnect(); + sendError = -1; + break; + } +#endif + } + else if(static_cast(amt) < (m_head->m_usedSize - m_head->m_sentSize)) + { + // partial send: trying to do anything more now would be a waste of time. Break from loop + m_head->m_sentSize += amt; + sendError = 1; + } + else if(amt == 0) + { + Disconnect(); + sendError = -1; + // client closed connection + } + else + { + // everything was sent from this block. Return it to the pool, advance m_head. Attempt to continue + // sending + data_block *tmp = m_head; + if(m_tail == m_head) + { + m_tail = m_tail->m_next; + m_head = m_head->m_next; + } + else + { + m_head = m_head->m_next; + } + m_sendAllocator->returnBlock(tmp); + + sendError = 0; + } + } + + return sendError; +} + + +bool TcpConnection::translateRecvSocketEror() +{ +/**< returns false if fatal error and socket has been closed, + true if should try again. */ + bool fatalError=false; +#ifdef WIN32 + + switch(WSAGetLastError()) + { + case WSAENOBUFS: + case WSAEINPROGRESS: + case WSAEINTR: + case WSAEWOULDBLOCK: + case WSABASEERR: + fatalError=false; + break; + + case WSANOTINITIALISED: + case WSAENETDOWN: + case WSAEFAULT: + case WSAENOTCONN: + case WSAENETRESET: + case WSAENOTSOCK: + case WSAEOPNOTSUPP: + case WSAESHUTDOWN: + case WSAEMSGSIZE: + case WSAEINVAL: + case WSAECONNABORTED: + case WSAETIMEDOUT: + case WSAECONNRESET: + default: + //fatal + fatalError=true; + Disconnect(); + break; + } + +#else //not WIN32 + + switch(errno) + { + case EWOULDBLOCK: + case EINTR: + case ETIMEDOUT: + case ENOBUFS: + //try later + fatalError=false; + break; + + case EBADF: + case ECONNRESET: + case EFAULT: + case EINVAL: + case ENOTCONN: + case ENOTSOCK: + case EOPNOTSUPP: + case EPIPE: + case EIO: + case ENOMEM: + case ENOSR: + default: + //fatal + fatalError=true; + Disconnect(); + break; + } +#endif + + + return fatalError; +} + +#ifdef EXTERNAL_DISTRO +}; +#endif + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.h new file mode 100644 index 00000000..07eb4f42 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.h @@ -0,0 +1,157 @@ +#ifndef TCPCONNECTION_H +#define TCPCONNECTION_H + + +#include "TcpHandlers.h" +#include "TcpManager.h" +#include "IPAddress.h" +#include "TcpBlockAllocator.h" +#include "Clock.h" + +#if defined(WIN32) + #include + typedef int socklen_t; +#else // for non-windows platforms (linux) + #include + #include + #include + #include + #include + #include + #include +#endif + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + + +/** + * @brief Manages a single connection. + */ +class TcpConnection +{ +public: + + /** + * @brief The connection status. + */ + enum Status { + StatusNegotiating, /**< Currently attempting to connect. */ + StatusConnected, /**< Currently connected. */ + StatusDisconnected /**< Currently disconnected. */ + }; + + /** + * @brief Sets the handler object which will receive callback methods. + * + * To have the TcpConnection call your object directly when packets are received, and when the + * connection is disconnected, you simply need to derive your class + * (multiply if necessary) from TcpConnectionHandler, then you can use + * this method to set the object the TcpConnection will call as appropriate. + * default = NULL (no callbacks made) + * + * @param handler The object which will be called for notifications. + */ + void SetHandler(TcpConnectionHandler *handler){ m_handler = handler; } + + /** + * @brief Returns the handler associated with this object. + */ + TcpConnectionHandler *GetHandler(){ return m_handler; } + + /** + * @brief Returns the current status of this connection. + */ + Status GetStatus(){ return m_status; } + + /** + * @brief Queues a message to be sent on this connection. + */ + void Send(const char *data, unsigned dataLen); + + /** + * @brief Disconnects and recycles the socket. + * + * @param notifyApplication primarily used internally, but when set to 'true', it will cause the application + * to be called back via the onTerminated handler due to this call (the callback will not occur if the connection was + * already disconnected) + */ + void Disconnect(bool notifyApplication=true); + + /** + * @brief Returns the ip on the other side of this connection. + */ + IPAddress GetDestinationIp(){ return m_destIP; } + + /** + * @brief Returns the port on the other side of this conection. + */ + short GetDestinationPort(){ return m_destPort; } + + /** + * @brief Standard AddRef/Release scheme + */ + void AddRef(); + + /** + * @brief Standard AddRef/Release scheme + */ + void Release(); + + bool wasRemovedFromMgr() { return m_wasConRemovedFromMgr; } + void setRemovedFromMgr() { m_wasConRemovedFromMgr = true; } + +protected: + friend class TcpManager; + TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, const IPAddress &destIP, short destPort, unsigned timeout); + int finishConnect();/**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */ + TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams ¶ms, SOCKET socket, const IPAddress &destIP, short destPort); + TcpConnection *m_nextConnection; /**< Double linked list imp. */ + TcpConnection *m_prevConnection; /**< Double linked list imp. */ + SOCKET m_socket; + int processOutgoing();/**< returns < 0 if fatal error and socket has been closed, =0 if sent data, call again immediately if want to, >0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */ + int processIncoming();/**< returns < 0 if fatal error and socket has been closed, =0 if read anything (full or partial message), >0 if nothing to read now, or would block so shouldn't try again immediately. */ + + + TcpConnection *m_nextKeepAliveConnection; /**< Double linked list imp. */ + TcpConnection *m_prevKeepAliveConnection; /**< Double linked list imp. */ + int m_aliveListId; + + TcpConnection *m_nextRecvDataConnection; + TcpConnection *m_prevRecvDataConnection; + int m_recvDataListId; + +private: + ~TcpConnection(); + void setOptions(); + TcpManager *m_manager; + bool translateRecvSocketEror(); + Status m_status; + TcpConnectionHandler *m_handler; + IPAddress m_destIP; + short m_destPort; + unsigned m_refCount; + TcpBlockAllocator *m_sendAllocator; + data_block *m_head; + data_block *m_tail; + unsigned m_bytesRead; + unsigned m_bytesNeeded; + TcpManager::TcpParams m_params; + char *m_recvBuff; + sockaddr_in m_addr; + unsigned m_connectTimeout; + Clock m_connectTimer; + + bool m_wasConRemovedFromMgr; +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif //TCPCONNECTION_H + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpConnection.o new file mode 100644 index 0000000000000000000000000000000000000000..ad8494680082ca70418e1616bb7ecb9438ea272b GIT binary patch literal 7692 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 WS?jX=jPUr!j2^6+*4@Z>jPYNG8(h8s literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpHandlers.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpHandlers.h new file mode 100644 index 00000000..440e0ae9 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpHandlers.h @@ -0,0 +1,50 @@ +#ifndef TCPHANDLERS_H +#define TCPHANDLERS_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +class TcpConnection; + +/** + * @brief Interface used by TcpManager class for notification to application of connection state/etc. + * + * Note: these callbacks will only be made when during a call to TcpManager::giveTime. + */ +class TcpManagerHandler +{ + public: + /** + * @brief Callback made when a new connection has been established by the manager. + */ + virtual void OnConnectRequest(TcpConnection *con)=0; + +}; + +/** + * @brief Interface used by TcpConnection class for notification to application of connection state/etc. + * + * Note: these callbacks will only be made when during a call to TcpManager::giveTime. + */ +class TcpConnectionHandler +{ + public: + /** + * @brief Callback made when a new message has been received on the specified connection. + */ + virtual void OnRoutePacket(TcpConnection *con, const unsigned char *data, int dataLen)=0; + + /** + * @brief Callback made when the specified connection has closed, or been closed. + */ + virtual void OnTerminated(TcpConnection *con)=0; +}; + + +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif //TCPHANDLERS_H + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.cpp new file mode 100644 index 00000000..a89065a6 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.cpp @@ -0,0 +1,746 @@ +#include "TcpManager.h" +#include +#include "IPAddress.h" +#include "TcpConnection.h" + +#ifndef WIN32 + #include +#endif + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +TcpManager::TcpParams::TcpParams() +: port(0), + maxConnections(10), + incomingBufferSize(64*1024), + outgoingBufferSize(64*1024), + allocatorBlockSize(8*1024), + allocatorBlockCount(16), + maxRecvMessageSize(0), + keepAliveDelay(0), + noDataTimeout(0) +{ + memset(bindAddress, 0, sizeof(bindAddress)); +} + +TcpManager::TcpParams::TcpParams(const TcpParams &cpy) +: port(cpy.port), + maxConnections(cpy.maxConnections), + incomingBufferSize(cpy.incomingBufferSize), + outgoingBufferSize(cpy.outgoingBufferSize), + allocatorBlockSize(cpy.allocatorBlockSize), + allocatorBlockCount(cpy.allocatorBlockCount), + maxRecvMessageSize(cpy.maxRecvMessageSize), + keepAliveDelay(cpy.keepAliveDelay), + noDataTimeout(cpy.noDataTimeout) +{ +} + +TcpManager::TcpManager(const TcpParams ¶ms) +: m_handler(NULL), + m_keepAliveList(NULL, 1), + m_aliveList(NULL, 2), + m_noDataList(NULL, 1), + m_dataList(NULL, 2), + m_params(params), + m_refCount(1), + m_connectionList(NULL), + m_connectionListCount(0), + m_socket(INVALID_SOCKET), + m_boundAsServer(false), + m_allocator(params.allocatorBlockSize, params.allocatorBlockCount), + m_keepAliveTimer(), + m_noDataTimer() +{ + if (params.keepAliveDelay > 0) + m_keepAliveTimer.start(); + + if (params.noDataTimeout > 0) + m_noDataTimer.start(); + +#if defined(WIN32) + WSADATA wsaData; + WSAStartup(MAKEWORD(1,1), &wsaData); + + FD_ZERO(&m_permfds);//select only used on win32 +#endif + +} + + +TcpManager::~TcpManager() +{ +#if defined(WIN32) + WSACleanup(); +#endif + + if (m_boundAsServer) + { +#if defined(WIN32) + closesocket(m_socket); +#else + close(m_socket); +#endif + } + while (m_connectionList != NULL) + { + TcpConnection *con = m_connectionList; + m_connectionList = m_connectionList->m_nextConnection; + con->Release(); + m_connectionListCount--; + } +} + + +bool TcpManager::BindAsServer() +{ + + m_socket = socket(AF_INET, SOCK_STREAM, 0); + + if (m_socket != INVALID_SOCKET) + { +#if defined(WIN32) + +#pragma warning(push) +#pragma warning(disable : 4127) + FD_SET(m_socket, &m_permfds);//the socket this server is listening on +#pragma warning(pop) + + unsigned long isNonBlocking = 1; + int outBufSize = m_params.outgoingBufferSize; + int inBufSize = m_params.incomingBufferSize; + int keepAlive = 1; + int reuseAddr = 1; + struct linger ld; + ld.l_onoff = 0; + ld.l_linger = 0; + + if (ioctlsocket(m_socket, FIONBIO, &isNonBlocking) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&outBufSize, sizeof(outBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&inBufSize, sizeof(inBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepAlive, sizeof(keepAlive)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) != 0 ) + { + return false; + } +#else // linux is to remain the default compile mode + unsigned long isNonBlocking = 1; + unsigned long keepAlive = 1; + unsigned long outBufSize = m_params.outgoingBufferSize; + unsigned long inBufSize = m_params.incomingBufferSize; + unsigned long reuseAddr = 1; + struct linger ld; + ld.l_onoff = 0; + ld.l_linger = 0; + + if (ioctl(m_socket, FIONBIO, &isNonBlocking) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &outBufSize, sizeof(outBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &inBufSize, sizeof(inBufSize)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0 + || setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) != 0) + { + return false; + } +#endif + } + else + { + return false; + } + + + struct sockaddr_in addr_loc; + addr_loc.sin_family = AF_INET; + addr_loc.sin_port = htons(m_params.port); + addr_loc.sin_addr.s_addr = htonl(INADDR_ANY); + if (m_params.bindAddress[0] != 0) + { + unsigned long address = inet_addr(m_params.bindAddress); + if (address == INADDR_NONE) + { + struct hostent * lphp; + lphp = gethostbyname(m_params.bindAddress); + if (lphp != NULL) + addr_loc.sin_addr.s_addr = ((struct in_addr *)(lphp->h_addr))->s_addr; + } + else + { + addr_loc.sin_addr.s_addr = address; + } + } + + if (bind(m_socket, (struct sockaddr *)&addr_loc, sizeof(addr_loc)) != 0) + { + return false; + } + + if (listen(m_socket, 1000) != 0) + { + return false; + } + + m_boundAsServer = true; + return true; +} + +TcpConnection *TcpManager::acceptClient() +{ + TcpConnection *newConn = NULL; + + if (m_boundAsServer && m_connectionListCount < m_params.maxConnections) + { + + sockaddr_in addr; + int addrLength = sizeof(addr); + SOCKET sock = ::accept(m_socket, (sockaddr *) &addr, (socklen_t *) &addrLength); + + + if (sock != INVALID_SOCKET) + { + newConn = new TcpConnection(this, &m_allocator, m_params, sock, IPAddress(addr.sin_addr.s_addr), ntohs(addr.sin_port)); + addNewConnection(newConn); + if (m_handler != NULL) + { + m_handler->OnConnectRequest(newConn); + } + } + } + + return newConn; +} + +void TcpManager::SetHandler(TcpManagerHandler *handler) +{ + m_handler = handler; +} + +SOCKET TcpManager::getMaxFD() +{ +#ifdef WIN32 + return 0;//this param is not used on win32 for select, only on unix +#else + SOCKET maxfd = 0; + + if (m_boundAsServer) + maxfd = m_socket+1; + + TcpConnection *next = NULL; + for (TcpConnection *con = m_connectionList ; con != NULL ; con = next) + { + next = con->m_nextConnection; + if (con->GetStatus() != TcpConnection::StatusDisconnected && con->m_socket > maxfd) + { + maxfd = con->m_socket + 1; + } + } + return maxfd; +#endif +} + +TcpConnection *TcpManager::getConnection(SOCKET fd) +{ + TcpConnection *next = NULL; + for (TcpConnection *con = m_connectionList ; con != NULL ; con = next) + { + next = con->m_nextConnection; + if (con->m_socket == fd) + { + return con; + } + } + //if get here ,couldn't find it + return NULL; +} + +bool TcpManager::GiveTime(unsigned maxTimeAcceptingConnections,unsigned maxSendTimePerConnection, unsigned maxRecvTimePerConnection) +{ + bool processedIncoming = false; + + if (maxTimeAcceptingConnections == 0 && maxSendTimePerConnection==0 && maxRecvTimePerConnection==0) + { + //they don't want to do anything now + return processedIncoming; + } + + AddRef(); //keep a reference to ourself in case we callback to the application and the application releases us. + + + + //first process outgoing on each connection, and finish establishing connections, if params say to + if (m_connectionListCount != 0 && maxSendTimePerConnection != 0) + { + + // Send output from last heartbeat + TcpConnection *next = NULL; + for (TcpConnection *con = m_connectionList ; con != NULL ; con = next) + { + con->AddRef(); + if (next) next->Release(); + next = con->m_nextConnection; + if (next) next->AddRef(); + if(con->GetStatus() == TcpConnection::StatusConnected) + { + Clock timer; + timer.start(); + while(!timer.isDone(maxSendTimePerConnection)) + { + int err = con->processOutgoing(); + + if (err > 0) + { + //couldn't finish processing last request, don't try more + break; + } + else if (err < 0) + { + break; + } + } + con->Release(); + } + else if (con->GetStatus() == TcpConnection::StatusNegotiating) + { + if (con->finishConnect() < 0) + { + con->Release(); + continue; + } + con->Release(); + } + else //inactive client in client list???? + { + removeConnection(con); + con->Release(); + continue; + } + } + + } + + //process incoming messages (including connect requests) + if (( + m_boundAsServer //if in server mode and want to spend time accepting clients + && maxTimeAcceptingConnections != 0 + ) + || + ( + m_connectionListCount != 0 //if there are connections and want to spend time receiving on them + && maxRecvTimePerConnection != 0 + ) + ) + { +#ifdef WIN32 + SOCKET maxfd = getMaxFD(); //re-calc maxfd every time select on WIN32 + + //select on all fd's + struct timeval timeout; + + fd_set tmpfds; + tmpfds = m_permfds; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + int cnt = select(maxfd, &tmpfds, NULL, NULL, &timeout); // blocks for timeout + + + if (cnt > 0) + { + if (m_boundAsServer && maxTimeAcceptingConnections != 0) + {//activity on our socket means connect requests + + //see if are new incoming clients + if (FD_ISSET(m_socket, &tmpfds)) + { + //yep + Clock timer; + timer.start(); + while (acceptClient() && !timer.isDone(maxTimeAcceptingConnections)) + { + //loop + } + } + } + + + + //process incoming client messages + if (maxRecvTimePerConnection != 0) + { + TcpConnection *next = NULL; + for (TcpConnection *con = m_connectionList ; con != NULL ; con = next) + { + con->AddRef(); + if (next) next->Release(); + next = con->m_nextConnection; + if (next) next->AddRef(); + + SOCKET fd = con->m_socket; + if (fd == INVALID_SOCKET) + { + //invalid socket in list?, check if is connecting, otherwise, Disconnect and discard + if (con->GetStatus() != TcpConnection::StatusNegotiating) + { + removeConnection(con); + con->Release(); + continue; + } + } + + if (FD_ISSET(fd, &tmpfds)) + { + Clock timer; + timer.start(); + while(!timer.isDone(maxRecvTimePerConnection) && con->GetStatus() == TcpConnection::StatusConnected) + { + int err = con->processIncoming(); + if (err >= 0) + { + processedIncoming = true; + } + + if (err > 0) + { + //couldn't finish processing last request, don't try more + break; + } + else if (err < 0) + { + break; + } + + }//while(!timer...) + }//if (FD_ISSET...) + con->Release(); + }//for (...) + } //maxRecvTimePerConnection != 0 + }//cnt > 0 +#else //on UNIX use poll + + int numfds = m_connectionListCount; + int idx = 0; + if (m_boundAsServer) + { + numfds++; + idx++; + } + + struct pollfd pollfds[numfds]; + + if (m_boundAsServer) + { + pollfds[0].fd = m_socket; + pollfds[0].events |= POLLIN; + } + + TcpConnection *next = NULL; + for (TcpConnection *con = m_connectionList ; con != NULL ; con = next, idx++) + { + next = con->m_nextConnection; + pollfds[idx].fd = con->m_socket; + pollfds[idx].events |= POLLIN; + pollfds[idx].events |= POLLHUP; + } + + + int cnt = poll(pollfds, numfds, 1); + + if(cnt == SOCKET_ERROR) + { + //poll not working? + //TODO: need to notify client somehow, don't think we can assume a fatal error here + } + else if (cnt > 0) + { + for (idx = 0; idx < numfds; idx++) + { + //find corresponding TcpConnection + //TODO: optimize, seriously, this is takes linear time, every time + TcpConnection *con = getConnection(pollfds[idx].fd); + + if (pollfds[idx].revents & POLLIN) + { + if (m_boundAsServer && maxTimeAcceptingConnections != 0 && pollfds[idx].fd == m_socket) + { + //new incoming clients + Clock timer; + timer.start(); + while (acceptClient() && !timer.isDone(maxTimeAcceptingConnections)) + { + //loop + } + + continue;//don't try to readmsgs from listening fd + } + + //process regular msg(s) + if (con == NULL) + { + close(pollfds[idx].fd); + continue; + } + + Clock timer; + timer.start(); + con->AddRef();//so it can't get deleted while we are checking it's status + while(!timer.isDone(maxRecvTimePerConnection) && con->GetStatus() == TcpConnection::StatusConnected) + { + int err = con->processIncoming(); + if (err >= 0) + { + processedIncoming = true; + } + + if (err > 0) + { + //couldn't finish processing last request, don't try more + break; + } + else if (err < 0) + { + break; + } + + }//while(!timer....) + con->Release(); + }//if(pollfds[... + else if (pollfds[idx].revents & POLLHUP) + { + if (con == NULL) + { + close(pollfds[idx].fd); + continue; + } + + //Disconnect client + con->Disconnect(); + } + }//for (idx=0.... + }//else if (cnt > 0) + +#endif + }//wanted to process incoming messages or connect requests + + //now process any keepalives, if time to do that + if (m_params.keepAliveDelay > 0 && m_keepAliveTimer.isDone(m_params.keepAliveDelay)) + { + TcpConnection *next = NULL; + for (TcpConnection *con = m_keepAliveList.m_beginList ; con != NULL ; con = next) + { + con->AddRef(); + if (next) next->Release(); + next = con->m_nextKeepAliveConnection; + if (next) next->AddRef(); + + con->Send(NULL, 0); //note: this request will move the connection from the keepAliveList to the aliveList + con->Release(); + } + + //now move the complete alive list over to the keepalive list to reset those timers + m_keepAliveList.m_beginList = m_aliveList.m_beginList; + m_aliveList.m_beginList = NULL; + + //switch id's for those connections that were in the alive list last go - around + int tmpID = m_aliveList.m_listID; + m_aliveList.m_listID = m_keepAliveList.m_listID; + m_keepAliveList.m_listID = tmpID; + + m_keepAliveTimer.reset(); + m_keepAliveTimer.start(); + } + + //now process any noDataCons, if time to do that + if (m_params.noDataTimeout > 0 && m_noDataTimer.isDone(m_params.noDataTimeout)) + { + TcpConnection *next = NULL; + for (TcpConnection *con = m_noDataList.m_beginList ; con != NULL ; con = next) + { + con->AddRef(); + if (next) next->Release(); + next = con->m_nextRecvDataConnection; + if (next) next->AddRef(); + + //time to disconnect this guy + con->Disconnect(); + con->Release(); + } + + //now move the complete data list over to the nodata list to reset those timers + m_noDataList.m_beginList = m_dataList.m_beginList; + m_dataList.m_beginList = NULL; + + //switch id's for those connections that were in the data list last go - around + int tmpID = m_dataList.m_listID; + m_dataList.m_listID = m_noDataList.m_listID; + m_noDataList.m_listID = tmpID; + + m_noDataTimer.reset(); + m_noDataTimer.start(); + } + + Release(); + + return processedIncoming; +} + +TcpConnection *TcpManager::EstablishConnection(const char *serverAddress, unsigned short serverPort, unsigned timeout) +{ + if (m_boundAsServer) + { + //can't open outgoing connections when in server mode + // use a different TcpManager to do that + return NULL; + } + + if (m_connectionListCount >= m_params.maxConnections) + return(NULL); + + // get server address + unsigned long address = inet_addr(serverAddress); + if (address == INADDR_NONE) + { + struct hostent * lphp; + lphp = gethostbyname(serverAddress); + if (lphp == NULL) + return(NULL); + address = ((struct in_addr *)(lphp->h_addr))->s_addr; + } + IPAddress destIP(address); + + TcpConnection *con = new TcpConnection(this, &m_allocator, m_params, destIP, serverPort, timeout); + con->AddRef();//for the client - to conform to UdpLibrary method + addNewConnection(con); + + return con; +} + +void TcpManager::addNewConnection(TcpConnection *con) +{ + con->AddRef(); +#ifdef WIN32 //uses select + if (con->m_socket != INVALID_SOCKET) + { +#pragma warning(push) +#pragma warning(disable : 4127) + FD_SET(con->m_socket, &m_permfds); +#pragma warning(pop) + } +#endif + con->m_nextConnection = m_connectionList; + con->m_prevConnection = NULL; + if (m_connectionList != NULL) + m_connectionList->m_prevConnection = con; + m_connectionList = con; + m_connectionListCount++; + + con->m_nextKeepAliveConnection = m_aliveList.m_beginList; + con->m_prevKeepAliveConnection = NULL; + if (m_aliveList.m_beginList != NULL) + m_aliveList.m_beginList->m_prevKeepAliveConnection = con; + m_aliveList.m_beginList = con; + con->m_aliveListId = m_keepAliveList.m_listID;//start it out thinking it's already in the alive list, since it is + + con->m_nextRecvDataConnection = m_dataList.m_beginList; + con->m_prevRecvDataConnection = NULL; + if (m_dataList.m_beginList != NULL) + m_dataList.m_beginList->m_prevRecvDataConnection = con; + m_dataList.m_beginList = con; + con->m_recvDataListId = m_noDataList.m_listID;//start it out thinking it's already in the data list, since it is +} + +void TcpManager::removeConnection(TcpConnection *con) +{ + if (!con->wasRemovedFromMgr()) + { + con->setRemovedFromMgr(); + m_connectionListCount--; + #ifdef WIN32 //select only used on win32 + if (con->m_socket != INVALID_SOCKET) + { +#pragma warning(push) +#pragma warning(disable : 4127) + FD_CLR(con->m_socket, &m_permfds); +#pragma warning(pop) + } + #endif + if (con->m_prevConnection != NULL) + con->m_prevConnection->m_nextConnection = con->m_nextConnection; + if (con->m_nextConnection != NULL) + con->m_nextConnection->m_prevConnection = con->m_prevConnection; + if (m_connectionList == con) + m_connectionList = con->m_nextConnection; + con->m_nextConnection = NULL; + con->m_prevConnection = NULL; + + if (con->m_prevKeepAliveConnection != NULL) + con->m_prevKeepAliveConnection->m_nextKeepAliveConnection = con->m_nextKeepAliveConnection; + if (con->m_nextKeepAliveConnection != NULL) + con->m_nextKeepAliveConnection->m_prevKeepAliveConnection = con->m_prevKeepAliveConnection; + + if (m_aliveList.m_beginList == con) + m_aliveList.m_beginList = con->m_nextKeepAliveConnection; + else if (m_keepAliveList.m_beginList == con) + m_keepAliveList.m_beginList = con->m_nextKeepAliveConnection; + con->m_nextKeepAliveConnection = NULL; + con->m_prevKeepAliveConnection = NULL; + + + + if (con->m_prevRecvDataConnection != NULL) + con->m_prevRecvDataConnection->m_nextRecvDataConnection = con->m_nextRecvDataConnection; + if (con->m_nextRecvDataConnection != NULL) + con->m_nextRecvDataConnection->m_prevRecvDataConnection = con->m_prevRecvDataConnection; + + if (m_dataList.m_beginList == con) + m_dataList.m_beginList = con->m_nextRecvDataConnection; + else if (m_noDataList.m_beginList == con) + m_noDataList.m_beginList = con->m_nextRecvDataConnection; + con->m_nextRecvDataConnection = NULL; + con->m_prevRecvDataConnection = NULL; + + + + con->Release(); + } +} + +void TcpManager::AddRef() +{ + m_refCount++; +} + +void TcpManager::Release() +{ + if (--m_refCount == 0) + delete this; +} + +IPAddress TcpManager::GetLocalIp() const +{ + struct sockaddr_in addr_self; + memset(&addr_self, 0, sizeof(addr_self)); + socklen_t len = sizeof(addr_self); + getsockname(m_socket, (struct sockaddr *)&addr_self, &len); + return(IPAddress(addr_self.sin_addr.s_addr)); + +} + +unsigned int TcpManager::GetLocalPort() const +{ + struct sockaddr_in addr_self; + memset(&addr_self, 0, sizeof(addr_self)); + socklen_t len = sizeof(addr_self); + getsockname(m_socket, (struct sockaddr *)&addr_self, &len); + return(ntohs(addr_self.sin_port)); +} + + +#ifdef EXTERNAL_DISTRO +}; +#endif + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.h new file mode 100644 index 00000000..75eb6df4 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.h @@ -0,0 +1,287 @@ +#ifndef TCPMANAGER_H +#define TCPMANAGER_H + +#include "TcpHandlers.h" + +#include "TcpBlockAllocator.h" +#include "IPAddress.h" +#include "Clock.h" + +#if defined(WIN32) + #include + typedef int socklen_t; +#else // for non-windows platforms (linux) + #include + #include + #include + #include + #include + #include + #include + const int INVALID_SOCKET = 0xFFFFFFFF; + const int SOCKET_ERROR = 0xFFFFFFFF; + typedef int SOCKET; +#endif + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ +#endif + +class TcpConnection; + +struct ConnectionList +{ + ConnectionList(TcpConnection *con, int id) : m_beginList(con), m_listID(id) {} + + TcpConnection *m_beginList; + int m_listID; +}; + +/** + * @brief The purpose of the TcpManager is to manage a set of connections that are coming in on a particular port. + * + */ +class TcpManager +{ +public: + + /** @brief Parameters for the TcpManager. */ + struct TcpParams + { + /** @brief Simple constructor sets default values for members. */ + TcpParams(); + + /** @brief Simple copy constructor. */ + TcpParams(const TcpParams &cpy); + + /** + * @brief Connection port number. + * + * this is the port number that this manager will use for all incoming and outgoing data. On the client side + * this is typically set to 0, which causes the manager object to randomly pick an available port. On the server + * side, this port should be set to a specific value as it will represent the port number that clients will use + * to connect to the server (ie. the listening port). It's generally a good idea to give the user on the client + * side the option of fixing this port number at a specific value as well as it is often necessary for them to + * do so in order to navigate company firewalls which may have specific port numbers open to them for this purpose. + * default = 0 + */ + unsigned short port; + + /** + * @ brief Server bind ip. + * + */ + char bindAddress[64]; + + + /** + * @brief Maximum number of connections that can be established by this manager. + * + * this is the maximum number of connections that can be established by this manager, any incoming/outgoing connections + * over this limit will be refused. On the client side, this typically only needs to be set to 1, though there + * is little harm in setting this number larger. + * default = 10 + */ + unsigned maxConnections; + + /** + * @brief The size of the incoming socket buffer. + * + * The client will want to set this fairly small (32k or so), but the server + * will want to set this fairly large (512k) + * default = 64k + */ + unsigned incomingBufferSize; + + /** + * @brief The size of the outgoing socket buffer. + * + * The client will want to set this fairly small (32k or so), but the server + * will want to set this fairly large (512k) + * default = 64k + */ + unsigned outgoingBufferSize; + + /** + * @brief The block size of a single outgoing buffer memory allocator block. + * + * This param should allways be set at least as high as the maximum message size you + * expect to send (performance will suffer otherwise). + * default = 8K + */ + unsigned allocatorBlockSize; + + /** + * @brief The number of block memory allocator 'blocks' created at a time. + * + * This is the number of blocks created for the buffer allocator for each + * TcpConnection opened by this manager. Since the block size should be + * the max size of an outgoing message, the recommended setting is: greater + * than the number of concurrent connections you expect to normally have open. + * default = 1024 + */ + unsigned allocatorBlockCount; + + /** + * @brief The maximum size that a recvd message is allowed to be. + * + * Really only here for protection, not required. If you set this, you can safeguard + * your client/server from receiving stray oversized messages. If a message on the socket + * specifies it's length at larger than this value, then the message is not read, and the connection + * is terminated. If the value is set to 0, then there is no max message size checking + * on incoming messages (this will also cary a performance hit, since every new message + * recieved will have to have a new buffer created if you don't specify a value here). Be careful + * not to set this too small, if you have messages that could exceed the value you set here + * they will be discarded, and the connection will be terminated without warning. + * default = 0 + */ + unsigned maxRecvMessageSize; + + unsigned keepAliveDelay; + + unsigned noDataTimeout; + }; + + + /** + * @brief + */ + TcpManager(const TcpParams ¶ms); + + /** + * @brief Use to specify a handler object to receive callbacks. + * + * To have the TcpManager call your object directly when connection requests come in, you + * simply need to derive your class (multiply if necessary) from TcpManagerHandler, then you can use + * this method to set the object the TcpManager will call as appropriate. The TcpConnection object + * also has a handler mechanism that replaces the other callback functions below, see TcpConnection::SetHandler + * default = NULL (no callbacks made) + * + * @param handler The object which will be called for manager related notifications. + */ + void SetHandler(TcpManagerHandler *handler); + + /** + * @brief This function MUST be called on a regular basis in order to give the manager object time to service the socket and give time to various connection objects that may need processing time, etc. + * + * @param maxTimeAcceptingConnections The max amount of time in milliseconds to spend accepting new client connections. + * This parameter is only used if this manager has been bound as a server (bindAsServer). + * If you set this param to 0, it will not attempt to accept any new connections. + * + * @param giveConnectionsTime + * True if every connection opened on this manager is given time in this call, false if + * no connections are given time. + * + * @param maxSendTimePerConnection Max amount of time in milliseconds to spend on each client processing outgoing messages. + * A max of the specified amount of time will be spent on each and every individual connection. If you set + * this parametrer to 0, it will not process any outgoing messages on any clients. Note also that when attempting + * to establish new connections (via the EstablishConnection method), this parameter must be > 0 in order to + * complete the connection process for any connections that were still negotiating. + * + * @param maxRecvTimePerConnection Max amount of time in milliseconds to spend on each client processing incoming messages. + * A max of the specified amount of time will be spent on each and every individual connection. If you set + * this param to 0, it will not process any incoming messages on any clients. + * This is a good way to give the manager processing time for outgoing packets in situations + * where the application does not want to have to worry about processing incoming packets. + * + * @return true if any incoming packets were processed during this time slice, otherwise returns false + */ + bool GiveTime(unsigned maxTimeAcceptingConnections = 5, unsigned maxSendTimePerConnection = 5, unsigned maxRecvTimePerConnection = 5); + + /** + * @brief Used to establish a connection to a server that is listening at the specified address and port. + * + * The serverAddress will do a DNS lookup as appropriate. This call will block long enough to resolve + * the DNS lookup, but then will return a TcpConnection object that will be in a StatusNegotiating + * state until the connection is actually established. The application must give the manager + * object time after calling EstablishConnection or else the negotiation process to establish the + * connection will never have time to actually occur. Typically the client establishing the connection + * will call EstablishConnection, then sit in a loop calling TcpManager::GiveTime and checking to see + * if the status of the returned TcpConnection object is changed from StatusNegotiating. This allows + * the application to look for the ESC key or timeout an attempted connection. + * + * @param serverAddress The address of the server to open a connection to. + * + * @param serverPort The port of the server to open a connection to. + * + * @param timeout How long to attempt connecting to the server (in milliseconds). + * Setting the timeout value to something greater than 0 will cause the TcpConnection object to change + * from a StatusNegotiating state to a StatusDisconnected state after the timeout has expired. It will also cause + * the connect-complete callback to be called if the connection is succesfull. + * + * @return A pointer to a TcpConnection object. + * NULL if the manager object has exceeded its maximum number of connections + * or if the serverAddress cannot be resolved to an IP address. + */ + TcpConnection *EstablishConnection(const char *serverAddress, unsigned short serverPort, unsigned timeout = 0); + + /** + * @brief Binds this manager as a server which will listen for and accept incoming connections. + * + * @return 'true' if manager is able to bind succesfully, false otherwise. + */ + bool BindAsServer(); + + /** + * @brief Standard AddRef/Release scheme + */ + void AddRef(); + + /** + * @brief Standard AddRef/Release scheme + */ + void Release(); + + /** + * @brief Returns the ip address of this machine. If the machine is multi-homed, this value may be blank. + */ + IPAddress GetLocalIp() const; + + + /** + * @brief Returns the port the manager is actually using. This value will be the same as is specified in + * Params::port (or if Params::port was set to 0, this will be the dynamically assigned port number) + */ + unsigned int GetLocalPort() const; + +protected: + friend class TcpConnection; + void removeConnection(TcpConnection *con); + TcpManagerHandler *m_handler; + + ConnectionList m_keepAliveList; + ConnectionList m_aliveList; + + ConnectionList m_noDataList; + ConnectionList m_dataList; + +private: + ~TcpManager(); + TcpParams m_params; + int m_refCount; + TcpConnection *m_connectionList; + unsigned m_connectionListCount; +#ifdef WIN32 + fd_set m_permfds; /**< Used for select on WIN32 if we are in server mode. Keeps track of all clients connected to us. */ +#endif //WIN32 + SOCKET m_socket; + bool m_boundAsServer; + TcpBlockAllocator m_allocator; + Clock m_keepAliveTimer; + Clock m_noDataTimer; + + void addNewConnection(TcpConnection *con); + SOCKET getMaxFD(); + TcpConnection *getConnection(SOCKET fd); + TcpConnection *acceptClient(); +}; + +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif //TCPMANAGER_H + + + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/TcpLibrary/TcpManager.o new file mode 100644 index 0000000000000000000000000000000000000000..4c2f4d225c825d73a0699a9bf3f4ab0779386a92 GIT binary patch literal 8748 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/libAuctionTransferGameAPI.a b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/libAuctionTransferGameAPI.a new file mode 100644 index 0000000000000000000000000000000000000000..818a8930cc9d6dd3dac1b5e4a62880ed48e5a928 GIT binary patch literal 260171 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 +class CA2GZIPT +{ + public: + LPGZIP pgzip; + int Length; + public: + CA2GZIPT(char* lpsz,int len=-1):pgzip(0),Length(0) + { + Init(lpsz,len); + } + ~CA2GZIPT() + { + if(pgzip!=m_buffer) TRYFREE(pgzip); + } + void Init(char *lpsz,int len=-1) + { + if(lpsz==0) + { + pgzip=0; + Length=0; + return ; + } + if(len==-1) + { + len=(int)strlen(lpsz); + } + m_CurrentBufferSize=t_nBufferLength; + pgzip=m_buffer; + + + m_zstream.zalloc = (alloc_func)0; + m_zstream.zfree = (free_func)0; + m_zstream.opaque = (voidpf)0; + m_zstream.next_in = Z_NULL; + m_zstream.next_out = Z_NULL; + m_zstream.avail_in = 0; + m_zstream.avail_out = 0; + m_z_err = Z_OK; + m_crc = crc32(0L, Z_NULL, 0); + int err = deflateInit2(&(m_zstream), t_nLevel,Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, t_nStrategy); + m_outbuf = (Byte*)ALLOC(Z_BUFSIZE); + m_zstream.next_out = m_outbuf; + if (err != Z_OK || m_outbuf == Z_NULL) + { + destroy(); + return ; + } + m_zstream.avail_out = Z_BUFSIZE; + GZIP header[10]={0x1f,0x8b,Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE}; + write(header,10); + + m_zstream.next_in = (Bytef*)lpsz; + m_zstream.avail_in = len; + while (m_zstream.avail_in != 0) + { + if (m_zstream.avail_out == 0) + { + m_zstream.next_out = m_outbuf; + this->write(m_outbuf,Z_BUFSIZE); + m_zstream.avail_out = Z_BUFSIZE; + } + m_z_err = deflate(&m_zstream,Z_NO_FLUSH); + if (m_z_err != Z_OK) break; + } + m_crc = crc32(m_crc, (const Bytef *)lpsz, len); + if (finish() != Z_OK) { destroy(); return ;} + putLong(m_crc); + putLong (m_zstream.total_in); + destroy(); + } + private: + GZIP m_buffer[t_nBufferLength]; + int m_CurrentBufferSize; + z_stream m_zstream; + int m_z_err; /* error code for last stream operation */ + Byte *m_outbuf; /* output buffer */ + uLong m_crc; /* crc32 of uncompressed data */ + + int write(LPGZIP buf,int count) + { + if(buf==0) return 0; + if(Length+count>m_CurrentBufferSize) + { + int nTimes=(Length+count)/t_nBufferLength +1; + LPGZIP pTemp=pgzip; + pgzip=static_cast( malloc(nTimes*t_nBufferLength)); + m_CurrentBufferSize=nTimes*t_nBufferLength; + memcpy(pgzip,pTemp,Length); + if(pTemp!=m_buffer) free(pTemp); + } + memcpy(pgzip+Length,buf,count); + Length+=count; + return count; + } + + int finish() + { + uInt len; + int done = 0; + m_zstream.avail_in = 0; + for (;;) + { + len = Z_BUFSIZE - m_zstream.avail_out; + if (len != 0) + { + write(m_outbuf,len); + m_zstream.next_out = m_outbuf; + m_zstream.avail_out = Z_BUFSIZE; + } + if (done) break; + m_z_err = deflate(&(m_zstream), Z_FINISH); + if (len == 0 && m_z_err == Z_BUF_ERROR) m_z_err = Z_OK; + + done = (m_zstream.avail_out != 0 || m_z_err == Z_STREAM_END); + if (m_z_err != Z_OK && m_z_err != Z_STREAM_END) break; + } + return m_z_err == Z_STREAM_END ? Z_OK : m_z_err; + } + int destroy() + { + int err = Z_OK; + if (m_zstream.state != NULL) { + err = deflateEnd(&(m_zstream)); + } + if (m_z_err < 0) err = m_z_err; + TRYFREE(m_outbuf); + return err; + } + + void putLong (uLong x) + { + for(int n = 0; n < 4; n++) { + unsigned char c=(unsigned char)(x & 0xff); + write(&c,1); + x >>= 8; + } + } +}; +typedef CA2GZIPT<10> CA2GZIP; + + +template< int t_nBufferLength = 1024> +class CGZIP2AT +{ + public: + char *psz; + int Length; + CGZIP2AT(LPGZIP pgzip,int len):m_gzip(pgzip),m_gziplen(len),psz(0),Length(0),m_pos(0) + { + Init(); + } + ~CGZIP2AT() + { + if(psz!=m_buffer) TRYFREE(psz); + } + void Init() + { + if(m_gzip==0) + { + psz=0; + Length=0; + return ; + } + m_CurrentBufferSize=t_nBufferLength; + psz=m_buffer; + memset(psz,0,m_CurrentBufferSize+1); + + m_zstream.zalloc = (alloc_func)0; + m_zstream.zfree = (free_func)0; + m_zstream.opaque = (voidpf)0; + m_zstream.next_in = m_inbuf = Z_NULL; + m_zstream.next_out = Z_NULL; + m_zstream.avail_in = m_zstream.avail_out = 0; + m_z_err = Z_OK; + m_z_eof = 0; + m_transparent = 0; + m_crc = crc32(0L, Z_NULL, 0); + + m_zstream.next_in =m_inbuf = (Byte*)ALLOC(Z_BUFSIZE); + int err = inflateInit2(&(m_zstream), -MAX_WBITS); + if (err != Z_OK || m_inbuf == Z_NULL) + { + destroy(); + return; + } + m_zstream.avail_out = Z_BUFSIZE; + check_header(); + char outbuf[Z_BUFSIZE]; + int nRead; + while(true) + { + nRead=gzread(outbuf,Z_BUFSIZE); + if(nRead<=0) break; + write(outbuf,nRead); + } + destroy(); + } + private: + char m_buffer[t_nBufferLength+1]; + int m_CurrentBufferSize; + z_stream m_zstream; + int m_z_err; /* error code for last stream operation */ + Byte *m_inbuf; /* output buffer */ + uLong m_crc; /* crc32 of uncompressed data */ + int m_z_eof; + int m_transparent; + + int m_pos; + LPGZIP m_gzip; + int m_gziplen; + + void check_header() + { + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(); + if (c != gz_magic[len]) { + if (len != 0) m_zstream.avail_in++, m_zstream.next_in--; + if (c != EOF) { + m_zstream.avail_in++, m_zstream.next_in--; + m_transparent = 1; + } + m_z_err =m_zstream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(); + flags = get_byte(); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + m_z_err = Z_DATA_ERROR; + return; + } + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(); + len += ((uInt)get_byte())<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte() != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte()) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte()) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(); + } + m_z_err = m_z_eof ? Z_DATA_ERROR : Z_OK; + } + + int get_byte() + { + if (m_z_eof) return EOF; + if (m_zstream.avail_in == 0) + { + errno = 0; + m_zstream.avail_in =read(m_inbuf,Z_BUFSIZE); + if(m_zstream.avail_in == 0) + { + m_z_eof = 1; + return EOF; + } + m_zstream.next_in = m_inbuf; + } + m_zstream.avail_in--; + return *(m_zstream.next_in)++; + } + int read(LPGZIP buf,int size) + { + int nRead=size; + if(m_pos+size>=m_gziplen) + { + nRead=m_gziplen-m_pos; + } + if(nRead<=0) return 0; + memcpy(buf,m_gzip+m_pos,nRead); + m_pos+=nRead; + return nRead; + } + + int gzread(char* buf,int len) + { + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + + if (m_z_err == Z_DATA_ERROR || m_z_err == Z_ERRNO) return -1; + if (m_z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + m_zstream.next_out = (Bytef*)buf; + m_zstream.avail_out = len; + while (m_zstream.avail_out != 0) { + if (m_transparent) + { + /* Copy first the lookahead bytes: */ + uInt n = m_zstream.avail_in; + if (n > m_zstream.avail_out) n = m_zstream.avail_out; + if (n > 0) + { + zmemcpy(m_zstream.next_out,m_zstream.next_in, n); + next_out += n; + m_zstream.next_out = next_out; + m_zstream.next_in += n; + m_zstream.avail_out -= n; + m_zstream.avail_in -= n; + } + if (m_zstream.avail_out > 0) { + m_zstream.avail_out -=read(next_out,m_zstream.avail_out); + } + len -= m_zstream.avail_out; + m_zstream.total_in += (uLong)len; + m_zstream.total_out += (uLong)len; + if (len == 0) m_z_eof = 1; + return (int)len; + } + if (m_zstream.avail_in == 0 && !m_z_eof) + { + errno = 0; + m_zstream.avail_in = read(m_inbuf,Z_BUFSIZE); + if (m_zstream.avail_in == 0) + { + m_z_eof = 1; + } + m_zstream.next_in = m_inbuf; + } + m_z_err = inflate(&(m_zstream), Z_NO_FLUSH); + if (m_z_err == Z_STREAM_END) + { + /* Check CRC and original size */ + m_crc = crc32(m_crc, start, (uInt)(m_zstream.next_out - start)); + start = m_zstream.next_out; + if (getLong() != m_crc) { + m_z_err = Z_DATA_ERROR; + }else + { + (void)getLong(); + check_header(); + if (m_z_err == Z_OK) + { + uLong total_in = m_zstream.total_in; + uLong total_out = m_zstream.total_out; + inflateReset(&(m_zstream)); + m_zstream.total_in = total_in; + m_zstream.total_out = total_out; + m_crc = crc32(0L, Z_NULL, 0); + } + } + } + if (m_z_err != Z_OK || m_z_eof) break; + } + m_crc = crc32(m_crc, start, (uInt)(m_zstream.next_out - start)); + return (int)(len - m_zstream.avail_out); + } + uLong getLong() + { + uLong x = (uLong)get_byte(); + int c; + x += ((uLong)get_byte())<<8; + x += ((uLong)get_byte())<<16; + c = get_byte(); + if (c == EOF) m_z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; + } + int write(char* buf,int count) + { + if(buf==0) return 0; + if(Length+count>m_CurrentBufferSize) + { + int nTimes=(Length+count)/t_nBufferLength +1; + char *pTemp=psz; + psz=static_cast( malloc(nTimes*t_nBufferLength+1)); + m_CurrentBufferSize=nTimes*t_nBufferLength; + memset(psz,0,m_CurrentBufferSize+1); + memcpy(psz,pTemp,Length); + if(pTemp!=m_buffer) free(pTemp); + } + memcpy(psz+Length,buf,count); + Length+=count; + return count; + } + int destroy() + { + int err = Z_OK; + if (m_zstream.state != NULL) { + err = inflateEnd(&(m_zstream)); + } + if (m_z_err < 0) err = m_z_err; + TRYFREE(m_inbuf); + return err; +} + +}; +typedef CGZIP2AT<> CGZIP2A; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.c new file mode 100644 index 00000000..fae88b65 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define BASE 65521L /* 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 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#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); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/adler32.o new file mode 100644 index 0000000000000000000000000000000000000000..61a1f5d73152d09b64619570592e0d98ee644da8 GIT binary patch literal 1168 zcma)*&ubG=5XWbmO_MayjiMJl7z8Du@Yp0)s0R^B8xZj#(StwAHd$0i8cnvMpcn~z zSb{$e{R8wr@D!zZSqp;Xq#pFD#e-Tz4{f0owlm3$t{~{Z+s~Vs@6MZj``+E@Q!|>T zftUsn`0WAcBg4#*0kV*UxJU;qd!IY2sdHz~bf@Fpg;e)W+VhQPuf1jeTiRVW+yGV2 zso)nKpWeE+c`tan7vM&8iI98W*))s?izv9?qk=|nRP(jI(ZjBW9AQS7Iy1@?eT@A$ zGr=5VCYdSb4(3j#LF~LrcV7OWo*p)XAaLJ0$w5amTL0w2+7s$<R2XQ zI$h3X3Tkpf6*C3X%$vphL?+v`Yqr(0a{#J!tL|8HNT)gE6`7$(IrdElRMm1UP;;#o zsQHFtgK9R0p-Q7(x91&P^1tl>Dyi2|e&Ymkk^*dL=6+;Cg2=WGKskz$9NodUA7Vd( zB)c7|MLy}s#&OVI{Yz(}CWb?d>g^E+DdmsyoR2m 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/compress.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/compress.o new file mode 100644 index 0000000000000000000000000000000000000000..b215cecae8162ddf2c4ca5484d111a649d4c9456 GIT binary patch literal 1188 zcma)5&uddb5Z>2B6KxJrf))hLK_x|4@=_~WL6r6xg{G(>^S;tdQI(6S{FLWxd%5>s=EG)dTZKGl zXUplKVaw@{;2WTFaSf1N?)@GN241J#jc$BwU2b=ORf4`;d)Jc3+T9;IwX^ZAb^OgP zb$pE~=aU!OD|I%->wEVLUO(UQeh$AamR0$%%0yI-v@udv2Dk3q&JHhB`5u&JB8-}} zdD14dxy@Jds|?O~+IG(k!2er;Vk3#}m3XMFlexQbu>h z7bAa?3TF{$GrA+h&9|YnK!vo{0E`Z3?nHipnm!XACda-oFLsF7f8J>-EK$ywInQu| z{(O*qADBFF|Gx{|e*<`sMf?rpuO1}>`!)pqfqm)#Z65Cqdr5wj`tiQTFjvYDLh!l2 zxI_FEd4e4MjDDeyn!> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/crc32.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/crc32.o new file mode 100644 index 0000000000000000000000000000000000000000..f64169888d01c523b0d56f719e9b89068157ab2b GIT binary patch literal 2168 zcmcIlc{G$=7=Oo%nPCjmrbTMnq+}XIixh2B(xQ?QF~%6ij0qzptx}}4NNLj|rA-*a z*v8tT4Pz{0o01l7N=n*%_wv49bH`K@#=GtpxDZE2Evr(Mxoq-DnYI!6dW7whJKGr3n8< z+PGB?6C*3kaeA4BMX$&f1NYed|5kX(7chB9WJH5l|34a79NgZeh^kn(9xed1hpi6o z0n?1ZG=n|=MUF8^A(Pm;?{XZqP7Ey-k`8wAH&`Zd+7jcu63inTbT7&pH;-tmejKS% z95->u)XEP_+eR{#y*O-GaL9|6W!OPa(FZFQ5_h-yHMGRpUF}Z z7XOH#D*U9{NnewtmV)^7IW=Xu4Yu8R*PjaN%!6Ik^UJ9+hf}(X?w#&llwXNthr{$F0wK8 z&OBt-xRDspfXkyR;wRFo+oK}V0!B(RiAk*mXDyVnmlw)No2GOldNIjb$A-k~KFOu> zx0~7s$;Sm=hjFf)=beszex7W>@H!?pVkzR;@ivYq*ph@ZDC#8daxT^TbX%3mUEY?} z|CLN09Tu7WU2WLpxyZDB(8sW<{agp-w>9kaC664XGsH+2^1-k1tbA7#&}cnvq<4XRwWA?M`Y2!`d}J>xLkwkRC33 zn<*(csne2)KdDF)PiIxXx*4K4Gsvic5U$@C)Stq6y4%|8=q$dFn(V?4rIhQop6Stw z9iM_|rzMcK&WqK1uSg{C_36Nk_*qQ!b#wOYy3gb82(S_ieL?i|-)Nxx`Pif?$|ba( z_Q1Z0CsJp3cel%9=E}1MSI4A!yiBaA*%n)QzO=Y*+KLYKvJbr6N}hAxr6!_u_F}8_ zh4m)XItK&oo1g9RRvw`QyOMSfwUe5c+#cg^wps4GV84WYe^|J8-Z_P6oK=g@intJ+ z2Y41GH(Ot0^kgGVC%JXbEn`Z4`Vp5569Ql2dby{z*sQ!l8l9k;WSG*tF16U}lu-xg z&FMsbuy(9a;|fvh^lU5L*AYBY-~eYtbC-QV+`v#-ONvR_mT3l=I;Ub3N2v1ZXIbry zVWZRy6s4kS&zu(JhcA*QAOG$zu5^me7- z`t>Am5BjEfeyQs5W6v)a=x=J#KKD*Rtz8vPSXwN>PiGtPE_dmBR4ifnE@}wzpJmUl zOlfqfQF&9;w(qU$rmjrMyK*Zbw|RScI;*Wm${gO2pTDm-=N>awvhq@5##l|Oikw(t z?ZXMq&8rG{sxgdEZ;8yFU8-T=<95_UG;yk&l5svpr^G<5>2jc5!xUl7ojZeW%v$O+ zfo{&2ZppBqn=_eaObathx^W;^z-0$&n>_Z=nfh2~QyGe{Nyx3wk z!te|VLKyxcF&AM3iuzm}kx7ysoM`Xf9NSnv%aqF!5o4^a+*hH?XdS}2F$0Up31 zs1J@O0EKVjIH1tR1BF6^#%}`ipqK!K`G3n}f*cZ1Okll%m;n$gZ-sIVG-e9}*kpjx zQU5G}*cj-t1^<>28iRnv`T>sh2L0Y3j|B-TSRO=dP8jk5%@zXGMisUI_Ym&g@AZtq z;$hF2VD&H?!{7Y`hKJE1vHBL_ZIZI@Cf>; zqbYcB5~ESB1F%0B0nZ2WBGg7WfgB5S1_$ABIOgu)LT>OCaJ?AN?G7%qfQ#_BV)tKG SZ#ozY_X!6sp(%= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * 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. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * 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 FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + 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 + * and lookahead == 1 (input done one 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. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + 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]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* 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 >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#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); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.h new file mode 100644 index 00000000..b99a48a5 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/deflate.o new file mode 100644 index 0000000000000000000000000000000000000000..15234c08bfeb3796f7239d848a90a73034f4864f GIT binary patch literal 8124 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.c new file mode 100644 index 00000000..09e0a20b --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.c @@ -0,0 +1,875 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* @(#) $Id$ */ + +#include + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open return NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c != gz_magic[len]) { + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may + * be different from s->stream.total_out) in case of + * concatenated .gz files. Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + const voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char* ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/gzio.o new file mode 100644 index 0000000000000000000000000000000000000000..47cee4596fc2899e21e437a8c09c61576dc1f910 GIT binary patch literal 6952 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 + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + ZFREE(z, s->sub.trees.blens); + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.h new file mode 100644 index 00000000..173b2267 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infblock.o new file mode 100644 index 0000000000000000000000000000000000000000..38902f7f8aefd1a6c4bd0a3d354f6e0a16ad0b83 GIT binary patch literal 5740 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 = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ + f = q - c->sub.copy.dist; + while (f < s->window) /* modulo window size-"while" instead */ + f += s->end - s->window; /* of "if" handles invalid distances */ + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.h new file mode 100644 index 00000000..46821a02 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infcodes.o new file mode 100644 index 0000000000000000000000000000000000000000..051ae50ac0fff7ec2d1b0f8a3ee1dcbe3c4cb1e5 GIT binary patch literal 3496 zcmbtXZERCz6n^hkX$RGIIB?ObHGE{1S~{%8DnCl`u7DQ1Vh5rEWxK#;H%5E!keKwX*pUWAC+@D-lC_05}hfL=ty~{6YcclOx*&1b9o1@uwLru?N0pl}ldP6xFP4~|obyae0Cw(Tn_SoBYVlJST!>!D zelHZcAWA|Z;{Ro*8|C#XS!wLq}DFt4#UPGte4;YUDr=|)!T~~J(x6> z93>~+Y57eoO^&e>G0)K;{5j!Qmz11fot2MZ1zei$mwGxecOABysID)ddgxkTZ&?Q( zlb^#bf*Cepe&QfixS(1y(iQ_|9P!e?IRl&)NGajqR|uj8h>3QC#!drbD>-J;Xz4$G zBl`cIM^JWK6J?+RdRckTHLw}eZY3Auj!!SPN~idCS9vq0oB8tn2fn_Bf$Q*f%Z=b^ z@a4AoDmiftMu_&F;@a(o(22vq{8*vtA>gPzpA{VkPiw1x8m<GPYFqc>v??S#bV0tD_SOjJM3Kgn=mY~{I!_pyo zg0n`giO*xar-2awI}Ctr7QjVQ4Sd>qN`2_H;Aeovb@KdGE~de?6HN`UY7w+4MA;02u$@hv3o`Jy^|NYsc8eKudeE?=fo+3433&Z!|x(gt0kD2*V$;OI(w0&H7#j&tsUg zo2}0t+p>Ay!LI1`JjsP$>NIY)Kw}5K*PC0jHd?o%!`#!#=ygBeT5*#UAJjIYF9quR zARk3vg?pg!BY3tO;oM{oAZeWW)3_hw9M0YeN#~J-`zRR;p?Vl07DlG{jP{wr&|9~aw#7)w)4fLw(&l1~F0N&4p@LB~UuTyM#kC5b~? SC%#BNZpoA-pS0u-Oa1|?*6U;d literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.c new file mode 100644 index 00000000..aa7f1d4d --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.c @@ -0,0 +1,183 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + r = q - d; + if (r < s->window) /* wrap if needed */ + { + do { + r += s->end - s->window; /* force pointer in window */ + } while (r < s->window); /* covers invalid distances */ + e = s->end - r; + if (c > e) + { + c -= e; /* wrapped copy */ + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.h new file mode 100644 index 00000000..a31a4bbb --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffast.o new file mode 100644 index 0000000000000000000000000000000000000000..4be246255de9066590f1757a5bf9b41ceaab0ea6 GIT binary patch literal 1876 zcmb_d-)mcS6#w4jYSJo8-NFc4&?`mFrE-^~nKVwM%eY3XcW#xdNUbGHZntQX&g3S} zK~agrefK5Mf4~Qyeepp`AAB$kbRe>qzO-|Wpc5JvBtp#Mh>PdkA4wR>eDJ{cd(Qcu z&-eVwx!-&&zxEQxal|H$ILS~W&-Wq>}RTyGXEnB0p|wOy{dsnRX~d7xBha*rt!lk#50TWx#^ z6;!@?8l8F8=eX@`PgJ^{+Jxt`ELd2vSN_E_8TkV3&OA?d5wO^WK>HpLXrC3xJ1O6S zK%VtO_xb+`Tte+kZc_CI6b^yJ7M1I4K0wu-=wi3pPl`9MI4-+l@mGs? zu=A$^rh2k?r;&%!X~)#fy}WgAZD^l=fIV#3JGI&3VHV@7btkt8$y%9Kyqk^R?)Cd? zFauX(KJ0AcE7;Z$f9xOe(7a1OdM+)%tzi?d#Q4jucwcEYYH+(!BAuF`FEGW=KH#BW zQ^i)b;f!7@Ip{S8Go|{(Vw=thV5;zcU{tXRgGlFa7M;ZwJr6%cd&7p;^JnCH5M=NHzFD4!AXWqwX3B_g8s={hVUwPQIXB!xQZVbPZ;IoNyFsKJ zy%^c}tKaY6ey_3)PRXaMP5in_hb0nkX&g$n(8;PGd@w^a-pHxL5EJcq>(?U2H z3#$CK4hQKFaEeGr;w{$g3khHPD=qcVTp%Mv4<#+`r8AX`SybW$o6My!+rFe zC%^ZH7W6l2MSU~^>OB0fjMDvh`&TzHPV&$w81B2sA?pNZVn4)tW&~l(Mmo2=oG9p0 zlAKK@!%HxL=hGQ2CBe6_oJr`~5?TjJHc@z=ybeA%XwbJ7e;d+5-3g6Eeh@jNHf`x! Gmi{;JzS}YY literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffixed.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffixed.h new file mode 100644 index 00000000..77f7e763 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.c new file mode 100644 index 00000000..dfb2e867 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inflate.o new file mode 100644 index 0000000000000000000000000000000000000000..d0c306119f5c5523e64445de9a1db2c0e541e379 GIT binary patch literal 3744 zcma)8e{3699e=hj&b4)7uLMz8(7Y{72@{^3ZYXUvDYJ3IRyLWKbQ7a9u6g_rB-vC%ZL4a_AxHvG z8Hr)+A#24<405ka#*wv--Oyn&Y}5iqG6V~|o*IkQ{My{Wm>OtqA%yk6QEZ!yiz1)( zKXcqn@C>vk!>rbCCcg@mQp(nfy=X;QTpl(k16qrxoAGSSZm(Nd~RYVvsSn>+wFfAC>m zyvD`g{3||6e2@j_U!v0i92RjflPwBGn+r&_ULgO58#CD^fT)a+w$&Fr^8^H~p&u6^ zXr!gaYH)tji(|5-C)*F`Y03BuWUYi8e0{f`lC%$lmQUM~)j?2A)<;@6*!?iar5+GA zer}`(jkt7fP12U+1M$%8EvC0Cc{4S!b+YE7NoPqp-^_Sf}f7jbxE^oc? z#^1wLGYoQVm+7awzy41=71Iy5P6$^J&UGQA?Fz7Sm-gs!nF``F@kToeZ{AoTxro8^+UQzS**VZVRv&5f{2pim#x>i=Qb|y zWV-Xz(QDjLt#z%o=eoWMop-KTmNwUBHNSl?aP|Zn@4%d0CFsE3LP~O(>CGrVTgO9}Jou+gt?Hj%is(Zk2bg7V&@k7ei~>zn+Y2k0GR z0v-wJ?`v~1Q-c`fe2A+(+L&MMwWrQ^QQ`FA;~qW-Ac1}zh)2QYw&O-pHc}X5QM8xo z?->t-F05gq_VXAnTv~X<8hPLIDYs$7#elc{n2a7lY>5vb9@rv}i_e!ixnbdxGC`k| zojj2BS0Sy9^{MD8e`XW#%CDA@kua!tHfg@BKLaVK89^f@=?}Jy37PKLmaqQhKalVb zJ^PpwTfW(g`rCIVTfSslpO9fn59%3-M$nd2 zyUobRMjcc2%ENX&z|P2eeZWZu#iqJ+i*4tG4$D*(W1K!?z5KgX69wJ@YxdWRn!|4> z0_5M}Xe<(qQM9EKrExELjTn|?Zrxnn0 z=O0{bu6 z11Mh<`*rNUV-H|R+=u-F_RBOdm}RkvL}Gt|VF zcijR(x}!9$XpLj1=?01w5|BO7y-|9 z1lC<{y2L)Qx*W3S<`VAqK)A%?=;~~j_p>j6c@~@E^mJ~Et>I(*qT2|5edz4%0{af& zZfH;+oke*jv5EHxHt|z{&LVyu`?uJiM<~RvI7~p|pWcQ)y$#p5;Xehw0$X1MBzvy` zehmCAl!EZzY?EIC-b7k2022RC+xVA(r*L5|2tNI_8^WEVKR6`61Gb$-@nWnzUd*aW zB*&h}>YK49L17ScSxj{aS#UzIR{NE>et+((hdT#Wv-i` zoSZ&Y%60T`PL&IoP1^#mf{~fw95#tEdGR0?2-3$4HS`4W-U*_Jc|iJ-|A=rryq^%h zo3URJ#3TB>;D1CA?>d2D;6aZx0e>mr&FDGN!??@@?*;UJma#>G@c%UWPV|2Odf{g; z&fd>q#sd=l8sYGF2>tfrVH7D;*q#xP1~B0#1^k|XPYF0L;12|RR=`C8pBL~&0qO3N Iy_W_24}b^t)&Kwi literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.c new file mode 100644 index 00000000..5a5d6b66 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.c @@ -0,0 +1,454 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), or Z_DATA_ERROR if the input is invalid. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_DATA_ERROR; /* overflow of MANY */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.h new file mode 100644 index 00000000..04b73b72 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/inftrees.o new file mode 100644 index 0000000000000000000000000000000000000000..5ca11e740cbefaa76721b5b082ee45b2e89d36fb GIT binary patch literal 8920 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 literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.c new file mode 100644 index 00000000..9a076221 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.h new file mode 100644 index 00000000..4401df82 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/infutil.o new file mode 100644 index 0000000000000000000000000000000000000000..230ded53c9ac05ede459dd6f426b8e5411c5a8b3 GIT binary patch literal 1196 zcmcIj&ubG=5S~q9TWgA2DF}LSFKUA2u}Kp#60oGMdl4y=w4l^#3yDqTSwr2yYZ#$0N@@Sg>HC%GAzOkra9^+K(AqDr0WB1W-qD%Xd0w9j|NOFWh z{xHIHZe(jnz6{ggt3~+}j8rRiUt@EUg!+-`=<%0Jx|x6pKeFs8LYWiu4Z)*O5_}~$ zjY!T(L>~#fvMZB1iqS6=aK~75j2WE)t((?I`zIXlw}wO+$E3-A63ZALPr+||Ekhgq zlc|4v2Er-0HI!o(??(KM5jF{9a4#C6yO>7B;|SAT-@*D~tb+Chjn-z{YcyFMKGf^^ p8a}O^M$_J4L^LhWt~r+b@d|7<+wK-Pwo~8PhdnG$Oafd)@gJbA!nFVZ literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/maketree.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/maketree.c new file mode 100644 index 00000000..8e127ff4 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/maketree.c @@ -0,0 +1,51 @@ +/* maketree.c -- make inffixed.h table for decoding fixed codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* This program is included in the distribution for completeness. + You do not need to compile or run this program since inffixed.h + is already included in the distribution. To use this program + you need to compile zlib with BUILDFIXED defined and then compile + and link this program with the zlib library. Then the output of + this program can be piped to inffixed.h. */ + +#include +#include +#include "zutil.h" +#include "inftrees.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* generate initialization table for an inflate_huft structure array */ +void maketree(uInt b, inflate_huft *t) +{ + int i, e; + + i = 0; + while (1) + { + e = t[i].exop; + if (e && (e & (16+64)) == 0) /* table pointer */ + { + fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); + exit(1); + } + if (i % 4 == 0) + printf("\n "); + printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); + if (++i == (1<1q~ z4<+>G#iJ)ZcZ5Re=F(^WR z8PQus&IJic>ZNX-8sOZ<=ju-E?wwn;8{IWOmj3h(1s}h}x1x>b?`7YcjDNCP|5-rt zE2vEKcdON^*1s1J+j97w%CD_=qNq;1~Ar&O1STdQW_I4-bDjD@TjD+;Em3 z__9+Jc`J;NC-cH}X<^xQ%5s6kiX%zc9IE(|vR7xb%f8GJE02=AhQSYh2*?+OnY((4 jE&}<$uBkX?={iKTsCZHFRq(?^&%onEFI4;`IB)6?G|0QO literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.c new file mode 100644 index 00000000..0a984056 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.h new file mode 100644 index 00000000..72facf90 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/trees.o new file mode 100644 index 0000000000000000000000000000000000000000..1f1c64d7db6f4dc8a7cca3571529ee367702e6d8 GIT binary patch literal 12168 zcmcIq3w%>mn!ibtHf;kpKzSEoeZs)h7ICB$S1b*Wg~7GJ-BTyYqBrRv8^qz{RGp6qTLfF{`+^+L>WAwcW8ufB=!~|2y~IG%c(Q$e#ZG z`R6?Dd3^W#zVn^a)LQ4x(CKu7mUKdr(32B{xnq@@Nu0(CW+7E;%Gu8T!nz#$Hi4zC zj3U`#3U$O{F~9UIs+nX-7lbxx7(OZar8+##q)c9VD?T%LsXL8I$MVu_eA1Y%HtCHa z^iZ4h7H9hQD||DdOxhnV3eiMlM~H@JXEA<}Y&Y#1g~|IH1S39o($lUsYTgo^z2=O6 z8;!GT6bk$eVLa`3-=0{%YarE3pOx^4tF7T#g8+fFHT+ncM8m7`Z$FQJdr|$ikY>YW zkvYGZCL~)evcn?VO!ch~V`aJ%vY~-lqjLQ$EIoIhxKYBO%pR!^7NUUJ!nymrcgog? z|0x~wcFU8RWv^K_zbFPW0%E|h(Usd;-Otlswujdn223^#S)C+1x@C_^_C{r^x&8o+ zA)B|Oc{7@?qvp4H(zWJ8R}GWB7R-v7_cDhClW9<<;bXFu_hGXbsS7rB-NMBs@wLpQ zwOGxvh1sL>ECaJeyoEgFcW4Cp|3XUNvun#KQM`U^BmqQ zB4>OE8CANM=B+tH;;}_(_6>8f_+YzU5t3}MxY`Qp^;pVYs+h^_hw5Wfkry{UkA7t9 zVPS+$o{%qD_Jm^Ald?7HV(u69d5%c!9NFIPiW#bN zj^;VKo=%r--R$^yYnPl+k5*#9{G#755z`T059*reElb|8;2t7-!svIqUUyi0{UFw+ zTSvMuQ=QR9Yp-u5)6wMXh(f$? z3hvv{onmGF1v<8s^jyY@JYnXpH^`3g0mC4nGkp`OM_a)g=ypb)C-QU)*GUuHm|~Fi z`$&NmGf|Y2*-tWCh&j5Xh_1GjeSimOfNeB@|KTPBbVgU37PE$BYnbUfliScWdeF=E zDBI_1Gi=id2Mp?WeRJ9 zow0fBy6VXcwE{=6V!bgb5SUwB8&U^BD&Ds zL$WRWAjv2+;A`wnaYfX0pZjX7xy>3Ooy&>shR+woz$`tqFa=*5-}Rs}ydGb7C(+x4 zNB5YaH`|k;qSh#igj`2d+_-}(ttKPi(5&5LzYaJ!Gdnm_49wl0oaYUDO}PifwQJ~! z551{)FD~8GhR%CnLc{W`5qApwIqXM*8*;^(-ol2}IZ}$H)xuCv(9lc;Y0wZ?OnMvN zb7HU+Os{|9^g3_KJ;+OvF$$k>CrzJL!dC_xk6EL+o~XFNf%U3Z$@fsHi`yk!vemqc zgt42R5(Crp%o=X9b|WJ+lXS>6deU~2NSalVBnskTY`~jnf0eyqh=6$`*vG`cqF0ic zBOJ4K=i0lm5qYCCnfGL_BOpRi%QJ+b#H7K?$GC-UXq@HJ#YAH~30 z-usniuL*YV&R%j|BnGyVBHnnRj$miS09W$MrlZW|9eN?s`To8IFbiql*Vj1(F>r#N zAJ_9gjvJ5Ahp3tn4XD7$+J?@H(Cz23O-f^w%@oCS>_V}KVrl;v?2vwb+Cov)*;q{6Xg3xQiA8j?ixIrd!#OxTBU@&ZvGmGd{$T zc+XO+k?}bw79^cd_bv37#I8{-cn_GE7}%#+?~!8>7vuYi)Oto40GnIq2><*TJKQsP z(5PqxvxhZFn0+O(H$#(v)D~rtc>BLq44+;}3Sm_WBV=m^4!w|&wn<5?22}=Db53j) zq6YsKenhu-`8V)Wxve|Tn<4st0zLFMkrE&($9~JVHt9V18w7ScpCOgN7Ta)*()+)* zSgA$zJDs5!s&p#<6I)F|gT974C2qKVcRXm5zd)~rSHm$dbsO(A$re@223I}Bp|5c1qew>H zKzBg?{4?W%>>!;CA|`PoZ9>w8e(?9IQ@K8oX%=;{muJ!R^CqsJSC^a`+^LeI!1RVo zF7nNiizG;{8S#5t6UmGMdB5{`;u+jbXMX4$u9zGaHGG$RPYb?^I$x&VW9G8|1UnN6 z8kcbO!5GUR=wYe+pn|N91Yho$1A#c zO&!Om_h01b4Of~g4%gEPoO+CB>IX| zYMLvy_DveF^In|3z(P!-JJi`Imp0+hRDV8(!qsWw&U&iF{Y1_uvvTLcK_P`R%N@b{P(;auZDxM=%`W3Q13!XtLtY zsd^keBa$~Nh>b7eAzUVK3&xps500SSiaQ*49Ok?PUYt9^%w}~H?BfWp?U0EpfF5)1 zcnh8xV`FxE5`1BI#}<_H^R(TJO_-L21GyM@p@Ght%&s1amBa91OmZ3B8=-CBBs2L860?Iq|=SsCN0GN);BBw}tFXY}g9l4V~yEvpsrf z2bUV|H(nBMoJJ-HZnS0}fd(4ja^aDlN;DD1H^juVl(G@#9LO2gaxQeowDK z7sSOzS>?X^qs=3UG8~tOUt_aOm#RV z-c!A2&QW$;YS*Q<9_iE_osIkd?jv8Y!~CB}3GMhlz@&)9ldlA--x#4HWWB<_&N?S) z_fe4)-`GCg&?9Py>taeM%ZH5ciKzcuqf2QXG)GLnoBMQdS)|-)X>9Qg?9=MXGwT^c z>gpAb@QtS)VSp08@PGT!j+8GKo8%c8>oP6zyF7N>6%3guWH06sC~7}Cdt{wCvBkN= zY8!;8Qm3wZglg~nmT-Lv9-gVx)O7Xibb>$|Jtg`V=}iFrAB!S@Ix0lE37|5b)V70= zp=gVyOo@uKbF#8?c<$Oh=-EV2;GPJ&drbtio0LBeOjSq(vfr4rv9vL?zO_EJz7P}& z1X`!IR$4Dy5eLqX0s&D6hZ#)hrvh|C63vt5NOQ0Z7$}%hQj^n+=>~IBKYf3lh%rsV zv%p;75HJDw6;KIu0hz$dz#`ydU@Gu7@H7ww^gsiU53~X|1OE(^0)GN9qVPQM5O5Tj z2>b@92EGE)fc3yX0Pg|c0bTt-N0`F4{!$P2lxRS@E^c;fnNhp0RIDw z0{#hb0RIi#3;Y}41-=FbVFiP9slsOPW^fU>2z(5D415>(F7TV+H^DXF8t`fGX>d9? z9V~-o@Eq_Q@cZER!Q;W>!M_Cm68t#$ad0QN6Fd?;68sYQCGbM<5ej zl7K-#IxrGQ0fqwcq|+xE3`S!zQVNnuO{r>1>yy&^B=c2LzpJGF-!h5cGVxtu;GjVn zNQ04vsA;I0hV@Cq`=k+9Nh7b4GQVXS^(~V?@86h=_nw-XmX@AQuajOGy%rL!MNI?L zG*C^0)I@SiOeDj^q{&lbO|BaE5$|Q$KH|PCdlm7IxSIIM4k)J4;slCg$U3yxg)Eff z6pBsy1N5&2{L}!pD!@Jk_zmUfXxZS&z%-x`SOQc5b-=4Y3(yW+DfJzn#-?#;Od5~I z8UxT6(|{#F9nb>MMob0=D?jAF?+F9vb zTH_oi2w632o^UTM1-q*iUaoyZqb#@cNw<(i-^!P|mkL>>H8n!kij{6B3RfycWhPtBGVnX(T`%TuYm>1mQ3;^uFkMdY2?etb^w%4x}^& zKk=KYeC40ij?!&FVt-5SRNgK1N6%{gp_uop^|y$AGMJFG{wAS};!Z75JJKC3(HtpF z0kl_0`8u>)K!d7jjLP|7?HMXMeusc~uP14B15l*RjcPBU-JG6g@jepAr0NOZ5d`|B z6UF4W0<;d2HOVBgzmF#fh-FZyri8Cr5$D8mgK&zD!SU4lSEST`;s}(dJuNXM_D1!z z7b}UBONTtoxejB39bK1 zsz+X{Uxhp+dZ+Ze*tP0+ElWwIW5(loA z)aM5wp8+TLy!!mj$j^e^ZBgsLi~J&t*QDmZhy4B#0%B#QzXIgxwsa!qK>ZgXe-iCW z)p}4oCB>~5gz93Vq1`912Q5nxQ;hw--S9 z-FTkzTajz+u29RAYK*9~pz@`aO0GsITUoV69T7dc zDm^vJg&L>3gj{=xdrg%SEuN^VcGlGNv|3%UqTEv@l+a=!)N-ew%0SIvQG7KR5UX2R z?JQTHrGllE70Xr#^o{CtW-W0PKnx2 jRe3)#+I^(*s^LogT9q+<-X12ynfnerkLEl-LFNAiB0v4H literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.c new file mode 100644 index 00000000..a287714f --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.c @@ -0,0 +1,58 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress 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, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/uncompr.o new file mode 100644 index 0000000000000000000000000000000000000000..a706a49e3ff1744dc23ec006789b0356522ba14b GIT binary patch literal 1108 zcma)5&ubGw6n@)AQ?-XEK|v4ZqNFIpZfZpIkU)Fz;Gu_t9u*1(LGU275Z{-~YgaGz!Q1bBZ@zgmZ)WzjyKu*{EE2P5 zoDLb$V?(YD1$jC}6CxdADf$-n7alI%j~6H6SCg@uiA&kY-HJ*dqs8s8x4+TZiqnz1 zv+3?)!lv5?tld}zEbZW9Y#kvihC%|&(G%a#e1cxTtVHOQPa7CZ9Dd~ zGn31=bX|LGJw>G2FB^fk%owyrxGE8gRG?o3q^e%vky>uIN%_q{lWH|bsY^C+Fo znl!r@>Scv6VlCKpcEn>KY`Adg30!oy6EX5X*e@e6Cc4wiWp5bD@<7pO0HOoRn#gB) z(kI4~>^Lv%Lqp_NLdPzI^hbydlL=0{xfpVhrU-}P%j eS%{$PS5XpmE#B@N;}{?A10XlI0-PjzWAG0)Kb#K$ literal 0 HcmV?d00001 diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zconf.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zconf.h new file mode 100644 index 00000000..eb0ae2e1 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zlib.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zlib.h new file mode 100644 index 00000000..52cb529f --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 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 + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. 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. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress 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. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + 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. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress 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, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.c b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.c new file mode 100644 index 00000000..dfc38ec1 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.c @@ -0,0 +1,225 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.h new file mode 100644 index 00000000..718ebc15 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.o b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/zip/Zip/zutil.o new file mode 100644 index 0000000000000000000000000000000000000000..fe432b01cec9a1a2960af93c54ca9009b29e3ec7 GIT binary patch literal 1384 zcmah}%W4!+5Ut5WCpuyxD!~V~qB22jXC_84xKM{Npb~?Sh=PQko;$IjAJW|;W<*>B z7a>34GN0f+S>z+!3NEq{M6wXZbGq-19bBZK`qZhaTldy|^rzO-N2O9pjFeSoiRjJ6BEUth5+5=zTeZ56{2=!e=W zSJpcfCtegvyVvci*ivyE#mGoNJ=arVY6U8Y;#KK5siVV58Y?Hzr0bzdK1@s?>`16o z$Le@)isBB2*X_EE&6;aAXRYeo{Nj|=u;(^jKatJkLMGgdWLzH$;ZC1NM5LF%-D zX`JI5Vl)KPjfW_TnWJUVE*Iv?Zyx+=Rci(km_entries[ #_name_ ] = new HandlerEntry( #_name_, CentralCSHandler::HandlerEntry::_type_ ); + +#define REGISTER_HANDLED_CMD(_name_, _type_ ) \ +smp_instance->m_entries[ #_name_ ] = new HandlerEntry( #_name_, &CentralCSHandler::handle_##_name_, CentralCSHandler::HandlerEntry::_type_ ); + + +#define CS_CMD(_name_) void CentralCSHandler::handle_##_name_( GameServerCSRequestMessage& request ) +// statics + +CentralCSHandler * CentralCSHandler::smp_instance = 0; + +void CentralCSHandler::install() +{ + + smp_instance = new CentralCSHandler(); + REGISTER_CS_CMD( get_characters, TYPE_DB ); + REGISTER_CS_CMD( get_pc_info, TYPE_GAME_SERVER); + REGISTER_CS_CMD( undelete_item, TYPE_ARBITRARY_GAME_SERVER ); + REGISTER_CS_CMD( get_containment_info, TYPE_DB ); + REGISTER_CS_CMD( get_deleted_items, TYPE_DB ); + + REGISTER_CS_CMD( test, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( set_bank_credits, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( check_args, TYPE_GAME_SERVER ); + + REGISTER_CS_CMD( rename_player, TYPE_GAME_SERVER ); + + REGISTER_CS_CMD( list_objvars, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( set_objvar, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( add_objvar, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( remove_objvar, TYPE_GAME_SERVER ); + + REGISTER_CS_CMD( dump_info, TYPE_GAME_SERVER ); + + REGISTER_CS_CMD( get_player_id, TYPE_DB ); + + REGISTER_CS_CMD( move_object, TYPE_GAME_SERVER ); + REGISTER_CS_CMD( create_crafted_object, TYPE_GAME_SERVER ); + + REGISTER_CS_CMD( list_structures, TYPE_DB ); + + REGISTER_HANDLED_CMD( login_character, TYPE_CONDITIONAL_CENTRAL ); + REGISTER_CS_CMD( warp_player, TYPE_CONDITIONAL ); + +} + +void CentralCSHandler::remove() +{ + NOT_NULL(smp_instance); + delete smp_instance; +} + +void CentralCSHandler::handleStructureListResponse( StructureListMessage& msg ) +{ + std::string response; + response = "structurelist\r\n"; + response += "character_id:" + msg.getCharacterId().getValueString() + "\r\n"; + + std::vector data = msg.getData(); + + char buf[512]; + for( unsigned i = 0; i < data.size(); ++i ) + { + StructureListMessageData &row = data[ i ]; + snprintf(buf,512,"structure-%u:(%s)%s %s(%.02f %.02f %.02f)%ld\r\n", i, + row.m_structureId.getValueString().c_str(), + row.m_objectTemplate.c_str(), + row.m_location.c_str(), + row.m_coordinates.x, + row.m_coordinates.y, + row.m_coordinates.z, + row.m_deleted ); + + response += buf; + } + + // build the response message. + + CSToolResponse rmsg(0, response, msg.getToolId()); + CentralServer::getInstance().sendToLoginServer(msg.getLoginServerId(), rmsg); +} + + +void CentralCSHandler::handleFindObjectResponse( int iIndex, bool bFound ) +{ + // try to find the entry. + CentralCharFindMap::iterator it = m_findMap.find( iIndex ); + + // if it's there... + if( it != m_findMap.end() ) + { + CSCharacterFindInfo &info = *( it->second ); + // if we found the character... + if( bFound ) + { + // send the request to the appropriate game server and delete the entry + // make a new request + GameServerCSRequestMessage gsreq( info.iAccount, + info.commandLine, + info.iToolId, + info.iAccessLevel, + info.iLoginServerId, + info.user, + info.command ); + + // spam it, in case the object has moved servers in between. + CentralServer::getInstance().sendToAllGameServersExceptDBProcess( gsreq, true ); + + delete it->second; + + m_findMap.erase( it ); + + return; + } + + // otherwise, decrement the counter. + + info.responsesWaiting--; + + // if the counter is <= 0, + if( info.responsesWaiting <= 0 ) + { + // send the request to the DB or the appropriate central handler. + // make a new request + if( info.bCentral ) + { + // find the handler. + CentralCSHandlerMap::iterator it = m_entries.find( info.command ); + + // if we're here, we should have an entry, and it should be of + // TYPE_CONDITIONAL_CENTRAL. Still, better safe than sorry. + if( it != m_entries.end() ) + { + HandlerEntry & entry = *( it->second ); + + if( entry.type == HandlerEntry::TYPE_CONDITIONAL_CENTRAL ) + { + // make a CSToolRequest + GameServerCSRequestMessage gsreq( info.iAccount, + info.commandLine, + info.iToolId, + info.iAccessLevel, + info.iLoginServerId, + info.user, + info.command ); + + CentralCSHandlerFunc func = entry.func; + ( this->*func )( gsreq ); + } + } + // execute. + } + else + { + // fire to the DB. + DBCSRequestMessage dbreq( info.iAccount, + info.iAccessLevel, + info.iToolId, + info.iLoginServerId, + info.command, + info.commandLine ); + CentralServer::getInstance().sendToDBProcess(dbreq, true); + } + + delete it->second; + + m_findMap.erase( it ); + } + } +} + +void CentralCSHandler::handle( const CSToolRequest & req, uint32 loginServerId ) +{ + CentralCSHandlerMap::iterator it = m_entries.find( req.getCommandName() ); + int type = -1; + if( it != m_entries.end() ) + { + HandlerEntry & entry = *( it->second ); + type = entry.type; + } + + + switch( type ) + { + case HandlerEntry::TYPE_DB: + { + // send to DB + DBCSRequestMessage dbreq( req.getAccountId(), + req.getAccessLevel(), + req.getToolId(), + loginServerId, + req.getCommandName(), + req.getCommandString() ); + CentralServer::getInstance().sendToDBProcess( dbreq, true ); + } + break; + + + + case HandlerEntry::TYPE_CENTRAL: + { + // handle it here. + if( it->second->func != 0 ) + { + GameServerCSRequestMessage gsreq( req.getAccountId(), + req.getCommandString(), + req.getToolId(), + req.getAccessLevel(), + loginServerId, + req.getUserName(), + req.getCommandName() ); + CentralCSHandlerFunc func = it->second->func; + ( this->*func )( gsreq ); + } + } + break; + case HandlerEntry::TYPE_CONDITIONAL: + case HandlerEntry::TYPE_CONDITIONAL_CENTRAL: + { + static int sequence = 0; + // don't check twice. If we've already got one, that's fine. + // get the network id out of our command string. It should be the second word. + std::string::size_type pos; + std::string::size_type lastpos; + pos = req.getCommandString().find(" "); + if(pos == std::string::npos) + return; + lastpos = req.getCommandString().find(" ", pos + 1); + + std::string idstring; + if(lastpos == std::string::npos) + idstring = req.getCommandString().substr(pos); + else + idstring = req.getCommandString().substr(pos, lastpos - pos); + + NetworkId id( idstring ); + if( m_findMap.find( sequence ) != m_findMap.end() ) + { + return; + } + + GameServerCSRequestMessage gsreq( req.getAccountId(), + req.getCommandString(), + req.getToolId(), + req.getAccessLevel(), + loginServerId, + req.getUserName(), + req.getCommandName() ); + + // queue up some messages to find the characters. + GenericValueTypeMessage > const msg("CSFindAuthObject", std::make_pair(id, sequence)); + CentralServer::getInstance().sendToAllGameServersExceptDBProcess( msg, true ); + + CentralCSHandler::CSCharacterFindInfo * p_info = new CSCharacterFindInfo( id, CentralServer::getInstance().getNumGameServers(), gsreq, ( type == HandlerEntry::TYPE_CONDITIONAL_CENTRAL ) ); + + m_findMap[ sequence ] = p_info; + sequence++; + } + break; + case HandlerEntry::TYPE_ARBITRARY_GAME_SERVER: + { + GameServerCSRequestMessage gsreq( req.getAccountId(), + req.getCommandString(), + req.getToolId(), + req.getAccessLevel(), + loginServerId, + req.getUserName(), + req.getCommandName() ); + CentralServer::getInstance().sendToRandomGameServer( gsreq ); + } + break; + case HandlerEntry::TYPE_GAME_SERVER: + default: + { + // spam to game servers (except DB) + GameServerCSRequestMessage gsreq( req.getAccountId(), + req.getCommandString(), + req.getToolId(), + req.getAccessLevel(), + loginServerId, + req.getUserName(), + req.getCommandName() ); + CentralServer::getInstance().sendToAllGameServersExceptDBProcess( gsreq, true ); + } + break; + } +} + +CentralCSHandler & CentralCSHandler::getInstance() +{ + NOT_NULL(smp_instance); + return *smp_instance; +} + +CentralCSHandler::~CentralCSHandler() +{ + for( CentralCSHandlerMap::iterator it = m_entries.begin(); + it != m_entries.end(); + ++it ) + { + delete it->second; + } +} + +CS_CMD( login_character ) +{ + unsigned pos = request.getCommandString().find(" "); + std::string id; + std::string account; + + if(pos == std::string::npos) + return; + unsigned pos2 = request.getCommandString().find(" ", pos + 1 ); + id = request.getCommandString().substr(pos, pos2 - pos); + account = request.getCommandString().substr(pos2 + 1); + + // TODO: Find a way to tell if the player is logged into a different + // character on the same account. + + TransferCharacterData data(TransferRequestMoveValidation::TRS_transfer_server); + data.setCharacterId(NetworkId(id)); + data.setSourceStationId(atoi(account.c_str())); + data.setCSToolId(request.getToolId()); + const GenericValueTypeMessage loginCharacter("TransferGetLoginLocationData", data); + CentralServer::getInstance().sendToDBProcess( loginCharacter, true ); +} diff --git a/engine/server/application/CentralServer/src/shared/CentralCSHandler.h b/engine/server/application/CentralServer/src/shared/CentralCSHandler.h new file mode 100644 index 00000000..e2b5fd0b --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CentralCSHandler.h @@ -0,0 +1,128 @@ +// ====================================================================== +// +// CentralCSHandler.h +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== +// routing of CS commands on the Central Server. +// ====================================================================== +#ifndef CENTRALCSHANDLER_H +#define CENTRALCSHANDLER_H + +#include "serverNetworkMessages/GameServerCSRequestMessage.h" + +class CSToolRequest; +class StructureListMessage; + +#define DECLARE_CS_CMD( _name ) void handle_##_name( GameServerCSRequestMessage & message ); + + +class CentralCSHandler +{ +public: + static void install(); + static void remove(); + static CentralCSHandler & getInstance(); + void handle( const CSToolRequest& msg, uint32 loginServerId ); + ~CentralCSHandler(); + + void handleFindObjectResponse( int iIndex, bool bFound ); + void handleStructureListResponse( StructureListMessage& msg ); + + // only need to DECLARE_CS_CMD for commands handled at the CentralServer. + + DECLARE_CS_CMD( list_structures ); + DECLARE_CS_CMD( login_character ); + DECLARE_CS_CMD( warp_player ); + +protected: + static CentralCSHandler * smp_instance; + typedef void( CentralCSHandler::*CentralCSHandlerFunc )( GameServerCSRequestMessage & ); + + class HandlerEntry + { + public: + enum EntryType + { + TYPE_DB = 0, + TYPE_GAME_SERVER, + TYPE_CENTRAL, + TYPE_CONDITIONAL, // use the game server if character is online. Use the DB server otherwise. + TYPE_CONDITIONAL_CENTRAL, // use the game server if character is online. Use the central handler otherwise. + TYPE_ARBITRARY_GAME_SERVER // send to a game server, we don't care which one. This is used + // if all game servers have what we're looking for, so we don't care who gets it. + }; + + + HandlerEntry( const std::string & in_name, CentralCSHandlerFunc in_func, EntryType in_type ) : + name( in_name ), + type( in_type ), + func( in_func ) + { + } + + HandlerEntry( const std::string & in_name, EntryType in_type ) : + name(in_name), + type( in_type ) + { + } + + std::string name; + EntryType type; + CentralCSHandlerFunc func; // will be null unless it's of TYPE_CENTRAL. + + + }; + + class CSCharacterFindInfo + { + public: + CSCharacterFindInfo( NetworkId & id, int numServers, GameServerCSRequestMessage &req, bool bHandleAtCentral ) : + commandLine( req.getCommandString() ), + command( req.getCommandName() ), + iAccessLevel( req.getAccessLevel() ), + user(req.getUserName() ), + iToolId( req.getToolId() ), + iAccount( req.getAccountId() ), + responsesWaiting( numServers ), + iLoginServerId( req.getLoginServerID() ), + bCentral( bHandleAtCentral ) + + { + + } + + std::string commandLine; + std::string command; + + uint32 iAccessLevel; + std::string user; + + uint32 iToolId; + int iAccount; + + + int responsesWaiting; + int iLoginServerId; + bool bCentral; // if offline, should we handle this at the Central Server or the DB? + protected: + + }; + + typedef std::map< int, CSCharacterFindInfo * > CentralCharFindMap; + + CentralCharFindMap m_findMap; + + typedef std::map< std::string, HandlerEntry * > CentralCSHandlerMap; + + CentralCSHandlerMap m_entries; + +private: + CentralCSHandler() : + m_findMap(), + m_entries() + { + }; +}; + +#endif // CENTRALCSHANDLER_H diff --git a/engine/server/application/CentralServer/src/shared/CentralServer.cpp b/engine/server/application/CentralServer/src/shared/CentralServer.cpp new file mode 100644 index 00000000..9cc4068b --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CentralServer.cpp @@ -0,0 +1,4086 @@ +// CentralServer.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "CentralServer.h" + +#include "CentralCSHandler.h" +#include "CentralServerMetricsData.h" +#include "CharacterCreationTracker.h" +#include "ChatServerConnection.h" +#include "ConfigCentralServer.h" +#include "ConnectionServerConnection.h" +#include "ConsoleConnection.h" +#include "ConsoleManager.h" +#include "CustomerServiceConnection.h" +#include "fileInterface/StdioFile.h" +#include "GameServerConnection.h" +#include "LoginServerConnection.h" +#include "PlanetManager.h" +#include "PlanetServerConnection.h" +#include "TaskConnection.h" +#include "UnicodeUtils.h" +#include "UniverseManager.h" +#include "serverKeyShare/KeyShare.h" +#include "serverMetrics/MetricsManager.h" +#include "serverNetworkMessages/AccountFeatureIdResponse.h" +#include "serverNetworkMessages/AddCharacterMessage.h" +#include "serverNetworkMessages/AddObjectIdBlockMessage.h" +#include "serverNetworkMessages/AdjustAccountFeatureIdResponse.h" +#include "serverNetworkMessages/CentralConnectionServerMessages.h" +#include "serverNetworkMessages/CentralGameServerMessages.h" +#include "serverNetworkMessages/CentralPingMessage.h" +#include "serverNetworkMessages/CentralPlanetServerConnect.h" +#include "serverNetworkMessages/CentralTaskMessages.h" +#include "serverNetworkMessages/CharacterListMessage.h" +#include "serverNetworkMessages/ChatServerOnline.h" +#include "serverNetworkMessages/ChunkObjectListMessage.h" +#include "serverNetworkMessages/ClaimRewardsMessage.h" +#include "serverNetworkMessages/ClaimRewardsReplyMessage.h" +#include "serverNetworkMessages/ConnectionServerDown.h" +#include "serverNetworkMessages/CreateNewObjectMessage.h" +#include "serverNetworkMessages/EnumerateServers.h" +#include "serverNetworkMessages/ExchangeListCreditsMessage.h" +#include "serverNetworkMessages/ExcommunicateGameServerMessage.h" +#include "serverNetworkMessages/FailedToLoadObjectMessage.h" +#include "serverNetworkMessages/FeatureIdTransactionResponse.h" +#include "serverNetworkMessages/ForceUnloadObjectMessage.h" +#include "serverNetworkMessages/GameServerForLoginMessage.h" +#include "serverNetworkMessages/GameServerReadyMessage.h" +#include "serverNetworkMessages/GameServerUniverseLoadedMessage.h" +#include "serverNetworkMessages/GameTaskManagerMessages.h" +#include "serverNetworkMessages/LoadObjectMessage.h" +#include "serverNetworkMessages/LocateStructureMessage.h" +#include "serverNetworkMessages/LoginConnectionServerAddress.h" +#include "serverNetworkMessages/LoginCreateCharacterAckMessage.h" +#include "serverNetworkMessages/LoginCreateCharacterMessage.h" +#include "serverNetworkMessages/LoginKeyPush.h" +#include "serverNetworkMessages/LoginRestoreCharacterMessage.h" +#include "serverNetworkMessages/LoginUpgradeAccountMessage.h" +#include "serverNetworkMessages/MessageToAckMessage.h" +#include "serverNetworkMessages/MessageToMessage.h" +#include "serverNetworkMessages/PlanetLoadCharacterMessage.h" +#include "serverNetworkMessages/PopulationListMessage.h" +#include "serverNetworkMessages/PreloadFinishedMessage.h" +#include "serverNetworkMessages/PreloadRequestCompleteMessage.h" +#include "serverNetworkMessages/ProfilerOperationMessage.h" +#include "serverNetworkMessages/RandomName.h" +#include "serverNetworkMessages/ReleaseAuthoritativeMessage.h" +#include "serverNetworkMessages/RenameCharacterMessage.h" +#include "serverNetworkMessages/RequestChunkMessage.h" +#include "serverNetworkMessages/RequestGameServerForLoginMessage.h" +#include "serverNetworkMessages/RequestObjectIdsMessage.h" +#include "serverNetworkMessages/RequestObjectMessage.h" +#include "serverNetworkMessages/RestartServerMessage.h" +#include "serverNetworkMessages/SceneTransferMessages.h" +#include "serverNetworkMessages/ServerDeleteCharacterMessage.h" +#include "serverNetworkMessages/SetConnectionServerPublic.h" +#include "serverNetworkMessages/SetObjectPositionMessage.h" +#include "serverNetworkMessages/TaskProcessDiedMessage.h" +#include "serverNetworkMessages/TaskSpawnProcess.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "serverNetworkMessages/TransferCharacterDataArchive.h" +#include "serverNetworkMessages/UnloadObjectMessage.h" +#include "serverNetworkMessages/UpdateLoginConnectionServerStatus.h" +#include "serverNetworkMessages/UpdatePlayerCountMessage.h" +#include "serverNetworkMessages/ValidateAccountMessage.h" +#include "serverNetworkMessages/ValidateAccountReplyMessage.h" +#include "serverNetworkMessages/ValidateCharacterForLoginMessage.h" +#include "serverNetworkMessages/ValidateCharacterForLoginReplyMessage.h" +#include "serverNetworkMessages/VerifyAndLockName.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "serverUtility/ClusterWideDataManagerList.h" +#include "serverUtility/ServerClock.h" +#include "serverUtility/SetupServerUtility.h" +#include "sharedDebug/Profiler.h" +#include "sharedFile/Iff.h" +#include "sharedFoundation/ApplicationVersion.h" +#include "sharedFoundation/CalendarTime.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/FormattedString.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/Timer.h" +#include "sharedLog/Log.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedMathArchive/VectorArchive.h" +#include "sharedNetwork/Connection.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetwork/Service.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedNetworkMessages/NameErrors.h" +#include "sharedNetworkMessages/NetworkStringIds.h" +#include "sharedUtility/SetupSharedUtility.h" +#include "sharedUtility/StartingLocationData.h" +#include "sharedUtility/StartingLocationManager.h" +#include "TransferServerConnection.h" +#include "StationPlayersCollectorConnection.h" +#include "AuctionTransferClient.h" +#include "unicodeArchive/UnicodeArchive.h" +#include + + +namespace CentralServerNamespace +{ + bool gs_connectionServersPublic=false; + bool gs_clusterIsLocked=false; + bool gs_clusterIsSecret=false; + + std::map ms_sceneToHostMap; + + // every connection server started on the cluster will + // have a entry in this vector which contains the node + // on which to start that particular connection server; + // every connection server that is started will be assigned + // a 1-based number, which corresponds to its position + // in this vector; that is, the connection server assigned + // number 1 will be at position 0 in this vector + std::vector s_connectionServerHostList; + + std::pair s_customerServiceServerChatServerServiceAddress; + std::pair s_customerServiceServerGameServerServiceAddress; + Service * s_commodityServerService = 0; + bool s_retryTransferServerConnection = false; + bool s_retryStationPlayersCollectorConnection = false; + + std::map m_purgeAccountToLoginServerMap; + std::map > s_pendingRenameCharacter; +} + +using namespace CentralServerNamespace; + +// ====================================================================== + +CentralServer::CentralObject::CentralObject() : +m_sceneId(), +m_authoritativeProcess(0), +m_proxyProcessList() +{ + +} + +//----------------------------------------------------------------------- + +CentralServer::CentralObject::CentralObject(const CentralServer::SceneId & sceneId, uint32 authProcess) : +m_sceneId(sceneId), +m_authoritativeProcess(authProcess), +m_proxyProcessList() +{ + +} + +//----------------------------------------------------------------------- + +CentralServer::CentralServer() : +Singleton(), +MessageDispatch::Receiver(), +m_connectionServerConnections(), +m_chatServerConnections(), +m_csServerConnections(), +m_gameServers(), +m_accountConnectionMap(), +m_dbProcessServerProcessId(0), +m_done(false), +m_gameService(0), +m_chatService(0), +m_connService(0), +m_csService(0), +m_planetService(0), +m_consoleService(0), +m_transferServerConnection(0), +m_stationPlayersCollectorConnection(0), +m_gameServerConnections(), +m_gameServerConnectionsList(), +m_playerSceneMap(), +m_loginServerConnectionMap(), +m_loginServerKeys(0), +m_loginService(0), +m_pAuctionTransferClient(0), +m_messagesWaitingForPlanetServer(), +m_pendingLoadingObjects(), +m_pendingNewObjects(), +m_nextFreeProcessId(0), +m_taskManager(0), +m_taskService(0), +m_commandLine(), +m_pendingTransfers(), +m_totalPlayerCount(0), +m_totalFreeTrialCount(0), +m_totalEmptySceneCount(0), +m_totalTutorialSceneCount(0), +m_totalFalconSceneCount(0), +m_metricsData(0), +m_pendingPlanetServers(), +m_planetsWaitingForPreload(), +m_planetServers(), +m_nextPlanetWatcherPort(ConfigCentralServer::getFirstPlanetWatcherPort()), +m_databaseBacklogged(false), +m_lastLoadingStateTime(0), +m_timeClusterStarted(time(0)), +m_clusterStartupTime(-1), +m_timeClusterWentIntoLoadingState(time(0)), +m_clusterId(0), +m_serverPings(), +m_shutdownTotalTime(0), +m_shutdownMaxTime(0), +m_shutdownSystemMessage(Unicode::narrowToWide("")), +m_shutdownPhase(0), +m_shutdownHaveDatabaseSaveStart(false), +m_shutdownHaveDatabaseComplete(false), +m_curTime(0), +m_lastTimeSystemTimeMismatchNotification(0), +m_lastTimeSystemTimeMismatchNotificationDescription(), +m_disconnectedTaskManagerList(), +m_populationStatistics(), +m_timePopulationStatisticsRefresh(0), +m_timePopulationStatisticsNextRefresh(0), +m_gcwScoreStatistics(), +m_timeGcwScoreStatisticsRefresh(0), +m_timeGcwScoreStatisticsNextRefresh(0), +m_lastLoginTimeStatistics(), +m_createTimeStatistics(), +m_timeLastLoginTimeStatisticsRefresh(0), +m_timeLastLoginTimeStatisticsNextRefresh(0), +m_numberOfCharacterMatchRequests(0), +m_numberOfCharacterMatchResults(0), +m_timeSpentOnCharacterMatchRequestsMs(0), +m_timeCharacterMatchStatisticsNextRefresh(0) +{ + m_curTime = static_cast(time(0)); + m_loginServerKeys = new KeyServer(20); + + connectToMessage("LoginKeyPush"); + + //Connection Messages + connectToMessage("ClientConnectionClosed"); // from connection server + connectToMessage("ConnectionOpened"); + connectToMessage("RequestClusterShutdown"); + connectToMessage("GameConnectionClosed"); + connectToMessage("CentralGameServerConnect"); + connectToMessage("CentralGameServerDbProcessServerProcessId"); + connectToMessage("LoginConnectionOpened"); + connectToMessage("LoginConnectionClosed"); + connectToMessage("ClusterId"); + connectToMessage("GameServerReadyMessage"); + connectToMessage("GameServerUniverseLoadedMessage"); + connectToMessage("ConnectionServerConnectionClosed"); + connectToMessage("ConnectionServerConnectionOpened"); + connectToMessage("TaskConnectionClosed"); + connectToMessage("TaskConnectionOpened"); + connectToMessage("RandomNameRequest"); // from connection server + connectToMessage("RandomNameResponse"); // from game server + connectToMessage("VerifyAndLockNameRequest"); // from connection server + connectToMessage("VerifyAndLockNameResponse"); // from game server + + //Object Messages + connectToMessage("RequestObjectMessage"); + connectToMessage("RequestChunkMessage"); + connectToMessage("ChunkObjectListMessage"); + connectToMessage("CreateNewObjectMessage"); + connectToMessage("SetObjectPositionMessage"); + connectToMessage("FailedToLoadObjectMessage"); + connectToMessage("ReleaseAuthoritativeMessage"); + connectToMessage("ForceUnloadObjectMessage"); + connectToMessage("RequestUnloadObjectMessage"); + connectToMessage("MessageToMessage"); + connectToMessage("MessageToAckMessage"); + connectToMessage("LocateStructureMessage"); + + //Create character messages + connectToMessage("ConnectionCreateCharacter"); + connectToMessage("DatabaseCreateCharacterSuccess"); + connectToMessage("GameCreateCharacterFailed"); + connectToMessage("RequestGameServerForLoginMessage"); + connectToMessage("GameServerForLoginMessage"); + connectToMessage("LoginCreateCharacterAckMessage"); + connectToMessage("LoginUpgradeAccountMessage"); + connectToMessage("LoginRestoreCharacterMessage"); + connectToMessage("NewCharacterCreated"); + + connectToMessage("ServerDeleteCharacterMessage"); + connectToMessage("ValidateCharacterForLoginMessage"); + connectToMessage("ValidateCharacterForLoginReplyMessage"); + connectToMessage("EnableCharacterMessage"); + connectToMessage("EnableCharacterReplyMessage"); + connectToMessage("DisableCharacterMessage"); + connectToMessage("DisableCharacterReplyMessage"); + + connectToMessage("RequestOIDsMessage"); + connectToMessage("AddOIDBlockMessage"); + connectToMessage("CharacterListMessage"); + connectToMessage("LoggedInMessage"); + connectToMessage("CentralPlanetServerConnect"); + connectToMessage("PlanetCreateProxy"); + connectToMessage("PlanetRemoveProxy"); + + connectToMessage("RequestSceneTransfer"); + connectToMessage("SceneTransferMessage"); + connectToMessage("PlanetLoadCharacterMessage"); + + connectToMessage("ConnSrvDropDupeConns"); + connectToMessage("CntrlSrvDropDupeConns"); + + connectToMessage("PlayerDroppedFromGameServerCrash"); + + // Station exchange messages + connectToMessage("ExchangeListCreditsMessage"); + + // Chat Server messages + connectToMessage("ChatServerConnectionOpened"); + connectToMessage("ChatServerConnectionClosed"); + connectToMessage("ChatServerOnline"); + + // Chat Server messages + connectToMessage("CustomerServiceConnectionOpened"); + connectToMessage("CustomerServiceConnectionClosed"); + + connectToMessage("ValidateAccountMessage"); + connectToMessage("ValidateAccountReplyMessage"); + + connectToMessage("RequestPreloadListMessage"); + connectToMessage("PreloadListMessage"); + connectToMessage("PreloadRequestCompleteMessage"); + connectToMessage("PreloadFinishedMessage"); + connectToMessage("DatabaseBackloggedMessage"); + + connectToMessage("UpdatePlayerCountMessage"); + connectToMessage("RenameCharacterMessageEx"); + connectToMessage("PlayerRenameRequestSubmitted"); + connectToMessage("PlayerRenameRequestCompleted"); + connectToMessage("PopulationListMessage"); + + connectToMessage("SetConnectionServerPublic"); + + connectToMessage("ProfilerOperationMessage"); + connectToMessage("CentralPingMessage"); + + connectToMessage("DatabaseSaveStart"); + connectToMessage("DatabaseSaveComplete"); + connectToMessage("ShutdownCluster"); + connectToMessage("AbortShutdown"); + connectToMessage("SetSceneForPlayer"); + connectToMessage("DatabaseConsoleReplyMessage"); + connectToMessage("TaskProcessDiedMessage"); + connectToMessage("SystemTimeMismatchNotification"); + connectToMessage("DisconnectedTaskManagerMessage"); + connectToMessage("TransferServerConnectionClosed"); + connectToMessage("PlanetRequestSave"); + connectToMessage("TransferReplyLoginLocationData"); + connectToMessage("CustomerServiceServerChatServerServiceAddress"); + connectToMessage("CustomerServiceServerGameServerServiceAddress"); + connectToMessage("ChatClosedConnectionWithGameServer"); + + connectToMessage("ReconnectToTransferServer"); + connectToMessage("ClaimRewardsMessage"); + connectToMessage("ClaimRewardsReplyMessage"); + connectToMessage("PurgeStructuresForAccountMessage"); + connectToMessage("WarnStructuresAboutPurgeMessage"); + connectToMessage("PurgeCompleteMessage"); + connectToMessage("RestartServerMessage"); + connectToMessage("RestartServerByRoleMessage"); + connectToMessage("ExcommunicateGameServerMessage"); + connectToMessage("RestartPlanetMessage"); + + // Cluster state + connectToMessage("UpdateClusterLockedAndSecretState"); + + // Population statistics + connectToMessage("PopStatRsp"); + connectToMessage("LLTStatRsp"); + + // GCW score statistics + connectToMessage("GcwScoreStatRsp"); + + // Character Search statistics + connectToMessage("LfgStatRsp"); + + // Account feature Id management + connectToMessage("AdjustAccountFeatureIdResponse"); + connectToMessage("AccountFeatureIdResponse"); + connectToMessage("FeatureIdTransactionResponse"); + + // Unlocked Slot management + connectToMessage("OccupyUnlockedSlotRsp"); + connectToMessage("VacateUnlockedSlotRsp"); + connectToMessage("SwapUnlockedSlotRsp"); + + // Cluster wide data manager + ClusterWideDataManagerList::install(); + ClusterWideDataManagerList::registerMessage(*this); + ClusterWideDataManagerList::setLockTimeoutValue(ConfigCentralServer::getClusterWideDataLockTimeout()); + + CentralCSHandler::install(); + + gs_connectionServersPublic = ConfigCentralServer::getStartPublic(); + + m_metricsData = new CentralServerMetricsData; + MetricsManager::install(m_metricsData, false, "CentralServer", "", 0); + ConsoleManager::install(); + CharacterCreationTracker::install(); + + IGNORE_RETURN(UniverseManager::getInstance()); //make sure it's constructed +} + +//----------------------------------------------------------------------- + +CentralServer::~CentralServer() +{ + ConsoleManager::remove(); + + CentralCSHandler::remove(); + + ms_sceneToHostMap.clear(); + + // released during CentralServer::remove() + m_gameService = 0; + m_chatService = 0; + m_connService = 0; + m_csService = 0; + m_planetService = 0; + m_consoleService = 0; + m_transferServerConnection = 0; + m_stationPlayersCollectorConnection = 0; + m_loginServerKeys = 0; //lint !e423 : leak + m_loginService = 0; + m_taskManager = 0; + m_taskService = 0; + m_metricsData = 0; //lint !e423 : leak +} + +//----------------------------------------------------------------------- +void CentralServer::addGameServer(GameServerConnection * newGameServer) +{ + uint32 pid = newGameServer->getProcessId(); + + LOG("ServerStartup", ("Adding server %lu for scene %s", pid, newGameServer->getSceneId().c_str())); + + IGNORE_RETURN(m_gameServers.insert(SceneGameMap::value_type( + newGameServer->getSceneId(), newGameServer))); + m_gameServerConnections[pid] = newGameServer; + + if (newGameServer->getSceneId() != "database") + { + m_gameServerConnectionsList.push_back(newGameServer); + + if (ConfigCentralServer::getGameServerConnectionPendingAllocatedSizeLimit() != 0) + newGameServer->setTcpClientPendingSendAllocatedSizeLimit(ConfigCentralServer::getGameServerConnectionPendingAllocatedSizeLimit()); + + PlanetManager::addGameServerForScene(newGameServer->getSceneId(), newGameServer); + + // Have the new game server connect to the db and notify it of what game servers exist + std::vector serverList; + + GameServerConnection const * const databaseProcessConnection = CentralServer::getInstance().getGameServer(CentralServer::getInstance().getDbProcessServerProcessId()); + + FATAL(!databaseProcessConnection, ("Tried to add a game server without a database process connection?")); + + for (std::map::iterator i = m_gameServerConnections.begin(); i != m_gameServerConnections.end(); ++i) + { + GameServerConnection const * const g = (*i).second; + if (g != databaseProcessConnection && g->getProcessId() != pid) + serverList.push_back(g->getProcessId()); + } + + GenericValueTypeMessage, std::pair > > > const setupMessage( + "GameServerSetupMessage", + std::make_pair( + serverList, + std::make_pair( + databaseProcessConnection->getProcessId(), + std::make_pair( + databaseProcessConnection->getGameServiceAddress(), + databaseProcessConnection->getGameServicePort())))); + + newGameServer->send(setupMessage, true); + } +} + +//----------------------------------------------------------------------- + +void CentralServer::broadcastToChatServers(const GameNetworkMessage & message) const +{ + for (std::set::const_iterator i = m_chatServerConnections.begin(); i != m_chatServerConnections.end(); ++i) + (*i)->send(message, true); +} + +//----------------------------------------------------------------------- + +void CentralServer::broadcastToCustomerServiceServers(const GameNetworkMessage & message) const +{ + for (std::set::const_iterator i = m_csServerConnections.begin(); i != m_csServerConnections.end(); ++i) + (*i)->send(message, true); +} + +//----------------------------------------------------------------------- + +void CentralServer::broadcastToGameServers(const GameNetworkMessage & message) const +{ + for (SceneGameMap::const_iterator i = m_gameServers.begin(); i != m_gameServers.end(); ++i) + (*i).second->send(message, true); +} + +//----------------------------------------------------------------------- +// /** +// * Clears the object process map for an object. +// * +// * @param objectId id of object we want to clear +// */ +// void CentralServer::clearObjectMap(const NetworkId & objectId) +// { +// IGNORE_RETURN(m_centralObjectMap.erase(objectId)); +// } + +//----------------------------------------------------------------------- + +bool CentralServer::getIsClusterPublic() const +{ + return gs_connectionServersPublic; +} + +//----------------------------------------------------------------------- + +bool CentralServer::getIsClusterLocked() const +{ + return gs_clusterIsLocked; +} + +//----------------------------------------------------------------------- + +bool CentralServer::getIsClusterSecret() const +{ + return gs_clusterIsSecret; +} + +//----------------------------------------------------------------------- + +const std::string& CentralServer::getHostForScene(const std::string& scene) const +{ + static std::string anyString = "any"; + std::map::iterator i = ms_sceneToHostMap.find(scene); + if (i != ms_sceneToHostMap.end()) + { + return i->second; + } + return anyString; +} + +// ---------------------------------------------------------------------- + +/** + * Get the list of game servers that are ready + */ +void CentralServer::getReadyGameServers(std::vector &theList) +{ + std::map::const_iterator i; + for (i = m_gameServerConnections.begin(); i!=m_gameServerConnections.end(); ++i) + { + if ((*i).second->getProcessId()!=getDbProcessServerProcessId() && i->second->getReady()) + theList.push_back(i->second->getProcessId()); + } +} + +//------------------------------------------------------------- + +GameServerConnection * CentralServer::getRandomGameServer(void) +{ + if (m_gameServerConnectionsList.empty()) + return NULL; + + // m_gameServerConnectionsList ***DOES NOT*** contain the DB server so + // we don't have to worry about checking for and excluding the DB server + size_t const listSize = m_gameServerConnectionsList.size(); + size_t const indexChosenGameServer = (::rand() % listSize); + if (m_gameServerConnectionsList[indexChosenGameServer]->getReady()) + return m_gameServerConnectionsList[indexChosenGameServer]; + + // randomly chosen game server is not ready, find next ready game server + size_t indexNextGameServer = (indexChosenGameServer + 1); + if (indexNextGameServer == listSize) + indexNextGameServer = 0; + + while (indexNextGameServer != indexChosenGameServer) + { + if (m_gameServerConnectionsList[indexNextGameServer]->getReady()) + return m_gameServerConnectionsList[indexNextGameServer]; + + ++indexNextGameServer; + if (indexNextGameServer == listSize) + indexNextGameServer = 0; + } + + return NULL; +} + +//----------------------------------------------------------------------- + +/** +* Returns a game server that is handling a scene. +* +* @param scene the scene +* +* @return a game server connection for that scene +*/ +GameServerConnection * CentralServer::getGameServer(const SceneId &scene) const +{ + // @todo: we should pick a gameserver based on load + + CentralServer::ServersList range = getGameServers(scene); + SceneGameMap::const_iterator iter = range.first; + while (iter != range.second) + { + if (iter->second->getReady()) + return iter->second; + ++iter; + } + return 0; +} + +//----------------------------------------------------------------------- + +/** +* Returns the game server for a given process id. +* +* @param processId the process id +* +* @return the game server connection +*/ +GameServerConnection * CentralServer::getGameServer(const uint32 processId) const +{ + GameServerConnection * result = 0; + std::map::const_iterator i = m_gameServerConnections.find(processId); + if(i != m_gameServerConnections.end()) + result = (*i).second; + return result; +} + +//----------------------------------------------------------------------- + +/** +* Returns a list of game servers that are handling a scene. +* +* @param scene the scene +* +* @return an iterator pair for a range of GameServerConnections +*/ +const CentralServer::ServersList CentralServer::getGameServers(const SceneId &scene) const +{ + return m_gameServers.equal_range(scene); //lint !e64 //Type mismatch +} + +//----------------------------------------------------------------------- + +void CentralServer::pushAllKeys(ConnectionServerConnection * targetConnectionServer) const +{ + DEBUG_FATAL(static_cast(m_loginServerKeys->getKeyCount()) < 0, ("Invalid number of keys (uint overflow) in CentralServer.h")); + + for(int i = static_cast(m_loginServerKeys->getKeyCount()) - 1; i >= 0 ; i --) + { + ConnectionKeyPush pk(m_loginServerKeys->getKey(static_cast(i))); + targetConnectionServer->send(pk, true); + } +} + +//----------------------------------------------------------------------- + +void CentralServer::launchStartingProcesses() const +{ + static bool startingProcessesLaunched = false; + if (startingProcessesLaunched) + return; + + // we can only launch starting processes once we have a connection to the + // TaskManager *AND* have received our cluster id from the LoginServer + if (!m_taskManager || !m_taskManager->isConnected() || (m_clusterId == 0)) + { + if (!m_taskManager) + REPORT_LOG(true, ("CentralServer not launching starting processes because m_taskManager is NULL\n")); + else if (!m_taskManager->isConnected()) + REPORT_LOG(true, ("CentralServer not launching starting processes because m_taskManager->isConnected() is false\n")); + + if (m_clusterId == 0) + REPORT_LOG(true, ("CentralServer not launching starting processes because m_clusterId is 0, meaning hasn't received the cluster Id from the LoginServer yet\n")); + + return; + } + + REPORT_LOG(true, ("CentralServer now launching starting processes because has a connection to the TaskManager *AND* has received cluster Id (%u) from the LoginServer\n", m_clusterId)); + + startingProcessesLaunched = true; + + // spawn a connection server + launchStartingConnectionServers(); + + std::string options = "-s dbProcess centralServerAddress="; + if(getGameService()) + { + options += getGameService()->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + + TaskSpawnProcess pd(ConfigCentralServer::getDbServerHost(), "SwgDatabaseServer", options); + m_taskManager->send(pd, true); + + options = "-s ChatServer centralServerAddress="; + if(getChatService()) + { + options += getChatService()->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + options += " clusterName="; + options += ConfigCentralServer::getClusterName(); + TaskSpawnProcess pc(ConfigCentralServer::getChatServerHost(), "ChatServer", options); + m_taskManager->send(pc, true); + + options = "-s CustomerServiceServer centralServerAddress="; + if(getCustomerService()) + { + options += getCustomerService()->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + + options += " clusterName="; + options += ConfigCentralServer::getClusterName(); + TaskSpawnProcess pcs("any", "CustomerServiceServer", options); + m_taskManager->send(pcs, true); +} + +//----------------------------------------------------------------------- + +void CentralServer::launchStartingConnectionServers() const +{ + // if there are several planets listed explicitly in the config file/command line, + // spawn them + + int i = 0; + + // check for nesteds + int const numberOfStartingConnectionServers = ConfigCentralServer::getNumberOfStartingConnectionServers(); + for (i = 0; i < numberOfStartingConnectionServers; ++i) + { + char const * const host = ConfigCentralServer::getStartingConnectionServer(i); + if (host) + { + char const * listenAddress = strchr(host,':'); + DEBUG_FATAL(!listenAddress, ("Could not start up connection server because string %s has no listen address", host)); + std::string hostString(host, static_cast(listenAddress - host)); + ++listenAddress; + + char const * publicPort = strchr(listenAddress,':'); + DEBUG_FATAL(!publicPort, ("Could not start up connection server because string %s has no public port", host)); + std::string listenString(listenAddress, static_cast(publicPort - listenAddress)); + ++publicPort; + + char const * privatePort = strchr(publicPort,':'); + DEBUG_FATAL(!privatePort, ("Could not start up connection server because string %s has no private port", host)); + std::string publicPortString(publicPort, static_cast(privatePort - publicPort)); + ++privatePort; + std::string privatePortString(privatePort); + + DEBUG_REPORT_LOG(true, ("Spawning Connection Server on %s listen:%s public:%s priv:%s\n", hostString.c_str(), listenString.c_str(), publicPortString.c_str(), privatePortString.c_str())); + + // must update s_connectionServerHostList before calling startConnectionServer() + s_connectionServerHostList.push_back(hostString); + startConnectionServer(s_connectionServerHostList.size(), listenString, &publicPortString, &privatePortString, 0); + } + } + + // if there were none specified, use defaults + if(i == 0) + { + // must update s_connectionServerHostList before calling startConnectionServer() + s_connectionServerHostList.push_back("node0"); + startConnectionServer(s_connectionServerHostList.size(), NetworkHandler::getHostName(), 0, 0, 0); + } + +} + +//----------------------------------------------------------------------- + +void CentralServer::launchStartingPlanetServers() +{ + // if there are several planets listed explicitly in the config file/command line, + // spawn them + int i = 0; + int const numberOfStartPlanets = ConfigCentralServer::getNumberOfStartPlanets(); + + for (i = 0; i < numberOfStartPlanets ; ++i) + { + char const * const p = ConfigCentralServer::getStartPlanet(i); + if (p) + { + FATAL(!*p, ("CentralServer::launchStartingPlanetServers: ConfigCentralServer::getStartPlanet(%d) specified a non-null but empty planet name", i)); + + std::string planetName; + std::string hostName; + char const * planet = p; + NOT_NULL(planet); + char const * host = strchr(planet,':'); + + if (host) + { + planetName = std::string(planet, static_cast(host - planet) ); + ++host; + hostName = host; + } + else + { + planetName = planet; + } + + startPlanetServer(hostName, planetName, 0); + ms_sceneToHostMap[planetName] = hostName; + } + } + + // if there were no planets specified, get the configfile default and + // start that planet + if(i == 0) + { + startPlanetServer("any", ConfigCentralServer::getStartPlanet(), 0); + } +} + +//----------------------------------------------------------------------- + +void CentralServer::launchCommoditiesServer() +{ + std::string options; + TaskSpawnProcess csp("any", "CommoditiesServer", options); + CentralServer::getInstance().sendTaskMessage(csp); +} + +//----------------------------------------------------------------------- + +void CentralServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) +{ + if(message.isType("LoginKeyPush")) + { + // receiving another key + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const LoginKeyPush k(ri); + m_loginServerKeys->pushKey(k.getKey()); + DEBUG_REPORT_LOG(true, ("Received session key.\n")); + ConnectionServerConnectionList::iterator i = m_connectionServerConnections.begin(); + for (;i != m_connectionServerConnections.end(); ++i) + { + (*i)->send(k, true); + } + } + else if (message.isType("RequestClusterShutdown")) + { + REPORT_LOG(true, ("An admin requested we shutdown the entire cluster\n")); + m_done = true; + } + else if (message.isType("ClientConnectionClosed")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + + ConnectionServerSUIDMap::iterator i = m_accountConnectionMap.find(msg.getValue()); + if ((i != m_accountConnectionMap.end()) && (i->second == &source)) + { + // Erase the entry + m_accountConnectionMap.erase(i); + } + } + else if(message.isType("ConnectionOpened")) + { + if (!dynamic_cast(&source)) + { + ServerConnection *newServer = const_cast(safe_cast(&source)); + uint32 pid = newServer->getProcessId(); + + CentralGameServerSetProcessId pidMessage(pid, ServerClock::getInstance().getSubtractInterval(), ConfigCentralServer::getClusterName()); + newServer->send(pidMessage, true); + } + } + else if(message.isType("ConnectionServerConnectionClosed")) + { + DEBUG_REPORT_LOG(true,("Handling connection server crash.\n")); + ConnectionServerConnection const *c = safe_cast(&source); + removeFromAccountConnectionMap(c->getId()); + } + else if(message.isType("GameConnectionClosed")) + { + DEBUG_REPORT_LOG(true, ("Game server closed connection\n")); + GameServerConnection const *g = safe_cast(&source); + removeGameServer(g); + } + + else if (message.isType("LoginConnectionOpened")) + { + LoginServerConnection *l = const_cast(safe_cast(&source)); + m_loginServerConnectionMap[l->getProcessId()] = l; + //Send connection server data + ConnectionServerConnectionList::iterator i = m_connectionServerConnections.begin(); + for(; i != m_connectionServerConnections.end(); ++i) + { + const ConnectionServerConnection * const csc = *i; + if ( (csc->getClientServicePortPrivate() != 0) || (csc->getClientServicePortPublic() != 0) ) + { + const LoginConnectionServerAddress csa(csc->getId(), csc->getClientServiceAddress(), csc->getClientServicePortPrivate(), csc->getClientServicePortPublic(), csc->getPlayerCount(), csc->getPingPort ()); + l->send(csa, true); + } + } + + // send preload is finished, if it is + PreloadFinishedMessage msg(isPreloadFinished()); + l->send(msg, true); + + CharacterCreationTracker::getInstance().retryLoginServerCreates(); + } + + else if(message.isType("LoginConnectionClosed")) + { + LoginServerConnection const *l = safe_cast(&source); + LoginServerConnectionMapType::iterator i=m_loginServerConnectionMap.find(l->getProcessId()); + if (i!=m_loginServerConnectionMap.end()) + m_loginServerConnectionMap.erase(i); + + // In development mode, try to reconnect to the login server if we aren't shutting down + if (ConfigCentralServer::getDevelopmentMode() && !m_done) + connectToLoginServer(); + + CharacterCreationTracker::getInstance().onLoginServerDisconnect(l->getProcessId()); + } + + else if(message.isType("ClusterId")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + + if (m_clusterId == 0) + { + FATAL(((msg.getValue() < 1) || (msg.getValue() > 255)),("Cluster Id (%lu) must be between 1 and 255 inclusive", msg.getValue())); + + m_clusterId = static_cast(msg.getValue()); + + // start launching processes + launchStartingProcesses(); + } + } + + else if(message.isType("CentralGameServerConnect")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CentralGameServerConnect c(ri); + + GameServerConnection *g = const_cast(safe_cast(&source)); + + FATAL(ConfigCentralServer::getValidateBuildVersionNumber() && strcmp(ApplicationVersion::getInternalVersion(), c.getBuildVersionNumber().c_str()), + ("Build version number mismatch: central server (%s), remote server %s (%s)", ApplicationVersion::getInternalVersion(), g->getRemoteAddress().c_str(), c.getBuildVersionNumber().c_str()) + ); + + // a game server (or db process) has connected... + addGameServer(g); + + //Send connection server data + ConnectionServerConnectionList::iterator i = m_connectionServerConnections.begin(); + for(; i != m_connectionServerConnections.end(); ++i) + { + if ((*i)->getGameServicePort() != 0) + { + ConnectionServerAddress csa((*i)->getGameServiceAddress(), (*i)->getGameServicePort()); + g->send(csa, true); + } + } + + std::set::const_iterator chatIter; + for(chatIter = m_chatServerConnections.begin(); chatIter != m_chatServerConnections.end(); ++chatIter) + { + if((*chatIter)->getGameServicePort()) + { + ChatServerOnline cso((*chatIter)->getRemoteAddress(), (*chatIter)->getGameServicePort()); + g->send(cso, true); + } + } + + if (g != NULL) + { + //DEBUG_REPORT_LOG(true, ("CentralServer: Sending CustomerServiceServerGameServerServiceAddress to game server (%s:%d) pid(%i)\n", g->getRemoteAddress().c_str(), g->getRemotePort(), g->getProcessId())); + const GenericValueTypeMessage > address("CustomerServiceServerGameServerServiceAddress", std::make_pair(s_customerServiceServerGameServerServiceAddress.first, s_customerServiceServerGameServerServiceAddress.second)); + + g->send(address, true); + } + } + else if (message.isType("ChatClosedConnectionWithGameServer")) + { + GameServerConnection *g = const_cast(safe_cast(&source)); + std::set::const_iterator chatIter; + for(chatIter = m_chatServerConnections.begin(); chatIter != m_chatServerConnections.end(); ++chatIter) + { + if((*chatIter)->getGameServicePort()) + { + ChatServerOnline cso((*chatIter)->getRemoteAddress(), (*chatIter)->getGameServicePort()); + g->send(cso, true); + } + } + } + else if (message.isType("CustomerServiceServerGameServerServiceAddress")) + { + //DEBUG_REPORT_LOG(true, ("CentralServer::receiveMessage(CustomerServiceServerGameServerServiceAddress)\n")); + + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const GenericValueTypeMessage > address(ri); + s_customerServiceServerGameServerServiceAddress.first = address.getValue().first; + s_customerServiceServerGameServerServiceAddress.second = address.getValue().second; + + broadcastToGameServers(address); + } + else if(message.isType("TaskConnectionClosed")) + { + // Net::getInstance().connect(Network::Address("127.0.0.1", ConfigCentralServer::getTaskManagerPort()), TaskConnection()); + } + else if(message.isType("TaskConnectionOpened")) + { + DEBUG_REPORT_LOG(true, ("Task manager connection opened\n")); + } + + else if(message.isType("CentralGameServerDbProcessServerProcessId")) + { + DEBUG_REPORT_LOG(true, ("dbProcess connected\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CentralGameServerDbProcessServerProcessId d(ri); + m_dbProcessServerProcessId = d.getServerProcessId(); + ServerClock::getInstance().setSubtractInterval(d.getSubtractInterval()); + + launchCommoditiesServer(); + launchStartingPlanetServers(); + } + + else if(message.isType("RequestChunkMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RequestChunkMessage t(ri); + + // Forward this message to the dbProcess + sendToGameServer(m_dbProcessServerProcessId, t, true); + } + else if(message.isType("ChunkObjectListMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ChunkObjectListMessage t(ri); + + DEBUG_FATAL(true,("Got ChunkObjectListMessage. Thought it was deprecated.\n")); + // handleChunkList(t.getProcess(), t.getIds()); + } + else if(message.isType("LocateStructureMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LocateStructureMessage t(ri); + sendToPlanetServer(t.getSceneId(), t, true); + } + else if(message.isType("RequestObjectMessage")) + { + DEBUG_FATAL(true,("Got RequestObjectMessage. Thought this went away.")); + + // Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + // RequestObjectMessage t(ri); + // // tell the authoritative object to create a proxy + // const GameServerConnection *gameServer = getGameServer(t.getProcess()); + // NOT_NULL(gameServer); + // uint32 authId = sendToAuthoritativeServer(t.getId(), + // LoadObjectMessage(t.getId(), t.getProcess(), gameServer->getGameServiceAddress(), gameServer->getGameServicePort(), false), + // true); + // // if we sent the message to the database process, mark it as being + // // authoritative for this object + // if (authId == m_dbProcessServerProcessId) + // { + // addObjectToMap(t.getId(), authId, gameServer->getSceneId(), true); + // m_pendingLoadingObjects[t.getId()] = t.getProcess(); + // } + } + else if(message.isType("CreateNewObjectMessage")) + { + DEBUG_FATAL(true,("Ain't this supposed to be deprecated or something?")); + } + else if(message.isType("SetObjectPositionMessage")) + { + //@todo remove this message from the library + DEBUG_FATAL(true,("Got SetObjectPositionMessage. Thought this went away")); + } + else if(message.isType("FailedToLoadObjectMessage")) + { + //@todo remove this message from the library + DEBUG_FATAL(true,("Received Failed To Load Object Message. Thought it was depricated\n")); + } + else if(message.isType("ReleaseAuthoritativeMessage")) + { + //@todo remove this message from the library + DEBUG_FATAL(true, ("Received ReleaseAuthoritative for. Thought it was deprecated.")); + } + else if(message.isType("ForceUnloadObjectMessage")) + { + //N.B. This message can come from a game server or from the planet server. + DEBUG_WARNING(true, ("Received ForceUnloadObject. Need to implement this\n")); + + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ForceUnloadObjectMessage t(ri); + + //@todo: figure out some way to handle this (such as forwarding to PlanetServers), or remove every case where it's sent + // forceUnload(t.getId(),t.getPermaDelete()); + } + //Character Creation Messages + else if(message.isType("ConnectionCreateCharacter")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConnectionCreateCharacter c(ri); + + LOG("TraceCharacterCreation", ("%d received ConnectionCreateCharacter", c.getStationId())); + CharacterCreationTracker::getInstance().handleCreateNewCharacter(c); + } + else if(message.isType("GameCreateCharacterFailed")) + { + DEBUG_REPORT_LOG(true, ("Game server advises central that character creation failed\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GameCreateCharacterFailed f(ri); + CharacterCreationTracker::getInstance().handleGameCreateCharacterFailed(f.getStationId(), f.getName(), f.getErrorMessage(), f.getOptionalDetailedErrorMessage()); + } + else if(message.isType("DatabaseCreateCharacterSuccess")) + { + DEBUG_REPORT_LOG(true, ("Database Process advises central that character creation succeeded\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + DatabaseCreateCharacterSuccess s(ri); + CharacterCreationTracker::getInstance().handleDatabaseCreateCharacterSuccess(s.getStationId(), s.getCharacterName(), s.getObjectId(), s.getTemplateId(), s.getJedi()); + } + else if(message.isType("LoginCreateCharacterAckMessage")) + { + DEBUG_REPORT_LOG(true, ("Login Server advises central that character creation succeeded\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginCreateCharacterAckMessage s(ri); + CharacterCreationTracker::getInstance().handleLoginCreateCharacterAck(s.getStationId()); + } + else if(message.isType("LoginRestoreCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginRestoreCharacterMessage msg(ri); + + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + else if(message.isType("NewCharacterCreated")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const ncc(ri); + + CentralServer::getInstance().sendToAllConnectionServers(ncc, true); + } + else if(message.isType("DatabaseConsoleReplyMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > msg(ri); + + IGNORE_RETURN(sendToRandomGameServer(msg)); + } + else if(message.isType("LoginRestoreCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginRestoreCharacterMessage msg(ri); + + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + else if(message.isType("DatabaseConsoleReplyMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > msg(ri); + + IGNORE_RETURN(sendToRandomGameServer(msg)); + } + else if(message.isType("LoginUpgradeAccountMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginUpgradeAccountMessage msg(ri); + + if (msg.getIsAck()) + { + MessageToMessage const reply( + MessageToPayload(msg.getReplyToObject(), NetworkId::cms_invalid, msg.getReplyMessage(), msg.getPackedMessageData(), 0, false, MessageToPayload::DT_c,NetworkId::cms_invalid,std::string(), 0), + 0); + sendToAllGameServers (reply,true); + } + else + { + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + } + else if (message.isType("RandomNameRequest")) + { + GameServerConnection * gameServer = getRandomGameServer(); + if(gameServer) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RandomNameRequest crnr(ri); + gameServer->send(crnr, true); + } + } + else if (message.isType("RandomNameResponse")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RandomNameResponse crnr(ri); + ConnectionServerConnection * conn = getConnectionServerForAccount(crnr.getStationId()); + if (conn) + { + conn->send(crnr, true); + } + else + { + DEBUG_REPORT_LOG(true,("Could not send name to client because unable to determine which connection server to use.\n")); + } + } + else if (message.isType("VerifyAndLockNameRequest")) + { + GameServerConnection * gameServer = getRandomGameServer(); + if(gameServer) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + VerifyAndLockNameRequest valnr(ri); + gameServer->send(valnr, true); + } + } + else if (message.isType("VerifyAndLockNameResponse")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + VerifyAndLockNameResponse valnr(ri); + ConnectionServerConnection * conn = getConnectionServerForAccount(valnr.getStationId()); + if (conn) + { + conn->send(valnr, true); + } + else + { + DEBUG_REPORT_LOG(true,("Could not send name lock response to client because unable to determine which connection server to use.\n")); + } + } + else if (message.isType("RequestOIDsMessage")) + { + DEBUG_REPORT_LOG(true,("Got RequestOIDsMessage.\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RequestOIDsMessage m(ri); + + if (m.getLogRequest()) + LOG("ObjectIdManager", ("Requesting %lu more object ids for pid %lu", m.getHowMany(), m.getServerId())); + + sendToGameServer(m_dbProcessServerProcessId, m, true); + } + else if (message.isType("AddOIDBlockMessage")) + { + DEBUG_REPORT_LOG(true,("Got AddOIDBlockMessage.\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AddOIDBlockMessage m(ri); + + if (m.getLogRequest()) + LOG("ObjectIdManager", ("Returning object ids (%s - %s) for pid %lu", m.getStart().getValueString().c_str(), m.getEnd().getValueString().c_str(), m.getServerId())); + + sendToGameServer(m.getServerId(), m, true); + } + else if (message.isType("LoggedInMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoggedInMessage m (ri); + DEBUG_REPORT_LOG(true, ("Pending character %lu is logging in or dropping\n", m.getAccountNumber())); + + // Once they're logged in, Central doesn't need to know about them anymore: + removeFromAccountConnectionMap(m.getAccountNumber()); + } + + else if (message.isType("CharacterListMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CharacterListMessage m(ri); + + // Find the client connection and send the character to it. + DEBUG_REPORT_LOG(true,("Got CharacterListMessage for %lu.\n",m.getAccountNumber())); + ConnectionServerConnection *conn = getConnectionServerForAccount(m.getAccountNumber()); + + if (conn) + { + conn->send(m, true); + } + else + { + DEBUG_REPORT_LOG(true,("Warning: received CharacterListMessage for client that is not connected.")); + } + } + else if (message.isType("ValidateCharacterForLoginMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateCharacterForLoginMessage m(ri); + + // ask DBProcess to check whether the character is valid + //pendingCharactersLogin[m.getSuid()] = safe_cast(&source); + if (hasDBConnection()) + sendToDBProcess(m, true); + } + else if (message.isType("ValidateCharacterForLoginReplyMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateCharacterForLoginReplyMessage msg(ri); + + ConnectionServerConnection *conn = getConnectionServerForAccount(msg.getSuid()); + if(conn) + conn->send(msg,true); + else + DEBUG_REPORT_LOG(true,("Trying to handle ValidateCharacterForLoginReplyMessage for account %lu, but could not determine which connection server to use.\n",msg.getSuid())); + } + else if (message.isType("EnableCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::string> > msg(ri); + + LOG("CustomerService", ("EnableCharacter %d, %s request from %s\n", msg.getValue().first.first, msg.getValue().first.second.getValueString().c_str(), msg.getValue().second.c_str())); + // forward this request to LoginServer + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + else if (message.isType("EnableCharacterReplyMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > msg(ri); + GenericValueTypeMessage > reply("DatabaseConsoleReplyMessage", std::make_pair(msg.getValue().first, msg.getValue().second)); + getRandomGameServer()->send(reply, true); + } + else if (message.isType("DisableCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::string> > msg(ri); + + LOG("CustomerService", ("DisableCharacter %d, %s request from %s\n", msg.getValue().first.first, msg.getValue().first.second.getValueString().c_str(), msg.getValue().second.c_str())); + // forward this request to LoginServer + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + else if (message.isType("DisableCharacterReplyMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > msg(ri); + GenericValueTypeMessage > reply("DatabaseConsoleReplyMessage", std::make_pair(msg.getValue().first, msg.getValue().second)); + getRandomGameServer()->send(reply, true); + } + else if(message.isType("TransferReplyLoginLocationData")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage reply(ri); + // If this request has a CS Tool Id associated with it, it is an admin request for the CSTool, + // and so we should send it directly to the connection server, and not depend on a + // transfer server existing. + + if(reply.getValue().getCSToolId() > 0) + { + GenericValueTypeMessage loginMessage("TransferLoginCharacterToSourceServer", reply.getValue()); + ConnectionServerConnection * conn = getAnyConnectionServer(); + if(conn) + { + conn->send(loginMessage, true); + } + return; + } + + LOG("CustomerService", ("CharacterTransfer: Received TransferReplyLoginLocationData from database for character %s\n", reply.getValue().getSourceCharacterName().c_str())); + + if(reply.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(reply); + } + else + { + // send character to ConnectionServer for login to a game server + ConnectionServerConnection * connectionServer = CentralServer::getInstance().getAnyConnectionServer(); + if(connectionServer) + { + const GenericValueTypeMessage login("TransferLoginCharacterToSourceServer", reply.getValue()); + connectionServer->send(login, true); + + LOG("CustomerService", ("CharacterTransfer: Sending TransferLoginCharacterToSourceServer to ConnectionServer : %s", login.getValue().toString().c_str())); + } + } + } + else if (message.isType("CentralPlanetServerConnect")) + { + PlanetServerConnection *g = const_cast(safe_cast(&source)); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CentralPlanetServerConnect msg(ri); + g->setGameServerConnectionData(msg.getConnectionAddress(), msg.getGameServerPort()); + PlanetManager::addServer(msg.getSceneId(), g); + + std::map, time_t> >::iterator f = m_pendingPlanetServers.find(msg.getSceneId()); + if(f != m_pendingPlanetServers.end()) + m_pendingPlanetServers.erase(f); + + IGNORE_RETURN(m_planetServers.insert(std::make_pair(msg.getSceneId(), g))); + + if (isPreloadFinished()) + m_timeClusterWentIntoLoadingState = 0; + else if (m_timeClusterWentIntoLoadingState <= 0) + m_timeClusterWentIntoLoadingState = time(0); + + // handle planet transfers and logins for planet server that aren't up yet + std::vector::iterator t; + for(t = m_messagesWaitingForPlanetServer.begin(); t != m_messagesWaitingForPlanetServer.end();) + { + Archive::ReadIterator tri = t->begin(); + const GameNetworkMessage gnm(tri); + tri = t->begin(); + if(gnm.isType("RequestGameServerForLoginMessage")) + { + const RequestGameServerForLoginMessage loginMessage(tri); + if (loginMessage.getScene() == msg.getSceneId()) + { + t = m_messagesWaitingForPlanetServer.erase(t); + handleRequestGameServerForLoginMessage(loginMessage); + } + } + else if(gnm.isType("RequestSceneTransfer")) + { + const RequestSceneTransfer sceneMessage(tri); + if (sceneMessage.getSceneName() == msg.getSceneId()) + { + t = m_messagesWaitingForPlanetServer.erase(t); + handleRequestSceneTransfer(sceneMessage); + } + } + else + { + t = m_messagesWaitingForPlanetServer.erase(t); + WARNING_STRICT_FATAL(true, ("Unknown message type waiting for planet server")); + } + } + } + else if (message.isType("RequestSceneTransfer")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const RequestSceneTransfer msg (ri); + + handleRequestSceneTransfer(msg); + } + else if (message.isType("SceneTransferMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + SceneTransferMessage msg (ri); + + sendToGameServer(msg.getSourceGameServer(), msg, true); + } + else if (message.isType("GameServerReadyMessage")) + { + GameServerConnection const *g = safe_cast(&source); + UniverseManager::getInstance().onGameServerReady(*g); + } + else if (message.isType("GameServerUniverseLoadedMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const GameServerUniverseLoadedMessage msg(ri); + + // forward to the universe game server as ack that + // the game server who sent this message has received + // its UniverseCompleteMessage from the universe game server + if (msg.getSourceOfUniverseDataProcessId() != getDbProcessServerProcessId()) + sendToGameServer(msg.getSourceOfUniverseDataProcessId(), msg, true); + + CharacterCreationTracker::getInstance().retryGameServerCreates(); + } + else if (message.isType("MessageToMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + MessageToMessage msg(ri); + + WARNING_STRICT_FATAL(true,("CentralServer receieved a messageTo. These should not go to Central anymore. Sender was server %u\n", safe_cast(&source)->getProcessId())); + } + else if (message.isType("MessageToAckMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + MessageToAckMessage msg(ri); + + WARNING_STRICT_FATAL(true,("CentralServer receieved a MessageToAckMessage. These should not go to Central anymore. Sender was server %u\n",safe_cast(&source)->getProcessId())); + } + else if(message.isType("ChatServerConnectionOpened")) + { + // enumerate servers + ChatServerConnection *chatServer = const_cast(safe_cast(&source)); + IGNORE_RETURN(m_chatServerConnections.insert(chatServer)); + const int ct = static_cast(EnumerateServers::CONNECTION_SERVER); + for (ConnectionServerConnectionList::const_iterator ci = m_connectionServerConnections.begin(); ci != m_connectionServerConnections.end(); ++ci) + { + ConnectionServerConnection * c = (*ci); + + if ( (c != NULL) + && !c->getChatServiceAddress().empty() + && (c->getChatServicePort() != 0)) + { + EnumerateServers e(true, c->getChatServiceAddress(), c->getChatServicePort(), ct); + chatServer->send(e, true); + } + else + { + LOG("ChatServer", ("receiveMessage() ChatServerConnectionOpened - Invalid connection address in m_connectionServerConnections, skipping entry")); + } + } + + // Tell the single chat server the address to communicate with the customer service server + + if (!s_customerServiceServerChatServerServiceAddress.first.empty()) + { + //DEBUG_REPORT_LOG(true, ("CentralServer::receiveMessage(ChatServerConnectionOpened)\n")); + + const GenericValueTypeMessage > msg("CustomerServiceServerChatServerServiceAddress", std::make_pair(s_customerServiceServerChatServerServiceAddress.first, s_customerServiceServerChatServerServiceAddress.second)); + + chatServer->send(msg, true); + } + } + else if (message.isType("CustomerServiceServerChatServerServiceAddress")) + { + //DEBUG_REPORT_LOG(true, ("CentralServer::receiveMessage(CustomerServiceServerChatServerServiceAddress)\n")); + + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const GenericValueTypeMessage > address(ri); + + s_customerServiceServerChatServerServiceAddress.first = address.getValue().first; + s_customerServiceServerChatServerServiceAddress.second = address.getValue().second; + + // Tell the chat servers the address to communicate with the customer service server + + std::set::iterator iterChatServerConnections = m_chatServerConnections.begin(); + + for (; iterChatServerConnections != m_chatServerConnections.end(); ++iterChatServerConnections) + { + ChatServerConnection *connection = (*iterChatServerConnections); + + if (connection != NULL) + { + connection->send(address, true); + } + else + { + REPORT_LOG(true, ("Trying to send the customer service server: chat server service address to a NULL chat server\n")); + } + } + } + else if (message.isType("CustomerServiceConnectionOpened")) + { + CustomerServiceConnection *csServer = const_cast(safe_cast(&source)); + IGNORE_RETURN(m_csServerConnections.insert(csServer)); + const int ct = static_cast(EnumerateServers::CONNECTION_SERVER); + for (ConnectionServerConnectionList::const_iterator ci = m_connectionServerConnections.begin(); ci != m_connectionServerConnections.end(); ++ci) + { + ConnectionServerConnection * c = (*ci); + + if ( (c != NULL) + && !c->getCustomerServiceAddress().empty() + && (c->getCustomerServicePort() != 0)) + { + EnumerateServers e(true, c->getCustomerServiceAddress(), c->getCustomerServicePort(), ct); + csServer->send(e, true); + } + else + { + LOG("CustServ", ("receiveMessage() CustomerServiceConnectionOpened - Invalid connection address in m_connectionServerConnections, skipping entry")); + } + } + } + else if(message.isType("ChatServerConnectionClosed")) + { + ChatServerConnection *chatServer = const_cast(safe_cast(&source)); + IGNORE_RETURN(m_chatServerConnections.erase(chatServer)); + + // spawn a new chat server! + std::string options = "-s ChatServer centralServerAddress="; + if(CentralServer::getInstance().getChatService()) + { + options += CentralServer::getInstance().getChatService()->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + + options += " clusterName="; + options += ConfigCentralServer::getClusterName(); + TaskSpawnProcess pc(ConfigCentralServer::getChatServerHost(), "ChatServer", options, ConfigCentralServer::getChatServerRestartDelayTimeSeconds()); + CentralServer::getInstance().sendTaskMessage(pc); + + } + else if (message.isType("CustomerServiceConnectionClosed")) + { + CustomerServiceConnection *csServer = const_cast(safe_cast(&source)); + IGNORE_RETURN(m_csServerConnections.erase(csServer)); + + // spawn a new cs server! + std::string options = "-s CustomerServiceServer centralServerAddress="; + if(CentralServer::getInstance().getCustomerService()) + { + options += CentralServer::getInstance().getCustomerService()->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + + options += " clusterName="; + options += ConfigCentralServer::getClusterName(); + TaskSpawnProcess pc("any", "CustomerServiceServer", options); + CentralServer::getInstance().sendTaskMessage(pc); + } + else if(message.isType("ChatServerOnline")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ChatServerOnline cso (ri); + ChatServerConnection *csc = const_cast(safe_cast(&source)); + csc->setGameServicePort(cso.getPort()); + SceneGameMap::const_iterator iter; + for(iter = m_gameServers.begin(); iter != m_gameServers.end(); ++iter) + { + GameServerConnection * conn = (*iter).second; + conn->send(cso, true); + } + + } + else if (message.isType("RequestGameServerForLoginMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const RequestGameServerForLoginMessage msg(ri); + + time_t const timeNow = ::time(NULL); + PlayerSceneMapType::const_iterator i = m_playerSceneMap.find(msg.getCharacterId()); + if ((i != m_playerSceneMap.end()) && (i->second.second > timeNow)) + { + ServerConnection * c = const_cast(safe_cast(&source)); + GenericValueTypeMessage > const loginDeniedRecentCTS("LoginDeniedRecentCTS", std::make_pair(msg.getCharacterId(), msg.getStationId())); + c->send(loginDeniedRecentCTS, true); + } + else + { + std::map >::const_iterator const iterFind = s_pendingRenameCharacter.find(msg.getCharacterId()); + if ((iterFind != s_pendingRenameCharacter.end()) && (iterFind->second.first > timeNow)) + { + ServerConnection * c = const_cast(safe_cast(&source)); + GenericValueTypeMessage > const loginDeniedPendingPlayerRenameRequest("LoginDeniedPendingPlayerRenameRequest", std::make_pair(msg.getCharacterId(), msg.getStationId())); + c->send(loginDeniedPendingPlayerRenameRequest, true); + } + else + { + handleRequestGameServerForLoginMessage(msg); + } + } + } + else if (message.isType("GameServerForLoginMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GameServerForLoginMessage msg(ri); + + handleGameServerForLoginMessage(msg); + } + + + + else if (message.isType("ExchangeListCreditsMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ExchangeListCreditsMessage msg(ri); + + handleExchangeListCreditsMessage(msg); + } + + + + else if (message.isType("PlanetLoadCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PlanetLoadCharacterMessage msg(ri); + + // let all the game servers know we are about to load a character from the DB + GenericValueTypeMessage > const aboutToLoadCharacterFromDB("AboutToLoadCharacterFromDB", std::make_pair(msg.getCharacterId(), msg.getGameServerId())); + sendToAllGameServersExceptDBProcess(aboutToLoadCharacterFromDB, true); + + sendToDBProcess(msg,true); + } + else if (message.isType("ConnSrvDropDupeConns")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + // A ConnectionServer has received and validated a new connection from the client + + // request that all other ConnectionServers drop any existing connection(s) for the account + std::string galaxyConnectionInfo = "("; + galaxyConnectionInfo += ConfigCentralServer::getClusterName(); + + if (!msg.getValue().second.empty()) + { + galaxyConnectionInfo += ", "; + galaxyConnectionInfo += msg.getValue().second; + } + + galaxyConnectionInfo += ")"; + + GenericValueTypeMessage > const dropDuplicateConnections("CntrlSrvDropDupeConns", std::make_pair(msg.getValue().first, galaxyConnectionInfo)); + sendToAllConnectionServers(dropDuplicateConnections, true, dynamic_cast(&source)); + + // request (via LoginServer) that all ConnectionServers on all other galaxies drop any existing connection(s) for the account + if (ConfigCentralServer::getDisconnectDuplicateConnectionsOnOtherGalaxies()) + IGNORE_RETURN(sendToArbitraryLoginServer(dropDuplicateConnections)); + } + else if (message.isType("CntrlSrvDropDupeConns")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + // request that all ConnectionServers drop any existing connection(s) for the account + sendToAllConnectionServers(msg, true); + } + else if (message.isType("PlayerDroppedFromGameServerCrash")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const m(ri); + + std::set::const_iterator const end = m.getValue().end(); + for (std::set::const_iterator iter = m.getValue().begin(); iter != end; ++iter) + { + IGNORE_RETURN(m_playerSceneMap.erase(*iter)); + LOG("TRACE_LOGIN", ("Forgetting sceneId (because of game server crash) for character (%s) -- will query the database on next login", iter->getValueString().c_str())); + } + } + else if (message.isType("ServerDeleteCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginServerConnection const *l = safe_cast(&source); + ServerDeleteCharacterMessage msg(ri); + msg.setLoginServerId(l->getProcessId()); + + if (hasDBConnection()) + { + LOG("CustomerService", ("Player:deleted character %s for stationId %u", msg.getCharacterId().getValueString().c_str(), msg.getStationId())); + sendToDBProcess(msg,true); + + // let the game servers know that the character is being deleted + GenericValueTypeMessage const msg2("DeleteCharacterNotificationMessage", msg.getCharacterId()); + IGNORE_RETURN(sendToRandomGameServer(msg2)); + } + } + else if (message.isType("UpdatePlayerCountMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UpdatePlayerCountMessage msg(ri); + + ConnectionServerConnection * csc = const_cast(dynamic_cast(&source)); + if (csc) + { + // Update our stored values for the connection server + csc->setPlayerCount(msg.getCount()); + csc->setFreeTrialCount(msg.getFreeTrialCount()); + csc->setEmptySceneCount(msg.getEmptySceneCount()); + csc->setTutorialSceneCount(msg.getTutorialSceneCount()); + csc->setFalconSceneCount(msg.getFalconSceneCount()); + + // Update the login server with the new values + UpdateLoginConnectionServerStatus ulc(csc->getId(), csc->getClientServicePortPublic(), csc->getClientServicePortPrivate(), msg.getCount()); + sendToAllLoginServers(ulc); + + // Update the login servers with new population values + sendPopulationUpdateToLoginServer(); + } + else + { + WARNING_STRICT_FATAL(true,("Got UpdatePlayerCountMessage from something that wasn't a ConnectionServer.\n")); + } + } + else if (message.isType("ValidateAccountMessage")) + { + DEBUG_REPORT_LOG(true,("ValidateAccountMessage\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateAccountMessage msg(ri); + + // Store the connection information for the account + addToAccountConnectionMap(msg.getStationId(), const_cast(dynamic_cast(&source)), msg.getSubscriptionBits()); + + // Pass the validation to a LoginServer + IGNORE_RETURN(sendToArbitraryLoginServer(msg)); + } + else if (message.isType("ValidateAccountReplyMessage")) + { + DEBUG_REPORT_LOG(true,("ValidateAccountReplyMessage\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateAccountReplyMessage msg(ri); + + ConnectionServerConnection *conn=getConnectionServerForAccount(msg.getStationId()); + if (conn) + { + conn->send(msg,true); + } + } + else if (message.isType("PreloadRequestCompleteMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PreloadRequestCompleteMessage msg(ri); + + sendToDBProcess(msg,true); + } + else if (message.isType("ReconnectToTransferServer")) + { + if(ConfigCentralServer::getTransferServerPort()) + { + if(! getInstance().m_transferServerConnection) + { + getInstance().m_transferServerConnection = new TransferServerConnection(ConfigCentralServer::getTransferServerAddress(), ConfigCentralServer::getTransferServerPort()); + s_retryTransferServerConnection = true; + } + } + } + else if (message.isType("ReconnectToStationPlayersCollector")) + { + if(ConfigCentralServer::getStationPlayersCollectorPort()) + { + if(! getInstance().m_stationPlayersCollectorConnection) + { + getInstance().m_stationPlayersCollectorConnection = new StationPlayersCollectorConnection(ConfigCentralServer::getStationPlayersCollectorAddress(), ConfigCentralServer::getStationPlayersCollectorPort()); + s_retryStationPlayersCollectorConnection = true; + } + } + } + else if (message.isType("PreloadFinishedMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PreloadFinishedMessage msg(ri); + + const PlanetServerConnection *conn=dynamic_cast(&source); + WARNING_STRICT_FATAL(!conn,("Programmer bug: got PreloadFinishedMessaage from something that wasn't a PlanetServer.\n")); + if (conn) + { + if (msg.getFinished()) + { + IGNORE_RETURN(m_planetsWaitingForPreload.erase(conn->getSceneId())); + if (isPreloadFinished()) + { + m_timeClusterWentIntoLoadingState = 0; + + DEBUG_REPORT_LOG(true,("Preload finished on all planets.\n")); + + // record how long it took the cluster to come up + if (m_clusterStartupTime == -1) + { + m_clusterStartupTime = static_cast(time(0) - m_timeClusterStarted) / 60; + + // let all the game servers know that the cluster has completed its initial startup + GenericValueTypeMessage clusterStartComplete("ClusterStartComplete", true); + sendToAllGameServersExceptDBProcess(clusterStartComplete, true); + } + else + { + // let all the game servers know that the cluster has recovered from a crash + GenericValueTypeMessage clusterStartComplete("ClusterStartComplete", false); + sendToAllGameServersExceptDBProcess(clusterStartComplete, true); + } + + sendToAllLoginServers(msg); + sendTaskMessage(msg); + m_lastLoadingStateTime=time(0); + // connect to the character transfer server + if(ConfigCentralServer::getTransferServerPort()) + { + if(! getInstance().m_transferServerConnection) + { + getInstance().m_transferServerConnection = new TransferServerConnection(ConfigCentralServer::getTransferServerAddress(), ConfigCentralServer::getTransferServerPort()); + s_retryTransferServerConnection = true; + } + } + + // connect to the station players collector + if(ConfigCentralServer::getStationPlayersCollectorPort()) + { + if(! getInstance().m_stationPlayersCollectorConnection) + { + getInstance().m_stationPlayersCollectorConnection = new StationPlayersCollectorConnection(ConfigCentralServer::getStationPlayersCollectorAddress(), ConfigCentralServer::getStationPlayersCollectorPort()); + s_retryStationPlayersCollectorConnection = true; + } + } + } + else if (m_timeClusterWentIntoLoadingState <= 0) + { + m_timeClusterWentIntoLoadingState = time(0); + } + } + else + { + if(getInstance().m_transferServerConnection != NULL) + { + getInstance().m_transferServerConnection->disconnect(); + getInstance().m_transferServerConnection = 0; + s_retryTransferServerConnection = false; + } + + if(getInstance().m_stationPlayersCollectorConnection != NULL) + { + getInstance().m_stationPlayersCollectorConnection->disconnect(); + getInstance().m_stationPlayersCollectorConnection = 0; + s_retryStationPlayersCollectorConnection = false; + } + + + IGNORE_RETURN(m_planetsWaitingForPreload.insert(conn->getSceneId())); + + if (isPreloadFinished()) + m_timeClusterWentIntoLoadingState = 0; + else if (m_timeClusterWentIntoLoadingState <= 0) + m_timeClusterWentIntoLoadingState = time(0); + + + sendToAllLoginServers(msg); + sendTaskMessage(msg); + } + } + } + else if (message.isType("RenameCharacterMessageEx")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RenameCharacterMessageEx msg(ri); + + IGNORE_RETURN(sendToArbitraryLoginServer(RenameCharacterMessage(msg.getCharacterId(), msg.getNewName(), msg.getRequestedBy()))); + + // if the player requested the rename, also rename the chat avatar, so mail, friends list, and ignore list will migrate + if ((msg.getRenameCharacterMessageSource() == RenameCharacterMessageEx::RCMS_player_request) && !msg.getLastNameChangeOnly() && !ConfigFile::getKeyBool("CharacterRename", "disableRenameChatAvatar", false)) + { + broadcastToChatServers(msg); + } + } + else if (message.isType("PlayerRenameRequestSubmitted")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > > > const msg(ri); + + GenericValueTypeMessage kick("TransferKickConnectedClients", msg.getValue().first); + CentralServer::getInstance().sendToAllLoginServers(kick); + CentralServer::getInstance().sendToAllConnectionServers(kick, true); + + // update the list of pending rename requests, to prevent a character with a pending rename request from logging in + std::map >::iterator const iterFind = s_pendingRenameCharacter.find(msg.getValue().second.first); + if (iterFind != s_pendingRenameCharacter.end()) + { + ++(iterFind->second.second); + iterFind->second.first = ::time(NULL) + 3600; // 1 hour timeout + } + else + { + s_pendingRenameCharacter.insert(std::make_pair(msg.getValue().second.first, std::make_pair((::time(NULL) + 3600), 1))); // 1 hour timeout + } + + // tell the chat server to destroy any avatar with the new name, but only if the first name changed + if (!msg.getValue().second.second.second) + { + GenericValueTypeMessage const chatDestroyAvatar("ChatDestroyAvatar", msg.getValue().second.second.first); + broadcastToChatServers(chatDestroyAvatar); + } + } + else if (message.isType("PlayerRenameRequestCompleted")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + // update the list of pending rename requests, to prevent a character with a pending rename request from logging in + std::map >::iterator const iterFind = s_pendingRenameCharacter.find(msg.getValue().second); + if (iterFind != s_pendingRenameCharacter.end()) + { + if (iterFind->second.second <= 1) + s_pendingRenameCharacter.erase(iterFind); + else + --(iterFind->second.second); + } + } + else if(message.isType("SetConnectionServerPublic")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + SetConnectionServerPublic msg(ri); + if(msg.getIsPublic()) + gs_connectionServersPublic = true; + else + gs_connectionServersPublic = false; + + sendToAllConnectionServers(msg, true); + } + else if(message.isType("ProfilerOperationMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ProfilerOperationMessage msg(ri); + sendToAllGameServers(msg, true); + sendToAllPlanetServers(msg, true); + sendToAllConnectionServers(msg, true); + } + else if (message.isType("PopulationListMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PopulationListMessage msg(ri); + sendToAllGameServers(msg, true); + } + else if (message.isType("CentralPingMessage")) + { + GameServerConnection const *g = safe_cast(&source); + NOT_NULL(g); + LOG("CentralServerPings",("Got reply from %lu",g->getProcessId())); + IGNORE_RETURN(m_serverPings.erase(g->getProcessId())); + } + else if (message.isType("DatabaseBackloggedMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage dbbacklog(ri); + + m_databaseBacklogged = dbbacklog.getValue(); + bool const preloadFinished = isPreloadFinished(); + + if (preloadFinished) + m_timeClusterWentIntoLoadingState = 0; + else if (m_timeClusterWentIntoLoadingState <= 0) + m_timeClusterWentIntoLoadingState = time(0); + + PreloadFinishedMessage msg(preloadFinished); + sendToAllLoginServers(msg); + sendTaskMessage(msg); + } + + else if (message.isType("DatabaseSaveStart")) + { + LOG("CentralServer",("Received DatabaseSaveStart network message.")); + if( m_shutdownPhase == 4 ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Setting indicator for receipt of DatabaseSaveStart.", m_shutdownPhase)); + m_shutdownHaveDatabaseSaveStart = true; + checkShutdownProcess(); + } + else if( m_shutdownPhase == 5 && m_shutdownHaveDatabaseSaveStart) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Setting indicator that final database save cycle is complete.", m_shutdownPhase)); + m_shutdownHaveDatabaseComplete = true; + checkShutdownProcess(); + } + } + else if (message.isType("DatabaseSaveComplete")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + LOG("CentralServer",("Received DatabaseSaveComplete network message.")); + + // tell all the Planet Servers that the save finished + sendToAllPlanetServers(msg,true); + + // don't want to indicate this yet until we are at the beginning of a full cycle + if( m_shutdownPhase == 5 && m_shutdownHaveDatabaseSaveStart) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Setting indicator that final database save cycle is complete.", m_shutdownPhase)); + m_shutdownHaveDatabaseComplete = true; + checkShutdownProcess(); + } + } + else if (message.isType("PlanetRequestSave")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GameNetworkMessage msg(ri); + + sendToDBProcess(msg,true); + } + else if (message.isType("ShutdownCluster")) + { + LOG("CentralServerShutdown",("Received ShutdownCluster network message.")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ShutdownCluster m(ri); + startShutdownProcess(m.getTimeToShutdown(), m.getMaxTime(), m.getSystemMessage()); + } + else if (message.isType("AbortShutdown")) + { + LOG("CentralServerShutdown",("Received AbortShutdown network message.")); + abortShutdownProcess(); + } + + + else if (message.isType("SetSceneForPlayer")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > > ssfp(ri); + + if (ssfp.getValue().second.first.empty()) + { + static const std::string loginTrace("TRACE_LOGIN"); + + IGNORE_RETURN(m_playerSceneMap.erase(ssfp.getValue().first)); + LOG(loginTrace, ("Forgetting sceneId for character (%s) -- will query the database on next login", ssfp.getValue().first.getValueString().c_str())); + } + else + { + PlayerSceneMapType::iterator i = m_playerSceneMap.find(ssfp.getValue().first); + if (i != m_playerSceneMap.end()) + { + i->second.first = ssfp.getValue().second.first; + if (ssfp.getValue().second.second) + i->second.second = ::time(NULL) + static_cast(ConfigCentralServer::getCtsDenyLoginThresholdSeconds()); + } + else + { + m_playerSceneMap[ssfp.getValue().first]=std::make_pair(ssfp.getValue().second.first, (ssfp.getValue().second.second ? (::time(NULL) + static_cast(ConfigCentralServer::getCtsDenyLoginThresholdSeconds())) : 0)); + } + } + } + + else if (message.isType("TaskProcessDiedMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + TaskProcessDiedMessage died(ri); + LOG("TaskProcessDied", ("received TaskProcessDied for %s:%i", died.getProcessName().c_str(), died.getProcessId()));; + if(died.getProcessName().find("SwgGameServer") != std::string::npos) + { + LOG("TaskProcessDied", ("Dead process %i is a game server", died.getProcessId())); + // extract sceneId + size_t pos = died.getProcessName().find("sceneID="); + if(pos != std::string::npos) + { + pos += std::string("sceneID=").length(); + size_t end = died.getProcessName().find_first_of(' ', pos); + if(end != std::string::npos) + { + std::string scene = died.getProcessName().substr(pos, end - pos); + LOG("TaskProcessDied", ("Dead game server process %i was running sceneID %s, advising planet server", died.getProcessId(), scene.c_str())); + std::map::iterator f = m_planetServers.find(scene); + if(f != m_planetServers.end()) + { + f->second->send(died, true); + } + } + } + } + } + else if (message.isType("SystemTimeMismatchNotification")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + + m_lastTimeSystemTimeMismatchNotification = time(0); + m_lastTimeSystemTimeMismatchNotificationDescription = msg.getValue(); + } + else if (message.isType("DisconnectedTaskManagerMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + + m_disconnectedTaskManagerList = msg.getValue(); + } + else if(message.isType("TransferServerConnectionClosed")) + { + // connect to the character transfer server + if(ConfigCentralServer::getTransferServerPort()) + { + if(s_retryTransferServerConnection) + { + getInstance().m_transferServerConnection = new TransferServerConnection(ConfigCentralServer::getTransferServerAddress(), ConfigCentralServer::getTransferServerPort()); + } + } + } + else if(message.isType("StationPlayersCollectorConnectionClosed")) + { + // connect to the station players collector + if(ConfigCentralServer::getStationPlayersCollectorPort()) + { + if(s_retryStationPlayersCollectorConnection) + { + getInstance().m_stationPlayersCollectorConnection = new StationPlayersCollectorConnection(ConfigCentralServer::getStationPlayersCollectorAddress(), ConfigCentralServer::getStationPlayersCollectorPort()); + } + } + } + else if(message.isType("ClaimRewardsMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ClaimRewardsMessage msg(ri); + sendToArbitraryLoginServer(msg); + } + else if(message.isType("ClaimRewardsReplyMessage")) + { + DEBUG_REPORT_LOG(true,("Central got ClaimRewardsReplyMessage\n")); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ClaimRewardsReplyMessage msg(ri); + sendToGameServer(msg.getGameServer(), msg, true); + } + else if (message.isType("PurgeStructuresForAccountMessage") || message.isType("WarnStructuresAboutPurgeMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + LoginServerConnection const * l = dynamic_cast(&source); + if (l) + { + m_purgeAccountToLoginServerMap[msg.getValue()]= l->getProcessId(); // remember which login server is handling this purge + sendToDBProcess(msg, true); + } + } + else if (message.isType("PurgeCompleteMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + + std::map::iterator i=m_purgeAccountToLoginServerMap.find(msg.getValue()); + if (i!=m_purgeAccountToLoginServerMap.end()) + { + sendToLoginServer(i->second,msg); + m_purgeAccountToLoginServerMap.erase(i); + } + } + else if (message.isType("RestartServerMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RestartServerMessage msg(ri); + + sendToPlanetServer(msg.getScene(), msg, true); + } + else if (message.isType("RestartServerByRoleMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > msg(ri); + + sendToPlanetServer(msg.getValue().first, msg, true); + } + else if (message.isType("ExcommunicateGameServerMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ExcommunicateGameServerMessage msg(ri); + + excommunicateServer(msg); + } + else if (message.isType("RestartPlanetMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + + GenericValueTypeMessage const shutdownMsg("ShutdownMessage", 0); + sendToPlanetServer(msg.getValue(),shutdownMsg, true); + } + else if (message.isType("UpdateClusterLockedAndSecretState")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + gs_clusterIsLocked = msg.getValue().first; + gs_clusterIsSecret = msg.getValue().second; + } + else if (message.isType("PopStatRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + m_timePopulationStatisticsRefresh = ::time(NULL); + m_populationStatistics = msg.getValue(); + } + else if (message.isType("GcwScoreStatRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::pair >, std::map > > > > const msg(ri); + + m_timeGcwScoreStatisticsRefresh = ::time(NULL); + std::string const timeGcwScoreStatisticsRefreshStr = CalendarTime::convertEpochToTimeStringLocal(m_timeGcwScoreStatisticsRefresh); + + std::map const & gcwImperialScorePercentile = msg.getValue().first; + std::map > const & gcwImperialScore = msg.getValue().second.first; + std::map > const & gcwRebelScore = msg.getValue().second.second; + std::map >::const_iterator iterFind; + std::map::const_iterator iterFindImperialScorePercentile; + std::pair > >::iterator, bool> iterInsertion; + int imperialScorePercentile; + std::string scoreText, scoreTextDesc; + + for (std::map >::const_iterator iterImp = gcwImperialScore.begin(); iterImp != gcwImperialScore.end(); ++iterImp) + { + iterFindImperialScorePercentile = gcwImperialScorePercentile.find(iterImp->first); + if (iterFindImperialScorePercentile != gcwImperialScorePercentile.end()) + imperialScorePercentile = iterFindImperialScorePercentile->second; + else + imperialScorePercentile = 0; + + iterFind = gcwRebelScore.find(iterImp->first); + if (iterFind != gcwRebelScore.end()) + scoreText = FormattedString<1024>().sprintf("Imp (%s, %s) Reb (%s, %s) - ", NetworkId(iterImp->second.first).getValueString().c_str(), NetworkId(iterImp->second.second).getValueString().c_str(), NetworkId(iterFind->second.first).getValueString().c_str(), NetworkId(iterFind->second.second).getValueString().c_str()); + else + scoreText = FormattedString<1024>().sprintf("Imp (%s, %s) Reb (0, 0) - ", NetworkId(iterImp->second.first).getValueString().c_str(), NetworkId(iterImp->second.second).getValueString().c_str()); + + scoreTextDesc = scoreText + timeGcwScoreStatisticsRefreshStr; + + iterInsertion = m_gcwScoreStatistics.insert(std::make_pair("gcwScore." + iterImp->first, std::make_pair(imperialScorePercentile, std::make_pair(scoreText, scoreTextDesc)))); + if (!iterInsertion.second) + { + if (iterInsertion.first->second.second.first != scoreText) + { + iterInsertion.first->second.first = imperialScorePercentile; + iterInsertion.first->second.second.first = scoreText; + iterInsertion.first->second.second.second = scoreTextDesc; + } + } + } + + for (std::map >::const_iterator iterReb = gcwRebelScore.begin(); iterReb != gcwRebelScore.end(); ++iterReb) + { + iterFind = gcwImperialScore.find(iterReb->first); + if (iterFind == gcwImperialScore.end()) + { + iterFindImperialScorePercentile = gcwImperialScorePercentile.find(iterReb->first); + if (iterFindImperialScorePercentile != gcwImperialScorePercentile.end()) + imperialScorePercentile = iterFindImperialScorePercentile->second; + else + imperialScorePercentile = 0; + + scoreText = FormattedString<1024>().sprintf("Imp (0, 0) Reb (%s, %s) - ", NetworkId(iterReb->second.first).getValueString().c_str(), NetworkId(iterReb->second.second).getValueString().c_str()); + scoreTextDesc = scoreText + timeGcwScoreStatisticsRefreshStr; + + iterInsertion = m_gcwScoreStatistics.insert(std::make_pair("gcwScore." + iterReb->first, std::make_pair(imperialScorePercentile, std::make_pair(scoreText, scoreTextDesc)))); + if (!iterInsertion.second) + { + if (iterInsertion.first->second.second.first != scoreText) + { + iterInsertion.first->second.first = imperialScorePercentile; + iterInsertion.first->second.second.first = scoreText; + iterInsertion.first->second.second.second = scoreTextDesc; + } + } + } + } + } + else if (message.isType("LLTStatRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage >, std::map > > > const msg(ri); + + m_timeLastLoginTimeStatisticsRefresh = ::time(NULL); + m_lastLoginTimeStatistics = msg.getValue().first; + m_createTimeStatistics = msg.getValue().second; + } + else if (message.isType("LfgStatRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > > const msg(ri); + + m_numberOfCharacterMatchRequests += msg.getValue().first; + m_numberOfCharacterMatchResults += msg.getValue().second.first; + m_timeSpentOnCharacterMatchRequestsMs += msg.getValue().second.second; + } + else if (message.isType("OccupyUnlockedSlotRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, uint32> > const occupyUnlockedSlotRsp(ri); + + // CS log the response + LoginUpgradeAccountMessage::OccupyUnlockedSlotResponse const response = static_cast(occupyUnlockedSlotRsp.getValue().first.first); + if (response == LoginUpgradeAccountMessage::OUSR_success) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request SUCCESS", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::OUSR_db_error) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request FAILED - internal db error", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::OUSR_account_has_no_unlocked_slot) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request FAILED - account doesn't have an unlocked slot", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::OUSR_account_has_no_unoccupied_unlocked_slot) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request FAILED - account has no unoccupied unlocked slot", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::OUSR_cluster_already_has_unlocked_slot_character) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request FAILED - cluster already has an unlocked slot character", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else + { + LOG("CustomerService",("JediUnlockedSlot:Player %s OccupyUnlockedSlot request FAILED - unknown result code (%d)", occupyUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), occupyUnlockedSlotRsp.getValue().first.first)); + } + + GameServerConnection * gs = getGameServer(occupyUnlockedSlotRsp.getValue().second); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(occupyUnlockedSlotRsp, true); + } + else if (message.isType("VacateUnlockedSlotRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::pair > > const vacateUnlockedSlotRsp(ri); + + // CS log the response + LoginUpgradeAccountMessage::VacateUnlockedSlotResponse const response = static_cast(vacateUnlockedSlotRsp.getValue().first.first); + if (response == LoginUpgradeAccountMessage::VUSR_success) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request SUCCESS", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + + // to safeguard against any sort of timing exploit to create another normal + // slot character while this one is being converted to normal, thus allowing + // the account to have more normal slot characters on this cluster than is + // allowed, make it look like a normal character has been created on this + // account on this cluster, and that mechanism will prevent such an exploit + + // let all connection servers know that a new character has been created for the station account + GenericValueTypeMessage const ncc("NewCharacterCreated", static_cast(vacateUnlockedSlotRsp.getValue().second.first)); + CentralServer::getInstance().sendToAllConnectionServers(ncc, true); + } + else if (response == LoginUpgradeAccountMessage::VUSR_db_error) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request FAILED - internal db error", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::VUSR_account_has_no_unlocked_slot) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request FAILED - account doesn't have an unlocked slot", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::VUSR_not_unlocked_slot_character) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request FAILED - character is not an unlocked slot character", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::VUSR_no_available_normal_character_slot) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request FAILED - no available normal character slot for the account on this galaxy", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str())); + } + else + { + LOG("CustomerService",("JediUnlockedSlot:Player %s VacateUnlockedSlot request FAILED - unknown result code (%d)", vacateUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), vacateUnlockedSlotRsp.getValue().first.first)); + } + + GameServerConnection * gs = getGameServer(vacateUnlockedSlotRsp.getValue().second.second); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(vacateUnlockedSlotRsp, true); + } + else if (message.isType("SwapUnlockedSlotRsp")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::pair > > > const swapUnlockedSlotRsp(ri); + + // CS log the response + LoginUpgradeAccountMessage::SwapUnlockedSlotResponse const response = static_cast(swapUnlockedSlotRsp.getValue().first.first); + if (response == LoginUpgradeAccountMessage::SUSR_success) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s (%s) request SUCCESS", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.second.c_str())); + } + else if (response == LoginUpgradeAccountMessage::SUSR_db_error) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - internal db error", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::SUSR_account_has_no_unlocked_slot) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - account doesn't have an unlocked slot", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::SUSR_not_unlocked_slot_character) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - source character is not an unlocked slot character", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::SUSR_invalid_target_character) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - target character is either not valid, not on the same account, or not on this galaxy", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str())); + } + else if (response == LoginUpgradeAccountMessage::SUSR_target_character_already_unlocked_slot_character) + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - target character is already an unlocked slot character", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str())); + } + else + { + LOG("CustomerService",("JediUnlockedSlot:Player %s SwapUnlockedSlot with %s request FAILED - unknown result code (%d)", swapUnlockedSlotRsp.getValue().first.second.getValueString().c_str(), swapUnlockedSlotRsp.getValue().second.second.first.getValueString().c_str(), swapUnlockedSlotRsp.getValue().first.first)); + } + + GameServerConnection * gs = getGameServer(swapUnlockedSlotRsp.getValue().second.first); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(swapUnlockedSlotRsp, true); + } + else if (message.isType("AdjustAccountFeatureIdResponse")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AdjustAccountFeatureIdResponse const msg(ri); + + GameServerConnection * gs = getGameServer(msg.getGameServer()); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(msg, true); + } + else if (message.isType("AccountFeatureIdResponse")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AccountFeatureIdResponse const msg(ri); + + GameServerConnection * gs = getGameServer(msg.getGameServer()); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(msg, true); + } + else if (message.isType("FeatureIdTransactionResponse")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + FeatureIdTransactionResponse const msg(ri); + + GameServerConnection * gs = getGameServer(msg.getGameServer()); + if (!gs) + gs = getRandomGameServer(); + + if (gs) + gs->send(msg, true); + } + else if(ClusterWideDataManagerList::handleMessage(source, message)) + { + // nothing else to do with the message since it was + // handled by the Cluster wide data manager + } +} + +//----------------------------------------------------------------------- +void CentralServer::removeConnectionServerConnection(const ConnectionServerConnection * conn) +{ + DEBUG_REPORT_LOG(true, ("Removing connection server connection\n")); + if (conn) + { + startConnectionServer(conn->getConnectionServerNumber(), + conn->getGameServiceAddress(), + conn->getClientServicePortPublic(), + conn->getClientServicePortPrivate(), true, + ConfigCentralServer::getConnectionServerRestartDelayTimeSeconds()); + + ConnectionServerConnectionList::iterator i = m_connectionServerConnections.begin(); + for(;i != m_connectionServerConnections.end();++i) + { + if (conn->getId() == (*i)->getId()) + { + ConnectionServerDown c((*i)->getId()); + sendToAllLoginServers(c); + IGNORE_RETURN(m_connectionServerConnections.erase(i)); + return; + } + + } + + // Clean up all the account info for the connection + removeFromAccountConnectionMap(conn->getId()); + } +} +//----------------------------------------------------------------------- +/** +* Removes all references to a game server from the server. +* +* @param gameServer the game server connection to remove +*/ +void CentralServer::removeGameServer(GameServerConnection const *gameServer) +{ + uint32 const pid = gameServer->getProcessId(); + + LOG("ServerStartup", ("Game Server %lu went down", pid)); + + //@todo this whole function needs a re-write. + NOT_NULL(gameServer); + std::map::iterator const i = m_gameServerConnections.find(pid); + if (i == m_gameServerConnections.end()) + return; + + for (std::vector::iterator ii = m_gameServerConnectionsList.begin(); ii != m_gameServerConnectionsList.end();) + { + if ((*ii) == i->second) + ii = m_gameServerConnectionsList.erase(ii); + else + ++ii; + } + + m_gameServerConnections.erase(i); + + /** @todo: this is slow, find a better way (probably by creating reverse + * lookup table(s)) + */ + if (pid == m_dbProcessServerProcessId) + { + DEBUG_REPORT_LOG(true, ("Database process died -- Central will exit and let the cluster restart\n")); + m_done = true; + return; //lint !e527 Unreachable + } + + DEBUG_WARNING(true, ("Game server %lu crashed", pid)); + + for (SceneGameMap::iterator j = m_gameServers.begin(); j != m_gameServers.end();) + { + if ((*j).second == gameServer) + m_gameServers.erase(j++); + else + ++j; + } + + UniverseManager::getInstance().onGameServerDisconnect(*gameServer); + PlanetManager::onGameServerDisconnect(gameServer); + CharacterCreationTracker::getInstance().onGameServerDisconnect(pid); + ClusterWideDataManagerList::onGameServerDisconnect(pid); + + ExcommunicateGameServerMessage const excommunicateMessage(pid, 0, ""); + sendToAllGameServersExceptDBProcess(excommunicateMessage, true); +} + +//----------------------------------------------------------------------- + +void CentralServer::done() +{ + getInstance().m_done = true; +} + +//----------------------------------------------------------------------- + +void CentralServer::run(void) +{ + SetupSharedLog::install("CentralServer"); + SetupSharedUtility::Data utilityData; + SetupSharedUtility::install (utilityData); + SetupServerUtility::install(); + + gs_connectionServersPublic = ConfigCentralServer::getStartPublic(); + // listen for game server connect requests + static CentralServer & cserver = getInstance(); + + NetworkSetupData setup; + setup.maxConnections = 100; + setup.bindInterface = ConfigCentralServer::getGameServiceBindInterface(); + setup.port = ConfigCentralServer::getGameServicePort(); + Service * gs = new Service(ConnectionAllocator(), setup); + cserver.m_gameService = gs; + + // listen for planet server connection requests + setup.bindInterface = ConfigCentralServer::getPlanetServiceBindInterface(); + setup.port = ConfigCentralServer::getPlanetServicePort(); + Service * ps = new Service(ConnectionAllocator(), setup); + cserver.m_planetService = ps; + + setup.port = ConfigCentralServer::getChatServicePort(); + setup.maxConnections = 32; + setup.bindInterface = ConfigCentralServer::getChatServiceBindInterface(); + Service * cs = new Service(ConnectionAllocator(), setup); + cserver.m_chatService = cs; + + setup.port = ConfigCentralServer::getCustomerServicePort(); + setup.bindInterface = ConfigCentralServer::getCustomerServiceBindInterface(); + Service * css = new Service(ConnectionAllocator(), setup); + cserver.m_csService = css; + + setup.port = ConfigCentralServer::getConnectionServicePort(); + setup.bindInterface = ConfigCentralServer::getConnectionServiceBindInterface(); + Service * cons = new Service(ConnectionAllocator(), setup); + NOT_NULL(cons); + cserver.m_connService = cons; + + setup.port = ConfigCentralServer::getConsoleServicePort(); + setup.bindInterface = ConfigCentralServer::getConsoleServiceBindInterface(); + cserver.m_consoleService = new Service(ConnectionAllocator(), setup); + + setup.port = ConfigCentralServer::getCommodityServerServicePort(); + setup.bindInterface = ConfigCentralServer::getCommodityServerServiceBindInterface(); + s_commodityServerService = new Service(ConnectionAllocator(), setup); + + setup.port = ConfigCentralServer::getLoginServicePort(); + if (ConfigCentralServer::getDevelopmentMode()) + cserver.connectToLoginServer(); + else + { + setup.bindInterface = ConfigCentralServer::getLoginServiceBindInterface(); + cserver.m_loginService = new Service(ConnectionAllocator(), setup); + } + + // connect to the task manager + cserver.m_taskManager = new TaskConnection("127.0.0.1", ConfigCentralServer::getTaskManagerPort()); + + unsigned long startTime = Clock::timeMs(); + unsigned long nextLoadingLogTime=0; + unsigned long nextPingTime=0; + unsigned long nextPopulationLogTime = 0; + + LOG("ServerStartup",("CentralServer starting")); +#ifndef WIN32 + if( FileExists( ".shutdown") ) + { + LOG("CentralServer", ("Removing stale .shutdown file.")); + IGNORE_RETURN(::remove( ".shutdown" )); + } + if( FileExists( ".abortshutdown" ) ) + { + LOG("CentralServer", ("Removing stale .abortshutdown file.")); + IGNORE_RETURN(::remove( ".abortshutdown" )); + } + if( FileExists( ".startanymissingplanet") ) + { + LOG("CentralServer", ("Removing stale .startanymissingplanet file.")); + IGNORE_RETURN(::remove( ".startanymissingplanet" )); + } + if( FileExists( ".startanymissinggameserver") ) + { + LOG("CentralServer", ("Removing stale .startanymissinggameserver file.")); + IGNORE_RETURN(::remove( ".startanymissinggameserver" )); + } +#endif + + while (!cserver.m_done) + { + unsigned long lastFrameTime = 0; + unsigned long frameStartTime = Clock::timeMs(); + + PROFILER_AUTO_BLOCK_DEFINE("main loop"); + + bool barrierReached = true; + + do + { + PROFILER_AUTO_BLOCK_DEFINE("BarrierWait"); + + if (!Os::update()) + cserver.m_done = true; + + { + PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::update"); + NetworkHandler::update(); + } + + { + PROFILER_AUTO_BLOCK_DEFINE("MetricsManager::update"); + unsigned long curTime = Clock::timeMs(); + MetricsManager::update(static_cast(curTime - startTime)); + startTime = curTime; + } + + if (ConfigCentralServer::getShouldSleep()) + { + PROFILER_AUTO_BLOCK_DEFINE("Os::sleep"); + Os::sleep(1); + } + + } while (!barrierReached && !cserver.m_done); + + //@todo Central needs to run a clock so we can schedule re-tries with the login server. + { + PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::dispatch"); + NetworkHandler::dispatch(); + } + + { + PROFILER_AUTO_BLOCK_DEFINE("update"); + cserver.update(); + } + + NetworkHandler::clearBytesThisFrame(); + + { + //Peridically log loading status + unsigned long curTime = Clock::timeMs(); + if (curTime > nextLoadingLogTime) + { + nextLoadingLogTime = curTime + 10000; + std::string planets; + for (std::set::const_iterator i=getInstance().m_planetsWaitingForPreload.begin(); i!=getInstance().m_planetsWaitingForPreload.end(); ++i) + LOG("Preload",("Waiting for planet %s",i->c_str())); + } + + //Perodically ping all the servers + if (ConfigCentralServer::getServerPingTimeout() != 0 && static_cast(curTime-nextPingTime) > 0) + { + nextPingTime = curTime + static_cast(ConfigCentralServer::getServerPingTimeout() * 1000); + getInstance().doServerPings(); + } + + //Periodically write out population to a log every 5 minutes + if (curTime > nextPopulationLogTime) + { + nextPopulationLogTime = curTime + 300000; + LOG("PopulationLog", ("Current Population: %d", getInstance().getPlayerCount())); + } + } + + + + + ServerClock::getInstance().incrementServerFrame(); + if(ConfigCentralServer::getShutdown()) + { + cserver.done(); + } + + unsigned long currentTime = Clock::timeMs(); + lastFrameTime = currentTime - frameStartTime; + if(lastFrameTime > 1000) + { + LOG("profile", ("Long loop (%u ms):\n%s", lastFrameTime, PROFILER_GET_LAST_FRAME_DATA())); + } + } + + LOG("ServerStartup",("CentralServer exiting")); + + SetupSharedLog::remove(); + CentralServer::remove(); +} + +// ---------------------------------------------------------------------- +/** + * Called every frame to do any required updates. + */ +void CentralServer::update() +{ + static int loopCount=0; + m_curTime = static_cast(time(0)); + + // Tell the LoginServers if necessary + if ((++loopCount > ConfigCentralServer::getUpdatePlayerCountFrequency())) + { + loopCount=0; + + // Update the population on the server + sendPopulationUpdateToLoginServer(); + } + + + + if ( ConfigCentralServer::getAuctionEnabled() ) // allow auctions? + { + if ( m_pAuctionTransferClient == NULL ) + { + const char* hostName[1] = { ConfigCentralServer::getAuctionServer() }; + const short port[1] = { (short)ConfigCentralServer::getAuctionPort() }; + + std::string s_id = ConfigCentralServer::getAuctionIDPrefix(); + s_id += ConfigCentralServer::getClusterName(); + + const char *identifier[1]; + identifier[ 0 ] = s_id.c_str(); + + m_pAuctionTransferClient = new AuctionTransferClient( hostName, port, 1, identifier, 1 ); + } + m_pAuctionTransferClient->process(); + } + else if ( m_pAuctionTransferClient ) + { + delete( m_pAuctionTransferClient ); + m_pAuctionTransferClient = 0; + } + + + + // check every 5th frame (one second roughly?) + if( loopCount%5 ) + { + checkShutdownProcess(); + } + + // update cluster wide data manager + ClusterWideDataManagerList::update(Clock::frameTime()); +} + +// ---------------------------------------------------------------------- +void CentralServer::sendPopulationUpdateToLoginServer() +{ + // Add up all the population totals (these are referenced by the metrics data) + m_totalPlayerCount = 0; + m_totalFreeTrialCount = 0; + m_totalEmptySceneCount = 0; + m_totalTutorialSceneCount = 0; + m_totalFalconSceneCount = 0; + + ConnectionServerConnectionList::const_iterator i; + for (i=m_connectionServerConnections.begin(); i!=m_connectionServerConnections.end(); ++i) + { + if (*i) + { + m_totalPlayerCount += (**i).getPlayerCount(); + m_totalFreeTrialCount += (**i).getFreeTrialCount(); + m_totalEmptySceneCount += (**i).getEmptySceneCount(); + m_totalTutorialSceneCount += (**i).getTutorialSceneCount(); + m_totalFalconSceneCount += (**i).getFalconSceneCount(); + } + } + + bool loadedRecently=false; + if (!isPreloadFinished() || (time(0)-m_lastLoadingStateTime < static_cast(ConfigCentralServer::getRecentLoadingStateSeconds()))) + loadedRecently=true; + + UpdatePlayerCountMessage upm(loadedRecently, m_totalPlayerCount, m_totalFreeTrialCount, m_totalEmptySceneCount, m_totalTutorialSceneCount, m_totalFalconSceneCount); + sendToAllLoginServers(upm); +} + +//----------------------------------------------------------------------- + +void CentralServer::sendTaskMessage(const GameNetworkMessage & source) +{ + if(m_taskManager) + m_taskManager->send(source, true); + DEBUG_REPORT_LOG(!m_taskManager, ("There is no task manager connection, but app is attempting to send to one\n")); +} + +//----------------------------------------------------------------------- + +void CentralServer::sendToGameServer(const uint32 gameServerProcessId, const GameNetworkMessage & message, const bool reliable) const +{ + GameServerConnection * g = getGameServer(gameServerProcessId); + if(g) + { + g->send(message, reliable); + } + else + { + DEBUG_WARNING(true,("Attempted to send to game server %i, without connection.\n",gameServerProcessId)); + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToLoginServer(uint32 loginServerId, const GameNetworkMessage &message) +{ + LoginServerConnectionMapType::iterator i=m_loginServerConnectionMap.find(loginServerId); + if (i!=m_loginServerConnectionMap.end() && i->second) + i->second->send(message,true); +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToAllGameServers(const GameNetworkMessage & message, const bool reliable) +{ + for (std::map::const_iterator i = m_gameServerConnections.begin(); i!=m_gameServerConnections.end(); ++i) + { + (*i).second->send(message, reliable); + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToAllGameServersExceptDBProcess(const GameNetworkMessage & message, const bool reliable) +{ + for (std::map::const_iterator i = m_gameServerConnections.begin(); i!=m_gameServerConnections.end(); ++i) + { + if ((*i).first != getDbProcessServerProcessId()) + (*i).second->send(message, reliable); + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToAllPlanetServers(const GameNetworkMessage & message, const bool reliable) +{ + for (std::map::const_iterator i = m_planetServers.begin(); i != m_planetServers.end(); ++i) + (*i).second->send(message, reliable); +} + +// ---------------------------------------------------------------------- + +bool CentralServer::hasPlanetServer(const std::string & sceneName) const +{ + for (std::map::const_iterator i = m_planetServers.begin(); i != m_planetServers.end(); ++i) + if (i->second->getSceneId() == sceneName) + return true; + return false; +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToPlanetServer(const std::string &sceneId, const GameNetworkMessage & message, const bool reliable) +{ + for (std::map::const_iterator i = m_planetServers.begin(); i != m_planetServers.end(); ++i) + if (i->second->getSceneId() == sceneId) + (*i).second->send(message, reliable); +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToAllConnectionServers(const GameNetworkMessage & message, const bool reliable, Connection const * exclude /*= NULL*/) +{ + // send to all connection servers + for (ConnectionServerConnectionList::const_iterator i = m_connectionServerConnections.begin(); i != m_connectionServerConnections.end(); ++i) + { + if ((*i) && (*i != exclude)) + (*i)->send(message, reliable); + } +} + +//----------------------------------------------------------------------- + +void CentralServer::sendToDBProcess(const GameNetworkMessage & message, const bool reliable) const +{ + GameServerConnection * g = getGameServer(getDbProcessServerProcessId()); + if(g) + { + g->send(message, reliable); + } + else + { + DEBUG_FATAL(!m_done,("Attempted to send message to DBProcess without connection (there should always be a connection to DBProcess).")); + } +} + +// ---------------------------------------------------------------------- + +bool CentralServer::hasDBConnection() const +{ + const GameServerConnection * g = getGameServer(getDbProcessServerProcessId()); + return (g != NULL); +} + +//----------------------------------------------------------------------- + +void CentralServer::setTaskManager(TaskConnection * newTaskManager) +{ + if (m_taskManager && newTaskManager != m_taskManager) + { + m_taskManager->setDisconnectReason("CentralServer::setTaskManager called"); + m_taskManager->disconnect(); + } + m_taskManager = newTaskManager; +} + +// ---------------------------------------------------------------------- + +void CentralServer::removePlanetServer(const PlanetServerConnection * p) +{ + for (std::map::iterator i = m_planetServers.begin(); i != m_planetServers.end(); ++i) + { + if ((*i).second == p) + { + DEBUG_REPORT_LOG(true,("Central lost connection to Planet Server %s\n",p->getSceneId().c_str())); + m_planetServers.erase(i); + + if (isPreloadFinished()) + m_timeClusterWentIntoLoadingState = 0; + else if (m_timeClusterWentIntoLoadingState <= 0) + m_timeClusterWentIntoLoadingState = time(0); + + return; + } + } +} + +// ---------------------------------------------------------------------- + +const std::string & CentralServer::getCommandLine() const +{ + return m_commandLine; +} + +//----------------------------------------------------------------------- + +void CentralServer::setCommandLine(const std::string & c) +{ + m_commandLine = c; +} + +//----------------------------------------------------------------------- + +const bool getStartLocation(const std::string & name, std::string & planetName, Vector & coordinates, NetworkId & cellId) +{ + const StartingLocationData * const sld = StartingLocationManager::findLocationByName (name); + if (sld) + { + planetName = sld->planet; + coordinates.x = sld->x; + coordinates.y = sld->y; + coordinates.z = sld->z; + cellId = NetworkId (sld->cellId); + return true; + } + + REPORT_LOG(true, ("The start location \"%s\" could not be found in StartingLocationManager", name.c_str())); + return false; +} + +//----------------------------------------------------------------------- + +void CentralServer::startPlanetServer(const std::string & host, const std::string & sceneId, const SpawnDelaySeconds spawnDelay) +{ + FATAL(sceneId.empty(), ("CentralServer::startPlanetServer: empty sceneId, host='%s'", host.c_str())); + std::map, time_t> >::const_iterator f = m_pendingPlanetServers.find(sceneId); + if(f == m_pendingPlanetServers.end()) + { + std::map::const_iterator pf = m_planetServers.find(sceneId); + if(pf == m_planetServers.end()) + { + std::string options = "-s PlanetServer centralServerAddress="; + if(m_planetService) + { + options += m_planetService->getBindAddress(); + } + else + { + options += NetworkHandler::getHostName(); + } + options += " sceneID="; + options += sceneId; + + char buffer[20]; + IGNORE_RETURN(_itoa(m_nextPlanetWatcherPort++,buffer,10)); + options += " watcherServicePort="; + options += buffer; + + static unsigned int portBase = 0; + IGNORE_RETURN(_itoa(portBase,buffer,10)); + portBase += 100; + options += " gameServerDebuggingPortBase="; + options += buffer; + + TaskSpawnProcess spawn(host.empty() ? std::string("any") : host, "PlanetServer", options, spawnDelay); + CentralServer::getInstance().sendTaskMessage(spawn); + m_pendingPlanetServers[sceneId] = std::make_pair(std::make_pair(host, options), ::time(NULL)); + IGNORE_RETURN(m_planetsWaitingForPreload.insert(sceneId)); + + bool const preloadFinished = isPreloadFinished(); + if (preloadFinished) + m_timeClusterWentIntoLoadingState = 0; + else if (m_timeClusterWentIntoLoadingState <= 0) + m_timeClusterWentIntoLoadingState = time(0); + + if(getInstance().m_transferServerConnection != NULL && !preloadFinished) + { + getInstance().m_transferServerConnection->disconnect(); + getInstance().m_transferServerConnection = 0; + s_retryTransferServerConnection = false; + } + + if(getInstance().m_stationPlayersCollectorConnection != NULL && ! isPreloadFinished()) + { + getInstance().m_stationPlayersCollectorConnection->disconnect(); + getInstance().m_stationPlayersCollectorConnection = 0; + s_retryStationPlayersCollectorConnection = false; + } + + PreloadFinishedMessage msg(preloadFinished); + sendToAllLoginServers(msg); + } + } +} + +//----------------------------------------------------------------------- +/** +* Forward the RequestGameServerForLoginMessage to the appropriate PlanetServer +*/ +void CentralServer::handleRequestGameServerForLoginMessage(const RequestGameServerForLoginMessage & msg) +{ + static const std::string loginTrace("TRACE_LOGIN"); + + std::string effectiveScene; + PlayerSceneMapType::iterator i=m_playerSceneMap.find(msg.getCharacterId()); + if (i!=m_playerSceneMap.end()) + { + effectiveScene=i->second.first; + LOG(loginTrace, ("using sceneId (%s) from memory for character (%s)", effectiveScene.c_str(), msg.getCharacterId().getValueString().c_str())); + } + else + effectiveScene=msg.getScene(); // only use the DB scene if we don't have more recent information + + // for CTS, the source character must currently be on one of the 10 original ground planets + if (msg.getForCtsSourceCharacter()) + { + static std::set s_tenOriginalGroundPlanets; + if (s_tenOriginalGroundPlanets.empty()) + { + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("tatooine")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("naboo")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("corellia")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("rori")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("talus")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("yavin4")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("endor")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("lok")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("dantooine")); + IGNORE_RETURN(s_tenOriginalGroundPlanets.insert("dathomir")); + } + + if (s_tenOriginalGroundPlanets.count(effectiveScene) <= 0) + { + // fail CTS because source character is not on one of the 10 original ground planets + LOG("CustomerService", ("CharacterTransfer: RequestGameServerForLoginMessage failed for source character (%s) stationId (%lu) because effective scene for the character (%s) is not one of the 10 original ground planets", msg.getCharacterId().getValueString().c_str(), msg.getStationId(), effectiveScene.c_str())); + + GenericValueTypeMessage > const failureMsg("CtsSrcCharWrongPlanet", std::make_pair(msg.getCharacterId(), msg.getStationId())); + IGNORE_RETURN(ConnectionServerConnection::sendToPseudoClientConnection(msg.getStationId(), failureMsg)); + + return; + } + } + + PlanetServerConnection *conn = PlanetManager::getPlanetServerForScene(effectiveScene); + if (conn) + { + LOG(loginTrace, ("handling RequestGameServerForLoginMessage(%s)", msg.getCharacterId().getValueString().c_str())); + conn->send(msg,true); + } + else + { + bool isPlanetValid = false; + bool allowDynamicStart = ConfigFile::getKeyBool("CentralServer", "startPlanetsDynamically", false); + + std::map::const_iterator f = ms_sceneToHostMap.find(msg.getScene()); + if(f != ms_sceneToHostMap.end()) + { + isPlanetValid = true; + } + + if(isPlanetValid || allowDynamicStart) + { + LOG(loginTrace, ("deferring RequestGameServerForLoginMessage(%s)", msg.getCharacterId().getValueString().c_str())); + DEBUG_REPORT_LOG(true, ("Starting planet server for login")); + startPlanetServer(getHostForScene(msg.getScene()), msg.getScene(), 0); + m_messagesWaitingForPlanetServer.push_back(); + msg.pack(m_messagesWaitingForPlanetServer.back()); + } + else + { + WARNING_STRICT_FATAL(true, ("Central received a request to start a planet (name=\"%s\") that is not in the startPlanet= list in the CentralServer config file.", msg.getScene().c_str())); + } + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::handleRequestSceneTransfer(const RequestSceneTransfer &msg) +{ + PlanetServerConnection *conn = PlanetManager::getPlanetServerForScene(msg.getSceneName()); + if (conn) + { + conn->send(msg,true); + } + else + { + DEBUG_REPORT_LOG(true, ("Starting planet server for login")); + startPlanetServer(getHostForScene(msg.getSceneName()), msg.getSceneName(), 0); + m_messagesWaitingForPlanetServer.push_back(); + msg.pack(m_messagesWaitingForPlanetServer.back()); + } +} + +// ---------------------------------------------------------------------- + +/** +* Forward the GameServerForLoginMessage to the appropriate ConnectionServer +*/ +void CentralServer::handleGameServerForLoginMessage(const GameServerForLoginMessage &msg) +{ + ConnectionServerConnection *conn = getConnectionServerForAccount(msg.getStationId()); + if (conn) + { + conn->send(msg,true); + } + else + { + if(! ConnectionServerConnection::sendToPseudoClientConnection(msg.getStationId(), msg)) + { + LOG("TRACE_LOGIN", ("Trying to log account %i in, but could not determine which connection server to use.",msg.getStationId())); + } + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::handleExchangeListCreditsMessage(const ExchangeListCreditsMessage &msg) +{ + LOG("Exchange", ("Central Server got exchange list credits %d.",msg.getCredits())); + if ( m_pAuctionTransferClient == NULL ) + { + // send failure packet + } + //////////////////////m_pAuctionTransferClient->addCoinToAuction( msg ); +} + + + + + +ConnectionServerConnection * CentralServer::getAnyConnectionServer() +{ + ConnectionServerConnection * result = 0; + if(! m_connectionServerConnections.empty()) + { + result = *(m_connectionServerConnections.begin()); + if(result) + { + int leastPlayers = result->getPlayerCount(); + + std::vector::iterator i; + for(i = m_connectionServerConnections.begin(); i != m_connectionServerConnections.end(); ++i) + { + if((*i)->getPlayerCount() < leastPlayers) + result = *i; + } + } + } + return result; +} + +// ---------------------------------------------------------------------- + +ConnectionServerConnection * CentralServer::getConnectionServerForAccount(StationId suid) +{ + ConnectionServerConnection * result = NULL; + ConnectionServerSUIDMap::iterator i=m_accountConnectionMap.find(suid); + if (i!=m_accountConnectionMap.end()) + { + result = (*i).second; + } + else + { + result = ConnectionServerConnection::getConnectionForAccount(suid); + } + + return result; +} + +// ---------------------------------------------------------------------- + +void CentralServer::addToAccountConnectionMap(StationId suid, ConnectionServerConnection * cconn, uint32 subscriptionBits) +{ + m_accountConnectionMap[suid] = cconn; + + // remove corresponding "pseudo client connection" + ConnectionServerConnection::removeFromAccountConnectionMap(suid); +} + +// ---------------------------------------------------------------------- + +void CentralServer::removeFromAccountConnectionMap(StationId suid) +{ + ConnectionServerSUIDMap::iterator i=m_accountConnectionMap.find(suid); + if (i!=m_accountConnectionMap.end()) + { + // Erase the entry + m_accountConnectionMap.erase(i++); + } +} + +// ---------------------------------------------------------------------- + +void CentralServer::removeFromAccountConnectionMap(int connectionServerConnectionId) +{ + ConnectionServerSUIDMap::iterator i; + for(i = m_accountConnectionMap.begin(); i != m_accountConnectionMap.end();) + { + const ConnectionServerConnection* cconn = (*i).second; + + if(cconn && (cconn->getId() == connectionServerConnectionId)) + { + // Erase the entry + m_accountConnectionMap.erase(i++); + } + else + { + ++i; + } + } + + // We could update the LoginServer population but people + // leaving the server are not as important as people connecting + // and so we will wait for update() to handle things +} + +//-------------------------------------------------------------------------------- + +const Service * CentralServer::getChatService() const +{ + return m_chatService; +} + +//-------------------------------------------------------------------------------- + +const Service * CentralServer::getCustomerService() const +{ + return m_csService; +} + +//-------------------------------------------------------------------------------- + +const Service * CentralServer::getGameService() const +{ + return m_gameService; +} + +//-------------------------------------------------------------------------------- + +void CentralServer::startConnectionServer(int connectionServerNumber, const std::string& listenAddress, uint16 publicPort, uint16 internalPort, bool, const SpawnDelaySeconds spawnDelay) const +{ + char tmp1[32]; + char tmp2[32]; + std::string publicString = _itoa(publicPort, tmp1, 10); + std::string privateString = _itoa(internalPort, tmp2, 10); + startConnectionServer(connectionServerNumber, listenAddress, &publicString, &privateString, spawnDelay); +} + +//-------------------------------------------------------------------------------- + +void CentralServer::startConnectionServer(int connectionServerNumber, const std::string& listenAddress, const std::string * publicPort, const std::string * internalPort, const SpawnDelaySeconds spawnDelay) const +{ + UNREF(listenAddress); //once we add dual nic support, we can use this + if(!m_connService) + { + DEBUG_WARNING(true, ("Could not start connection server because there was no service for it")); + return; + } + + if (!ConfigCentralServer::getAllowZeroConnectionServerPort()) + { + if (!publicPort) + { + WARNING(true, ("Could not start connection server because there were not client ports specified")); + return; + } + if (*publicPort == "0") + { + WARNING(true, ("Could not start connection server because one or more client ports were 0.")); + return; + } + } + + // there should already be an entry in s_connectionServerHostList that + // contains the node on which to start this particular connection server + if ((connectionServerNumber <= 0) || (connectionServerNumber > static_cast(s_connectionServerHostList.size()))) + { + WARNING(true, ("Could not start connection server because connectionServerNumber=%d and s_connectionServerHostList.size()=%d", connectionServerNumber, static_cast(s_connectionServerHostList.size()))); + return; + } + + // spawn a connection server + std::string options = "-s ConnectionServer clusterName="; + options += ConfigCentralServer::getClusterName(); + + if(gs_connectionServersPublic) + options += " startPublicServer=true"; + + options += " centralServerAddress="; + options += m_connService->getBindAddress(); + + char servicePort[32]; + + options += " centralServerPort="; + options += _itoa(m_connService->getBindPort(), servicePort, 10); + + if (publicPort != 0) + { + options += " clientServicePortPublic="; + options += *publicPort; + } + if (internalPort != 0) + { + options += " clientServicePortPrivate="; + options += *internalPort; + } + + options += " connectionServerNumber="; + options += _itoa(connectionServerNumber, servicePort, 10); + + DEBUG_REPORT_LOG(true, ("Spawning Connection server with options %s\n", options.c_str())); + TaskSpawnProcess p(s_connectionServerHostList[connectionServerNumber-1], "ConnectionServer", options, spawnDelay); + CentralServer::getInstance().sendTaskMessage(p); +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToAllLoginServers(const GameNetworkMessage &message) +{ + for (LoginServerConnectionMapType::iterator i=m_loginServerConnectionMap.begin(); i!=m_loginServerConnectionMap.end(); ++i) + i->second->send(message,true); +} + +// ---------------------------------------------------------------------- + +uint32 CentralServer::sendToArbitraryLoginServer(const GameNetworkMessage &message, bool roundRobin /*= true*/) +{ + static unsigned int nextServer = 0; + + if (m_loginServerConnectionMap.empty()) + return 0; + + LoginServerConnectionMapType::const_iterator i = m_loginServerConnectionMap.begin(); + + if (!roundRobin) + { + i->second->send(message,true); + return i->second->getProcessId(); + } + + ++nextServer; + if (nextServer >= m_loginServerConnectionMap.size()) + nextServer = 0; + + std::advance(i, nextServer); + + i->second->send(message,true); + return i->second->getProcessId(); +} + +// ---------------------------------------------------------------------- + +/** + * In development mode, connect to a login server. + */ +void CentralServer::connectToLoginServer() const +{ + IGNORE_RETURN(new LoginServerConnection(ConfigCentralServer::getLoginServerAddress(), ConfigCentralServer::getLoginServerPort())); +} + +//----------------------------------------------------------------------- + +void CentralServer::remove() +{ + CentralServer & cs = getInstance(); + MetricsManager::remove(); + delete cs.m_metricsData; + cs.m_metricsData = 0; + + delete cs.m_loginServerKeys; + + cs.m_messagesWaitingForPlanetServer.clear(); + cs.m_gameServerConnections.clear(); + cs.m_gameServerConnectionsList.clear(); + cs.m_connectionServerConnections.clear(); + + delete cs.m_gameService; + delete cs.m_chatService; + delete cs.m_csService; + delete cs.m_connService; + delete cs.m_planetService; + delete cs.m_loginService; + if(cs.m_taskManager) + { + cs.m_taskManager->setDisconnectReason("CentralServer::remove"); + cs.m_taskManager->disconnect(); + } + delete cs.m_taskService; + delete cs.m_consoleService; +} + +//----------------------------------------------------------------------- + +std::vector CentralServer::getGameServers() const +{ + std::vector result; + std::map::const_iterator i; + for(i = m_gameServerConnections.begin(); i != m_gameServerConnections.end(); ++i) + { + result.push_back((*i).second); + } + return result; +} + +// ---------------------------------------------------------------------- + +void CentralServer::sendToConnectionServerForAccount(StationId account, const GameNetworkMessage & message, const bool reliable) +{ + ConnectionServerConnection *conn = getConnectionServerForAccount(account); + if (conn) + conn->send(message,reliable); +} + +// ---------------------------------------------------------------------- + +uint32 CentralServer::sendToRandomGameServer(const GameNetworkMessage &message) +{ + GameServerConnection *conn = getRandomGameServer(); + if (conn) + { + conn->send(message,true); + return conn->getProcessId(); + } + else + return 0; +} + +// ---------------------------------------------------------------------- + +void CentralServer::doServerPings() +{ + for (std::set::iterator i=m_serverPings.begin(); i!=m_serverPings.end(); ++i) + { + LOG("CentralServerPings",("Dropping server %lu because it hasn't responded to CentralPingMessage",*i)); + GameServerConnection *conn=getGameServer(*i); + if (conn) + { + // tell task manager to kill the offending process (in case it's hung) + ExcommunicateGameServerMessage msg(*i, conn->getOsProcessId(), conn->getRemoteAddress()); + // disconnect, if it's not hung, it should die + conn->setDisconnectReason("CentralServer::doServerPings, failure to respond to CentralPingMessage"); + conn->disconnect(); + sendTaskMessage(msg); + excommunicateServer(msg); + } + else + { + LOG("CentralServerPings",("Didn't have connection to %lu to drop",*i)); + ExcommunicateGameServerMessage const excommunicateMessage(*i, 0, ""); + excommunicateServer(excommunicateMessage); // haven't received a reply (see CentralPingMessage, above) + } + } + m_serverPings.clear(); + + CentralPingMessage ping; + for (std::map::iterator j=m_gameServerConnections.begin(); j!=m_gameServerConnections.end(); ++j) + { + if (j->first != getDbProcessServerProcessId()) + { + LOG("CentralServerPings",("Pinging %lu",j->first)); + IGNORE_RETURN(m_serverPings.insert(j->first)); + j->second->send(ping,true); + } + } +} + +// ---------------------------------------------------------------------- + +/** + * Declare a game server anathema. All other servers will shun this server. + */ +void CentralServer::excommunicateServer(const ExcommunicateGameServerMessage & msg) +{ + sendToAllGameServers(msg,true); + sendToAllPlanetServers(msg,true); + sendToAllConnectionServers(msg,true); +} + +//----------------------------------------------------------------------- +void CentralServer::startShutdownProcess(const uint32 timeToShutdown, const uint32 maxTime, const Unicode::String &systemMessage) +{ + // sanity checking + if ( m_shutdownPhase > 6) + { + WARNING("CentralServerShutdown", ("startShutdownProcess: invalid value in CentralServer::m_shutdownPhase. Current value is %d. Resetting.", m_shutdownPhase)); + m_shutdownPhase = 0; + } + + // server already in the process of shutting down + if ( m_shutdownPhase > 0 ) + { + LOG("CentralServerShutdown", ("startShutdownProcess: Server already in the process of shutting down. Current shutdown phase is %d.", m_shutdownPhase)); + return; + } + + if( timeToShutdown>maxTime ) + { + LOG("CentralServerShutdown", ("startShutdownProcess: time to shutdown is greater than max time.")); + return; + } + m_shutdownPhase = 1; + LOG("CentralServerShutdown",("Shutdown Phase %d: Shutdown sequence starting now.", m_shutdownPhase)); + LOG("CentralServerShutdown",("Shutdown Phase %d: time to shutdown=%dsec, max time to wait=%dsec, broadcast warning message=\"%s\".", m_shutdownPhase, timeToShutdown, maxTime, Unicode::wideToNarrow(systemMessage).c_str())); + // this is the time in the future that we need to start the shutdown process. + m_shutdownTotalTime = m_curTime + timeToShutdown; + m_shutdownMaxTime = m_curTime + maxTime; + m_shutdownSystemMessage = systemMessage; + m_shutdownHaveDatabaseSaveStart = false; + m_shutdownHaveDatabaseComplete = false; + checkShutdownProcess(); +} +//------------------------------------------------------------------------ +void CentralServer::checkShutdownProcess() +{ + static bool warn30 = false; + static bool warn10 = false; + static bool warn0 = false; + static uint32 lastWarn = m_curTime; + static uint32 nextAbortCheck = m_curTime+1; + static uint32 nextShutdownCheck = m_curTime+30; + + if( !m_shutdownPhase ) + { +#ifndef WIN32 + // check if a .shutdown file exists + if( m_curTime > nextShutdownCheck ) + { + nextShutdownCheck = m_curTime + 30; + if( FileExists(".shutdown") ) + { + StdioFile shutdownFile(".shutdown", "r"); + if(shutdownFile.isOpen()) + { + char destBuffer[64] = {"\0"}; + if(shutdownFile.read(destBuffer, sizeof(destBuffer)) > 0) + { + destBuffer[sizeof(destBuffer) - 1] = 0; + int shutdownTime = atoi(destBuffer); + if(shutdownTime > 0) + { + LOG("CentralServerShutdown", ("Detected a .shutdown file. Initiating shutdown sequence.")); + startShutdownProcess(shutdownTime, 7200, Unicode::narrowToWide("The server will be shutting down soon. Please find a safe place to logout.")); + } + } + shutdownFile.close(); + } + IGNORE_RETURN(::remove(".shutdown")); + return; + } + + if( FileExists( ".startanymissingplanet") ) + { + LOG("CentralServer", ("Detected a .startanymissingplanet file. Checking for any planets that are not started, and starting them.")); + + for (std::map::const_iterator iter = ms_sceneToHostMap.begin(); iter != ms_sceneToHostMap.end(); ++iter) + { + if (!hasPlanetServer(iter->first)) + { + std::map, time_t> >::iterator iterPendingPlanetServer = m_pendingPlanetServers.find(iter->first); + if (iterPendingPlanetServer != m_pendingPlanetServers.end()) + { + // if it's been "awhile" since we requested to restart the PlanetServer, + // then assume that something has gone wrong, and try the restart again + time_t const timeNow = ::time(NULL); + + if ((iterPendingPlanetServer->second.second + static_cast(ConfigCentralServer::getMaxTimeToWaitForPlanetServerStartSeconds())) < timeNow) + { + LOG("CentralServer", ("startanymissingplanet:Starting missing planet %s because it has been %s since we requested it to be started, which has exceeded the %s limit.", iter->first.c_str(), CalendarTime::convertSecondsToMS(static_cast(timeNow - iterPendingPlanetServer->second.second)).c_str(), CalendarTime::convertSecondsToMS(static_cast(ConfigCentralServer::getMaxTimeToWaitForPlanetServerStartSeconds())).c_str())); + iterPendingPlanetServer->second.second = timeNow; + TaskSpawnProcess spawn(iterPendingPlanetServer->second.first.first.empty() ? std::string("any") : iterPendingPlanetServer->second.first.first, "PlanetServer", iterPendingPlanetServer->second.first.second); + CentralServer::getInstance().sendTaskMessage(spawn); + } + else + { + LOG("CentralServer", ("startanymissingplanet:It's only been %s since we requested for planet %s to be started, and we must wait %s before we can start it again.", CalendarTime::convertSecondsToMS(static_cast(timeNow - iterPendingPlanetServer->second.second)).c_str(), iter->first.c_str(), CalendarTime::convertSecondsToMS(static_cast(ConfigCentralServer::getMaxTimeToWaitForPlanetServerStartSeconds())).c_str())); + } + } + else + { + LOG("CentralServer", ("startanymissingplanet:Hmmm... planet %s is missing, but also is not in the list of planets we have attempted to start, so we're ***NOT*** going to start it.", iter->first.c_str())); + } + } + } + + IGNORE_RETURN(::remove( ".startanymissingplanet" )); + return; + } + + if( FileExists( ".startanymissinggameserver") ) + { + LOG("CentralServer", ("Detected a .startanymissinggameserver file. Checking for any game servers that are not started, and starting them.")); + + const GenericValueTypeMessage startAnyMissingGameServer("SAMGS", 0); + sendToAllPlanetServers(startAnyMissingGameServer, true); + + IGNORE_RETURN(::remove( ".startanymissinggameserver" )); + return; + } + } +#endif + return; + } + + // should we abort? + if( m_curTime > nextAbortCheck ) + { +#ifndef WIN32 + nextAbortCheck = m_curTime + 1; + if( FileExists(".abortshutdown") ) + { + + IGNORE_RETURN(::remove(".abortshutdown")); + LOG("CentralServerShutdown", ("Shutdown Phase %d: Detected a .abortshutdown file. Aborting shutdown sequence.", m_shutdownPhase)); + abortShutdownProcess(); + return; + } +#endif + } + + // Phase 1 is an immediate broadcast to players for the first shutdown warning + if( m_shutdownPhase == 1 ) + { + char strTimeLeft[1024]; + uint32 timeLeft = m_shutdownTotalTime - m_curTime; + if( timeLeft < 1 ) + { + strTimeLeft[0] = '\0'; + } + else if( timeLeft < 60 ) + { + sprintf(strTimeLeft, " ( %lusec left )", timeLeft); + } + else + { + sprintf(strTimeLeft, " ( %lumin left )", timeLeft/60); + } + + LOG("CentralServerShutdown",("Shutdown Phase %d: Broadcasting first shutdown message to players: \"%s %s\"", m_shutdownPhase, Unicode::wideToNarrow(m_shutdownSystemMessage).c_str(), strTimeLeft)); + ConGenericMessage const msg("game any systemMessage " + Unicode::wideToNarrow(m_shutdownSystemMessage)+strTimeLeft, 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + m_shutdownPhase = 2; + lastWarn = m_curTime; + } + // Phase 2 is broadcasting a system message every 60sec while we wait for time to expire + else if( m_shutdownPhase == 2 ) + { + if( m_curTime >= m_shutdownTotalTime) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Done broadcasting shutdown warning message to players . Advancing shutdown phase.", m_shutdownPhase)); + m_shutdownPhase = 3; + warn30 = false; + warn10 = false; + warn0 = false; + + + } + // broadcast warning message to players every 60sec. + else if( m_curTime >= lastWarn+60 ) + { + char strTimeLeft[1024]; + uint32 timeLeft = m_shutdownTotalTime - m_curTime; + if( timeLeft < 1 ) + { + strTimeLeft[0] = '\0'; + } + else if( timeLeft < 60 ) + { + sprintf(strTimeLeft, " ( %lusec left)", timeLeft); + } + else + { + sprintf(strTimeLeft, " ( %lumin left)", timeLeft/60); + } + + LOG("CentralServerShutdown",("Shutdown Phase %d: Broadcasting shutdown message to players: \"%s %s\"", m_shutdownPhase, Unicode::wideToNarrow(m_shutdownSystemMessage).c_str(), strTimeLeft)); + ConGenericMessage const msg("game any systemMessage " + Unicode::wideToNarrow(m_shutdownSystemMessage)+strTimeLeft, 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + lastWarn = m_curTime; + } + } + // warn the players they are about to be disconnected + else if( m_shutdownPhase == 3 ) + { + if( m_curTime>=m_shutdownTotalTime && !warn30 ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Broadcasting 30sec disconnect warning message to players.", m_shutdownPhase)); + ConGenericMessage const msg("game any systemMessage You will be disconnected in 30sec so the server can perform a final save before shutting down. Please find a safe place to logout now.", 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + warn30 = true; + + } + else if( m_curTime >= (m_shutdownTotalTime+20) && !warn10 ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Broadcasting 10sec disconnect warning message to players.", m_shutdownPhase)); + ConGenericMessage const msg("game any systemMessage You will be disconnected in 10sec so the server can perform a final save before shutting down. Please find a safe place to logout now.", 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + warn10 = true; + } + else if( m_curTime >= (m_shutdownTotalTime+30) && !warn0 ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Broadcasting final disconnect warning message to players.", m_shutdownPhase)); + ConGenericMessage const msg("game any systemMessage You will now be disconnected so the server can perform a final save before shutting down.", 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + warn0 = true; + } + else if( m_curTime >= (m_shutdownTotalTime+35) ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Setting server to private, disconnecting the players and now waiting for next database save cycle to begin.", m_shutdownPhase)); + gs_connectionServersPublic = false; + SetConnectionServerPublic const msg(false); + sendToAllConnectionServers(msg, true); + m_shutdownPhase = 4; + + // send a message to the DB telling it we're shutting down + GenericValueTypeMessage const msg2("ClusterShutdownMessage", true); + sendToDBProcess(msg2, true); + + // send a save start to the DB; must be sent after the above + // "ClusterShutdownMessage" message so the DB will know this + // is the final save before cluster shutdown + GenericValueTypeMessage const msg3("StartSaveMessage", NetworkId::cms_invalid); + sendToDBProcess(msg3, true); + } + } + else if( m_shutdownPhase == 4 ) + { + if( m_shutdownHaveDatabaseSaveStart ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Starting final database save cycle. Advancing shutdown phase.", m_shutdownPhase)); + m_shutdownPhase = 5; + } + } + else if( m_shutdownPhase == 5 ) + { + // we are done. Shut it down. Shut it down now! + if( m_shutdownHaveDatabaseComplete) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Completed final database save cycle. Advancing shutdown phase.", m_shutdownPhase)); + m_shutdownPhase = 6; + LOG("CentralServerShutdown",("Shutdown Phase %d: Instructing TaskManager to shutdown the cluster without restarting.", m_shutdownPhase)); + ConGenericMessage const msg("stop", 0); + sendTaskMessage(msg); + } + } + // maximum amount of time to wait has expired. Shut it down now without waiting for anything else. + else if( m_curTime >= m_shutdownMaxTime ) + { + LOG("CentralServerShutdown",("Shutdown Phase %d: Maximum time has gone by. Forcing a shutdown now.", m_shutdownPhase)); + m_shutdownPhase = 6; + LOG("CentralServerShutdown",("Shutdown Phase %d: Instructing TaskManager to shutdown the cluster without restarting.", m_shutdownPhase)); + ConGenericMessage const msg("stop", 0); + sendTaskMessage(msg); + } +} + +void CentralServer::abortShutdownProcess() +{ + LOG("CentralServerShutdown", ("Shutdown Phase %d: Aborting shutdown sequence.", m_shutdownPhase)); + if( m_shutdownPhase > 0 ) + { + ConGenericMessage const msg("game any systemMessage The server shutdown has been aborted. The server is no longer shutting down.", 0); + IGNORE_RETURN(sendToRandomGameServer(msg)); + } + + // send a message to the DB telling it we're no longer shutting down + GenericValueTypeMessage const msg("ClusterShutdownMessage", false); + sendToDBProcess(msg, true); + + m_shutdownPhase = 0; + m_shutdownTotalTime = 0; + m_shutdownMaxTime = 0; + m_shutdownSystemMessage = Unicode::narrowToWide(""); + m_shutdownHaveDatabaseSaveStart = false; + m_shutdownHaveDatabaseComplete = false; +} + +//----------------------------------------------------------------------- + +void CentralServer::sendToTransferServer(const GameNetworkMessage & msg) const +{ + if(getInstance().m_transferServerConnection) + { + getInstance().m_transferServerConnection->send(msg, true); + } +} + +//----------------------------------------------------------------------- + +//----------------------------------------------------------------------- + +void CentralServer::sendToStationPlayersCollector(const GameNetworkMessage & msg) const +{ + if(getInstance().m_stationPlayersCollectorConnection) + { + getInstance().m_stationPlayersCollectorConnection->send(msg, true); + } +} + +//----------------------------------------------------------------------- + +int CentralServer::getPlanetServersCount() const +{ + return m_planetServers.size(); +} + +//----------------------------------------------------------------------- + +const Service * CentralServer::getCommoditiesService() +{ + return s_commodityServerService; +} + +//----------------------------------------------------------------------- + +int CentralServer::getClusterStartupTime() const +{ + if (m_clusterStartupTime != -1) + return m_clusterStartupTime; + else + // return how long the cluster has been taking to come up + return int((time(0) - m_timeClusterStarted) / 60); +} + +//----------------------------------------------------------------------- + +int CentralServer::getSecondsClusterHasBeenInLoadingState() const +{ + if (m_timeClusterWentIntoLoadingState > 0) + return (time(0) - m_timeClusterWentIntoLoadingState); + else + return 0; +} + +// ---------------------------------------------------------------------- + +const std::map & CentralServer::getPopulationStatistics(time_t & refreshTime) +{ + // periodically request updated statistics from the game server + time_t const timeNow = ::time(NULL); + if (m_timePopulationStatisticsNextRefresh <= timeNow) + { + GameServerConnection * universeGameServerConnection = getGameServer(UniverseManager::getInstance().getUniverseProcess()); + if (universeGameServerConnection) + { + const GenericValueTypeMessage populationStatisticsRequest("PopStatReq", 0); + universeGameServerConnection->send(populationStatisticsRequest, true); + + m_timePopulationStatisticsNextRefresh = timeNow + 60; + } + } + + refreshTime = m_timePopulationStatisticsRefresh; + return m_populationStatistics; +} + +// ---------------------------------------------------------------------- + +const std::map > > & CentralServer::getGcwScoreStatistics(time_t & refreshTime) +{ + // periodically request updated statistics from the game server + time_t const timeNow = ::time(NULL); + if (m_timeGcwScoreStatisticsNextRefresh <= timeNow) + { + GameServerConnection * universeGameServerConnection = getGameServer(UniverseManager::getInstance().getUniverseProcess()); + if (universeGameServerConnection) + { + const GenericValueTypeMessage gcwScoreStatisticsRequest("GcwScoreStatReq", 0); + universeGameServerConnection->send(gcwScoreStatisticsRequest, true); + + m_timeGcwScoreStatisticsNextRefresh = timeNow + 60; + } + } + + refreshTime = m_timeGcwScoreStatisticsRefresh; + return m_gcwScoreStatistics; +} + +// ---------------------------------------------------------------------- + +std::pair > const *, std::map > const *> CentralServer::getLastLoginTimeStatistics(time_t & refreshTime) +{ + // periodically request updated statistics from the game server + time_t const timeNow = ::time(NULL); + if (m_timeLastLoginTimeStatisticsNextRefresh <= timeNow) + { + GameServerConnection * universeGameServerConnection = getGameServer(UniverseManager::getInstance().getUniverseProcess()); + if (universeGameServerConnection) + { + const GenericValueTypeMessage lastLoginTimeStatisticsRequest("LLTStatReq", 0); + universeGameServerConnection->send(lastLoginTimeStatisticsRequest, true); + + m_timeLastLoginTimeStatisticsNextRefresh = timeNow + (15 * 60); + } + } + + refreshTime = m_timeLastLoginTimeStatisticsRefresh; + + return std::make_pair(&m_lastLoginTimeStatistics, &m_createTimeStatistics); +} + +// ---------------------------------------------------------------------- + +void CentralServer::getCharacterMatchStatistics(int & numberOfCharacterMatchRequests, int & numberOfCharacterMatchResultsPerRequest, int & timeSpentPerCharacterMatchRequestMs) +{ + // periodically request updated statistics from the game server + time_t const timeNow = ::time(NULL); + if (m_timeCharacterMatchStatisticsNextRefresh <= timeNow) + { + const GenericValueTypeMessage characterMatchStatisticsRequest("LfgStatReq", 0); + sendToAllGameServersExceptDBProcess(characterMatchStatisticsRequest, true); + + m_timeCharacterMatchStatisticsNextRefresh = timeNow + 60; + } + + // wraparound, reset statistics + if (m_numberOfCharacterMatchRequests < 0) + { + m_numberOfCharacterMatchRequests = 0; + m_numberOfCharacterMatchResults = 0; + m_timeSpentOnCharacterMatchRequestsMs = 0; + } + + numberOfCharacterMatchRequests = m_numberOfCharacterMatchRequests; + numberOfCharacterMatchResultsPerRequest = (m_numberOfCharacterMatchRequests ? static_cast(m_numberOfCharacterMatchResults / m_numberOfCharacterMatchRequests) : 0); + timeSpentPerCharacterMatchRequestMs = (m_numberOfCharacterMatchRequests ? static_cast(m_timeSpentOnCharacterMatchRequestsMs / m_numberOfCharacterMatchRequests) : 0); +} + +// ====================================================================== +//lint -e766 // todo : TRF Fix this diff --git a/engine/server/application/CentralServer/src/shared/CentralServer.h b/engine/server/application/CentralServer/src/shared/CentralServer.h new file mode 100644 index 00000000..04fa237f --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CentralServer.h @@ -0,0 +1,467 @@ +// CentralServer.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _CentralServer_H +#define _CentralServer_H + +//----------------------------------------------------------------------- +#pragma warning(disable : 4100) +#include +#include +#include +#include +#include +#include "Singleton/Singleton.h" +#include "serverKeyShare/KeyServer.h" +#include "sharedFoundation/StationId.h" +#include "sharedFoundation/NetworkId.h" +#include "sharedMessageDispatch/Receiver.h" + +class CentralServerMetricsData; +class ChatServerConnection; +class Connection; +class ConnectionServerConnection; +class ConnectionCreateCharacter; +class CustomerServiceConnection; +class ExcommunicateGameServerMessage; +class GameNetworkMessage; +class GameServerConnection; +class GameServerConnectionHandler; +class GameServerForLoginMessage; +class LoginServerConnection; +class PlanetServerConnection; +class RequestGameServerForLoginMessage; +class RequestSceneTransfer; +class Service; +class TaskConnection; +class TransferServerConnection; +class StationPlayersCollectorConnection; +class AuctionTransferClient; +class ExchangeListCreditsMessage; + +//----------------------------------------------------------------------- + +class CentralServer : public Singleton, public MessageDispatch::Receiver +{ +public: + typedef std::string SceneId; + typedef std::vector ProcessList; + typedef unsigned int SpawnDelaySeconds; + struct CentralObject + { + CentralObject(); + CentralObject(const SceneId & sceneId, uint32 authProcess); + + SceneId m_sceneId; + uint32 m_authoritativeProcess; + ProcessList m_proxyProcessList; + }; + ~CentralServer(); +private: + typedef std::vector ConnectionServerConnectionList; + typedef std::map CentralObjectMap; + typedef std::hash_multimap SceneGameMap; + + typedef std::pair ServersList; + typedef std::hash_map ConnectionServerSUIDMap; + + typedef std::map > PlayerSceneMapType; + +public: + void addConnectionServerConnection(ConnectionServerConnection* conn); + void addGameServer(GameServerConnection * newGameServer); + void broadcastToChatServers(const GameNetworkMessage & message) const; + void broadcastToCustomerServiceServers(const GameNetworkMessage & message) const; + void broadcastToGameServers(const GameNetworkMessage & message) const; + bool getIsClusterPublic() const; + bool getIsClusterLocked() const; + bool getIsClusterSecret() const; + bool isPreloadFinished() const; + bool isInClusterInitialStartup() const; + uint8 getClusterId() const; + int getClusterStartupTime() const; + int getSecondsClusterHasBeenInLoadingState() const; + int getPlanetsWaitingForPreloadCount() const; + int getPlanetServersCount() const; + bool isDatabaseBacklogged() const; + bool hasDBConnection() const; + const Service * getGameService() const; + const Service * getChatService() const; + const Service * getCustomerService() const; + static const Service * getCommoditiesService(); + const Service * getPlanetService() const; + const std::string& getHostForScene(const std::string& scene) const; + int getNumChatServers() const; + int getNumConnectionServers() const; + int getNumDatabaseServers() const; + int getNumGameServers() const; + int getNumPlanetServers() const; + int getPlayerCount() const; + int getFreeTrialCount() const; + int getEmptySceneCount() const; + int getTutorialSceneCount() const; + int getFalconSceneCount() const; + + bool hasPlanetServer(const std::string & sceneName) const; + + void launchStartingProcesses() const; + void launchStartingConnectionServers() const; + void launchStartingPlanetServers(); + void launchCommoditiesServer(); + + void receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); + void removeConnectionServerConnection(const ConnectionServerConnection* conn); + void removeGameServer(const GameServerConnection *gameServer); + void removePlanetServer(const PlanetServerConnection *planetServer); + void pushAllKeys(ConnectionServerConnection * targetConnServer) const; + void sendTaskMessage(const GameNetworkMessage & source); + void sendToGameServer(const uint32 gameServerProcessId, const GameNetworkMessage & message, const bool reliable) const; + void sendToAllGameServers(const GameNetworkMessage & message, const bool reliable); + void sendToAllGameServersExceptDBProcess(const GameNetworkMessage & message, const bool reliable); + void sendToAllPlanetServers(const GameNetworkMessage & message, const bool reliable); + void sendToPlanetServer(const std::string &sceneId, const GameNetworkMessage & message, const bool reliable); + void sendToAllConnectionServers(const GameNetworkMessage & message, const bool reliable, Connection const * exclude = NULL); + void sendToConnectionServerForAccount(StationId account, const GameNetworkMessage & message, const bool reliable); + void sendToDBProcess(const GameNetworkMessage & message, const bool reliable) const; + void sendToLoginServer(uint32 loginServerId, const GameNetworkMessage &message); + void sendToAllLoginServers(const GameNetworkMessage &message); + uint32 sendToArbitraryLoginServer(const GameNetworkMessage &message, bool roundRobin = true); + uint32 sendToRandomGameServer(const GameNetworkMessage &message); + void sendToTransferServer(const GameNetworkMessage & message) const; + void sendToStationPlayersCollector(const GameNetworkMessage & msg) const; + void setTaskManager(TaskConnection * newTaskmanager); + void setDbProcessServerProcessId(const uint32 newDbServerProcessid); + void startConnectionServer(int connectionServerNumber, const std::string& listenAddress, const std::string * publicPort, const std::string * internalPort, SpawnDelaySeconds spawnDelay) const; + void startConnectionServer(int connectionServerNumber, const std::string& listenAddress, uint16 publicPort, uint16 internalPort, bool, SpawnDelaySeconds spawnDelay) const; + void startPlanetServer(const std::string& host, const std::string& sceneId, SpawnDelaySeconds spawnDelay); + void startShutdownProcess(const uint32 timeToShutdown, const uint32 maxTime, const Unicode::String &systemMessage); + void checkShutdownProcess(); + void abortShutdownProcess(); + + GameServerConnection * getRandomGameServer(void); + void getReadyGameServers(std::vector &theList); + const uint32 getDbProcessServerProcessId(void) const; + + const std::string & getCommandLine() const; + void setCommandLine(const std::string & cmdLine); + static void run(void); + static void done(); + static void remove(); + + ConnectionServerConnection * getAnyConnectionServer(); + + GameServerConnection * getGameServer (const uint32 processId) const; + GameServerConnection * getGameServer (const SceneId &scene) const; + const ServersList getGameServers (const SceneId &scene) const; + std::vector getGameServers() const; + + time_t getLastTimeSystemTimeMismatchNotification() const; + const std::string & getLastTimeSystemTimeMismatchNotificationDescription() const; + + const std::string & getDisconnectedTaskManagerList() const; + + const std::map & getPopulationStatistics(time_t & refreshTime); + + const std::map > > & getGcwScoreStatistics(time_t & refreshTime); + + std::pair > const *, std::map > const *> getLastLoginTimeStatistics(time_t & refreshTime); + + void getCharacterMatchStatistics(int & numberOfCharacterMatchRequests, int & numberOfCharacterMatchResultsPerRequest, int & timeSpentPerCharacterMatchRequestMs); + + void removeFromAccountConnectionMap(StationId suid); + +private: + void handleRequestGameServerForLoginMessage (const RequestGameServerForLoginMessage & msg); + void handleRequestSceneTransfer (const RequestSceneTransfer & msg); + void handleGameServerForLoginMessage (const GameServerForLoginMessage & msg); + + + void handleExchangeListCreditsMessage (const ExchangeListCreditsMessage& msg); + + size_t getGameServerCount (void) const; + void update(); + void sendPopulationUpdateToLoginServer(); + ConnectionServerConnection * getConnectionServerForAccount(StationId suid); + void addToAccountConnectionMap(StationId suid, ConnectionServerConnection * cconn, uint32 subscriptionBits); + void removeFromAccountConnectionMap(int connectionServerConnectionId); + void doServerPings(); + void excommunicateServer(const ExcommunicateGameServerMessage &); + +protected: + friend class Singleton; + CentralServer(); + +private: + void connectToLoginServer() const; + + CentralServer(const CentralServer & source); + CentralServer& operator= (const CentralServer & rhs); + + ConnectionServerConnectionList m_connectionServerConnections; + std::set m_chatServerConnections; + std::set m_csServerConnections; + SceneGameMap m_gameServers; + ConnectionServerSUIDMap m_accountConnectionMap; + +// Network::Address clientService; + /** + The dbProcessServerProcessId is set by the DBProcess. The central server + refers to this process if there are no matching objects in any of its maps. + */ + uint32 m_dbProcessServerProcessId; + bool m_done; + Service * m_gameService; + Service * m_chatService; + Service * m_connService; + Service * m_csService; + Service * m_planetService; + Service * m_consoleService; + TransferServerConnection * m_transferServerConnection; + StationPlayersCollectorConnection * m_stationPlayersCollectorConnection; + + // these two lists must be kept in sync, ***EXCEPT*** that + // m_gameServerConnectionsList doesn't contain the DB server + std::map m_gameServerConnections; + std::vector m_gameServerConnectionsList; + + PlayerSceneMapType m_playerSceneMap; + + typedef std::map LoginServerConnectionMapType; + LoginServerConnectionMapType m_loginServerConnectionMap; + + KeyServer * m_loginServerKeys; + Service * m_loginService; + + AuctionTransferClient * m_pAuctionTransferClient; + + std::vector m_messagesWaitingForPlanetServer; + + std::map m_pendingLoadingObjects; + std::map m_pendingNewObjects; + uint32 m_nextFreeProcessId; + TaskConnection * m_taskManager; + Service * m_taskService; + std::string m_commandLine; + std::map m_pendingTransfers; + int m_totalPlayerCount; + int m_totalFreeTrialCount; + int m_totalEmptySceneCount; + int m_totalTutorialSceneCount; + int m_totalFalconSceneCount; + CentralServerMetricsData* m_metricsData; + std::map, time_t> > m_pendingPlanetServers; + std::set m_planetsWaitingForPreload; + std::map m_planetServers; + uint16 m_nextPlanetWatcherPort; + bool m_databaseBacklogged; + time_t m_lastLoadingStateTime; + time_t m_timeClusterStarted; + int m_clusterStartupTime; + time_t m_timeClusterWentIntoLoadingState; + uint8 m_clusterId; + + std::set m_serverPings; + + uint32 m_shutdownTotalTime; + uint32 m_shutdownMaxTime; + Unicode::String m_shutdownSystemMessage; + // This tracks various phases of the shutdown sequence. + // 0 = not in the process of shutting down + // 1 = first broadcast message immediately after receiving a shutdown command + // 2 = beginning process of shutting down. Sending system message broadcasts each minute warning players. + // 3 = give players 30sec to get to a safe place before being disconnected. + // 4 = done broadcasting messages; set the cluster to private, kick the players and wait for the next DatabaseSaveStart message + // 5 = received DatabaseStartSave, now we are waiting for either another DatabaseSaveStart or DatabaseSaveComplete + // (it's possible to receive another DatabaseSaveStart without a matching DatabaseSaveComplete in cases where + // there happens to be nothing to save for that cycle) + // 6 = received a DatabaseSaveComplete (or another DatabaseSaveStart) and am in the process of shutting down. + uint32 m_shutdownPhase; + bool m_shutdownHaveDatabaseSaveStart; + bool m_shutdownHaveDatabaseComplete; + uint32 m_curTime; + + time_t m_lastTimeSystemTimeMismatchNotification; + std::string m_lastTimeSystemTimeMismatchNotificationDescription; + + std::string m_disconnectedTaskManagerList; + + std::map m_populationStatistics; + time_t m_timePopulationStatisticsRefresh; + time_t m_timePopulationStatisticsNextRefresh; + + std::map > > m_gcwScoreStatistics; + time_t m_timeGcwScoreStatisticsRefresh; + time_t m_timeGcwScoreStatisticsNextRefresh; + + std::map > m_lastLoginTimeStatistics; + std::map > m_createTimeStatistics; + time_t m_timeLastLoginTimeStatisticsRefresh; + time_t m_timeLastLoginTimeStatisticsNextRefresh; + + int m_numberOfCharacterMatchRequests; + uint64 m_numberOfCharacterMatchResults; + uint64 m_timeSpentOnCharacterMatchRequestsMs; + time_t m_timeCharacterMatchStatisticsNextRefresh; +}; + +//----------------------------------------------------------------------- +inline void CentralServer::addConnectionServerConnection(ConnectionServerConnection* conn) +{ + m_connectionServerConnections.push_back(conn); +} +//----------------------------------------------------------------------- + +inline int CentralServer::getNumChatServers() const +{ + return m_chatServerConnections.size(); //lint !e713 +} + +//----------------------------------------------------------------------- + +inline int CentralServer::getNumConnectionServers() const +{ + return m_connectionServerConnections.size(); //lint !e713 +} + +//----------------------------------------------------------------------- + +inline int CentralServer::getNumDatabaseServers() const +{ + GameServerConnection * g = getGameServer(getDbProcessServerProcessId()); + if(g) + { + return 1; + } + return 0; +} + +//----------------------------------------------------------------------- + +inline int CentralServer::getNumGameServers() const +{ + return m_gameServers.size() - 1; //lint !e713 +} + +//----------------------------------------------------------------------- + +inline int CentralServer::getNumPlanetServers() const +{ + return m_planetServers.size(); //lint !e713 +} + +//----------------------------------------------------------------------- + +inline const uint32 CentralServer::getDbProcessServerProcessId(void) const +{ + return m_dbProcessServerProcessId; +} + +//----------------------------------------------------------------------- + +inline size_t CentralServer::getGameServerCount(void) const +{ + return m_gameServers.size(); +} + +//----------------------------------------------------------------------- + +inline int CentralServer::getPlayerCount() const +{ + return m_totalPlayerCount; +} + +//----------------------------------------------------------- + +inline int CentralServer::getFreeTrialCount() const +{ + return m_totalFreeTrialCount; +} + +//----------------------------------------------------------- + +inline int CentralServer::getEmptySceneCount() const +{ + return m_totalEmptySceneCount; +} + +//----------------------------------------------------------- + +inline int CentralServer::getTutorialSceneCount() const +{ + return m_totalTutorialSceneCount; +} + +//----------------------------------------------------------- + +inline int CentralServer::getFalconSceneCount() const +{ + return m_totalFalconSceneCount; +} + +//----------------------------------------------------------------------- + +inline void CentralServer::setDbProcessServerProcessId(const uint32 newDbServerProcessId) +{ + m_dbProcessServerProcessId = newDbServerProcessId; +} + +//----------------------------------------------------------------------- + +inline bool CentralServer::isPreloadFinished() const +{ + return (!m_databaseBacklogged && m_planetsWaitingForPreload.empty() && !m_planetServers.empty()); +} + +//----------------------------------------------------------------------- + +inline bool CentralServer::isInClusterInitialStartup() const +{ + return (m_clusterStartupTime == -1); +} + +// ---------------------------------------------------------------------- + +inline int CentralServer::getPlanetsWaitingForPreloadCount() const +{ + return static_cast(m_planetsWaitingForPreload.size()); +} + +// ---------------------------------------------------------------------- + +inline bool CentralServer::isDatabaseBacklogged() const +{ + return m_databaseBacklogged; +} + +// ---------------------------------------------------------------------- + +inline time_t CentralServer::getLastTimeSystemTimeMismatchNotification() const +{ + return m_lastTimeSystemTimeMismatchNotification; +} + +// ---------------------------------------------------------------------- + +inline const std::string & CentralServer::getLastTimeSystemTimeMismatchNotificationDescription() const +{ + return m_lastTimeSystemTimeMismatchNotificationDescription; +} + +// ---------------------------------------------------------------------- + +inline const std::string & CentralServer::getDisconnectedTaskManagerList() const +{ + return m_disconnectedTaskManagerList; +} + +// ---------------------------------------------------------------------- + +inline uint8 CentralServer::getClusterId() const +{ + return m_clusterId; +} + +// ====================================================================== + +#endif //_CentralServer_H diff --git a/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.cpp b/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.cpp new file mode 100644 index 00000000..c69e4736 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.cpp @@ -0,0 +1,307 @@ +// ====================================================================== +// +// CentralServerMetricsData.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstCentralServer.h" +#include "CentralServerMetricsData.h" + +#include "CentralServer.h" +#include "UniverseManager.h" +#include "ConfigCentralServer.h" +#ifndef WIN32 +#include "MonAPI2/MonitorData.h" +#endif +#include "serverNetworkMessages/MetricsDataMessage.h" +#include "serverUtility/ClusterWideDataManagerList.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" + +// ====================================================================== + +CentralServerMetricsData::CentralServerMetricsData() : + MetricsData(), + m_numChatServers(0), + m_numConnectionServers(0), + m_numDatabaseServers(0), + m_numGameServers(0), + m_numPlanetServers(0), + m_population(0), + m_freeTrialPopulation(0), + m_emptyScenePopulation(0), + m_tutorialScenePopulation(0), + m_falconScenePopulation(0), + m_universeProcess(0), + m_isLocked(0), + m_isSecret(0), + m_isLoading(0), + m_clusterId(0), + m_clusterStartupTime(0), + m_systemTimeMismatch(0), + m_taskManagerDisconnected(0), + m_clusterWideDataQueuedRequests(0), + m_characterMatchRequests(0), + m_characterMatchResultsPerRequest(0), + m_characterMatchTimePerRequest(0), + m_timePopulationStatisticsRefresh(0), + m_mapPopulationStatisticsIndex(), + m_timeGcwScoreStatisticsRefresh(0), + m_mapGcwScoreStatisticsIndex(), + m_timeLastLoginTimeStatisticsRefresh(0), + m_mapLastLoginTimeStatisticsIndex(), + m_mapCreateTimeStatisticsIndex() +{ + MetricsPair p; + + ADD_METRICS_DATA(numChatServers, 0, true); + ADD_METRICS_DATA(numConnectionServers, 0, true); + ADD_METRICS_DATA(numDatabaseServers, 0, false); + ADD_METRICS_DATA(numGameServers, 0, true); + ADD_METRICS_DATA(numPlanetServers, 0, true); + ADD_METRICS_DATA(population, 0, true); // ***MUST*** be before isLocked, isSecret, and isLoading + ADD_METRICS_DATA(freeTrialPopulation, 0, true); + ADD_METRICS_DATA(emptyScenePopulation, 0, true); + ADD_METRICS_DATA(tutorialScenePopulation, 0, true); + ADD_METRICS_DATA(falconScenePopulation, 0, true); + ADD_METRICS_DATA(universeProcess, 0, false); + ADD_METRICS_DATA(isLocked, 0, false); + ADD_METRICS_DATA(isSecret, 0, false); + ADD_METRICS_DATA(isLoading, 0, true); + ADD_METRICS_DATA(clusterId, 0, false); + ADD_METRICS_DATA(clusterStartupTime, 0, true); + ADD_METRICS_DATA(systemTimeMismatch, 0, false); + ADD_METRICS_DATA(taskManagerDisconnected, 0, false); + ADD_METRICS_DATA(clusterWideDataQueuedRequests, 0, false) + ADD_METRICS_DATA(characterMatchRequests, 0, false); + ADD_METRICS_DATA(characterMatchResultsPerRequest, 0, false); + ADD_METRICS_DATA(characterMatchTimePerRequest, 0, false); + + m_data[m_clusterId].m_description = ConfigCentralServer::getClusterName(); + m_data[m_clusterStartupTime].m_description = "minutes"; + m_data[m_characterMatchTimePerRequest].m_description = "ms"; +} + +//----------------------------------------------------------------------- + +CentralServerMetricsData::~CentralServerMetricsData() +{ +} + +//----------------------------------------------------------------------- + +void CentralServerMetricsData::updateData() +{ + MetricsData::updateData(); + m_data[m_numChatServers].m_value = CentralServer::getInstance().getNumChatServers(); + m_data[m_numConnectionServers].m_value = CentralServer::getInstance().getNumConnectionServers(); + m_data[m_numDatabaseServers].m_value = CentralServer::getInstance().getNumDatabaseServers(); + m_data[m_numGameServers].m_value = CentralServer::getInstance().getNumGameServers(); + m_data[m_numPlanetServers].m_value = CentralServer::getInstance().getNumPlanetServers(); + +#ifndef WIN32 + // if the cluster is still in initial startup, set population value to + // "loading" to cause the top level node to appear yellow + if (CentralServer::getInstance().isInClusterInitialStartup()) + m_data[m_population].m_value = STATUS_LOADING; + else +#endif + m_data[m_population].m_value = CentralServer::getInstance().getPlayerCount(); + + m_data[m_freeTrialPopulation].m_value = CentralServer::getInstance().getFreeTrialCount(); + m_data[m_emptyScenePopulation].m_value = CentralServer::getInstance().getEmptySceneCount(); + m_data[m_tutorialScenePopulation].m_value = CentralServer::getInstance().getTutorialSceneCount(); + m_data[m_falconScenePopulation].m_value = CentralServer::getInstance().getFalconSceneCount(); + m_data[m_universeProcess].m_value = static_cast(UniverseManager::getInstance().getUniverseProcess()); + m_data[m_isLocked].m_value = ( CentralServer::getInstance().getIsClusterLocked() ) ? 1 : 0; + m_data[m_isSecret].m_value = ( CentralServer::getInstance().getIsClusterSecret() ) ? 1 : 0; + if (CentralServer::getInstance().isPreloadFinished()) + { + m_data[m_isLoading].m_value = 0; + m_data[m_isLoading].m_description="Load finished."; + } + else + { + m_data[m_isLoading].m_value = std::max(1, CentralServer::getInstance().getSecondsClusterHasBeenInLoadingState()); + if (CentralServer::getInstance().getNumPlanetServers() ==0) + m_data[m_isLoading].m_description = "(seconds) No planet servers running."; + else if (CentralServer::getInstance().getPlanetsWaitingForPreloadCount() > 0) + m_data[m_isLoading].m_description = "(seconds) Starting or recovering game servers."; + else if (CentralServer::getInstance().isDatabaseBacklogged()) + m_data[m_isLoading].m_description = "(seconds) Waiting for database backlog to clear."; + else + m_data[m_isLoading].m_description = "(seconds) Reason for loading state is not available."; + } + + m_data[m_clusterId].m_value = static_cast(CentralServer::getInstance().getClusterId()); + m_data[m_clusterStartupTime].m_value = CentralServer::getInstance().getClusterStartupTime(); + + time_t const lastTimeSystemTimeMismatchNotification = CentralServer::getInstance().getLastTimeSystemTimeMismatchNotification(); + if (lastTimeSystemTimeMismatchNotification) + { + m_data[m_systemTimeMismatch].m_description = CentralServer::getInstance().getLastTimeSystemTimeMismatchNotificationDescription(); + + // display the node as red (causing the top level node to + // appear yellow to draw attention) for some amount of time + // after detecting a system time mismatch issue +#ifndef WIN32 + if ((lastTimeSystemTimeMismatchNotification + ConfigCentralServer::getSystemTimeMismatchAlertIntervalSeconds()) > ::time(NULL)) + m_data[m_systemTimeMismatch].m_value = STATUS_LOADING; + else + m_data[m_systemTimeMismatch].m_value = 1; +#else + m_data[m_systemTimeMismatch].m_value = 1; +#endif + } + else + { + m_data[m_systemTimeMismatch].m_value = 0; + m_data[m_systemTimeMismatch].m_description = "None detected so far."; + } + + std::string const & disconnectedTaskManagerList = CentralServer::getInstance().getDisconnectedTaskManagerList(); + if (disconnectedTaskManagerList.empty()) + { + m_data[m_taskManagerDisconnected].m_value = 0; + m_data[m_taskManagerDisconnected].m_description = "None detected so far."; + } + else + { +#ifndef WIN32 + m_data[m_taskManagerDisconnected].m_value = STATUS_LOADING; +#else + m_data[m_taskManagerDisconnected].m_value = 1; +#endif + + m_data[m_taskManagerDisconnected].m_description = disconnectedTaskManagerList; + } + + m_data[m_clusterWideDataQueuedRequests].m_value = ClusterWideDataManagerList::getNumberOfQueuedRequests(); + + // handle character match statistics + int numberOfCharacterMatchRequests, numberOfCharacterMatchResultsPerRequest, timeSpentPerCharacterMatchRequestMs; + CentralServer::getInstance().getCharacterMatchStatistics(numberOfCharacterMatchRequests, numberOfCharacterMatchResultsPerRequest, timeSpentPerCharacterMatchRequestMs); + m_data[m_characterMatchRequests].m_value = numberOfCharacterMatchRequests; + m_data[m_characterMatchResultsPerRequest].m_value = numberOfCharacterMatchResultsPerRequest; + m_data[m_characterMatchTimePerRequest].m_value = timeSpentPerCharacterMatchRequestMs; + + // handle population statistics + time_t timePopulationStatisticsRefresh; + const std::map & populationStatistics = CentralServer::getInstance().getPopulationStatistics(timePopulationStatisticsRefresh); + if (!populationStatistics.empty() && (timePopulationStatisticsRefresh != m_timePopulationStatisticsRefresh)) + { + if (m_mapPopulationStatisticsIndex.empty()) + { + for (std::map::const_iterator iter = populationStatistics.begin(); iter != populationStatistics.end(); ++iter) + { + if (!iter->first.empty() && (iter->second >= 0) && (m_mapPopulationStatisticsIndex.count(iter->first) < 1)) + { + std::string label("population."); + label += iter->first; + + m_mapPopulationStatisticsIndex[iter->first] = addMetric(label.c_str(), 0, NULL, false, false); + } + } + } + + for (std::map::const_iterator iter = m_mapPopulationStatisticsIndex.begin(); iter != m_mapPopulationStatisticsIndex.end(); ++iter) + { + std::map::const_iterator iterFind = populationStatistics.find(iter->first); + if (iterFind != populationStatistics.end()) + updateMetric(iter->second, iterFind->second); + else + updateMetric(iter->second, 0); + } + + m_timePopulationStatisticsRefresh = timePopulationStatisticsRefresh; + } + + // handle GCW score statistics + time_t timeGcwScoreStatisticsRefresh; + const std::map > > & gcwScoreStatistics = CentralServer::getInstance().getGcwScoreStatistics(timeGcwScoreStatisticsRefresh); + std::map::const_iterator iterFind; + int gcwScoreStatisticsIndex; + if (!gcwScoreStatistics.empty() && (timeGcwScoreStatisticsRefresh != m_timeGcwScoreStatisticsRefresh)) + { + for (std::map > >::const_iterator iter = gcwScoreStatistics.begin(); iter != gcwScoreStatistics.end(); ++iter) + { + iterFind = m_mapGcwScoreStatisticsIndex.find(iter->first); + if (iterFind != m_mapGcwScoreStatisticsIndex.end()) + { + gcwScoreStatisticsIndex = iterFind->second; + } + else + { + gcwScoreStatisticsIndex = addMetric(iter->first.c_str(), 0, NULL, false, false); + IGNORE_RETURN(m_mapGcwScoreStatisticsIndex.insert(std::make_pair(iter->first, gcwScoreStatisticsIndex))); + } + + m_data[gcwScoreStatisticsIndex].m_value = iter->second.first; + m_data[gcwScoreStatisticsIndex].m_description = iter->second.second.second; + } + + m_timeGcwScoreStatisticsRefresh = timeGcwScoreStatisticsRefresh; + } + + // handle total characters on cluster and character last login time statistics + time_t timeLastLoginTimeStatisticsRefresh; + std::pair > const *, std::map > const *> statistics = CentralServer::getInstance().getLastLoginTimeStatistics(timeLastLoginTimeStatisticsRefresh); + const std::map > & lastLoginTimeStatistics = *(statistics.first); + const std::map > & createTimeStatistics = *(statistics.second); + if (!lastLoginTimeStatistics.empty() && !createTimeStatistics.empty() && (timeLastLoginTimeStatisticsRefresh != m_timeLastLoginTimeStatisticsRefresh)) + { + if (m_mapLastLoginTimeStatisticsIndex.empty()) + { + for (std::map >::const_iterator iter = lastLoginTimeStatistics.begin(); iter != lastLoginTimeStatistics.end(); ++iter) + { + if (!iter->second.first.empty() && (m_mapLastLoginTimeStatisticsIndex.count(iter->second.first) < 1)) + { + std::string label("population."); + label += iter->second.first; + + m_mapLastLoginTimeStatisticsIndex[iter->second.first] = addMetric(label.c_str(), 0, NULL, false, false); + } + } + } + + std::map >::const_iterator iter; + for (iter = lastLoginTimeStatistics.begin(); iter != lastLoginTimeStatistics.end(); ++iter) + { + if (!iter->second.first.empty()) + { + std::map::const_iterator iterFind = m_mapLastLoginTimeStatisticsIndex.find(iter->second.first); + if (iterFind != m_mapLastLoginTimeStatisticsIndex.end()) + updateMetric(iterFind->second, iter->second.second); + } + } + + if (m_mapCreateTimeStatisticsIndex.empty()) + { + for (std::map >::const_iterator iter = createTimeStatistics.begin(); iter != createTimeStatistics.end(); ++iter) + { + if (!iter->second.first.empty() && (m_mapCreateTimeStatisticsIndex.count(iter->second.first) < 1) && (m_mapLastLoginTimeStatisticsIndex.count(iter->second.first) < 1)) + { + std::string label("population."); + label += iter->second.first; + + m_mapCreateTimeStatisticsIndex[iter->second.first] = addMetric(label.c_str(), 0, NULL, false, false); + } + } + } + + for (iter = createTimeStatistics.begin(); iter != createTimeStatistics.end(); ++iter) + { + if (!iter->second.first.empty()) + { + std::map::const_iterator iterFind = m_mapCreateTimeStatisticsIndex.find(iter->second.first); + if (iterFind != m_mapCreateTimeStatisticsIndex.end()) + updateMetric(iterFind->second, iter->second.second); + } + } + + m_timeLastLoginTimeStatisticsRefresh = timeLastLoginTimeStatisticsRefresh; + } +} + +// ====================================================================== diff --git a/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.h b/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.h new file mode 100644 index 00000000..23207246 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CentralServerMetricsData.h @@ -0,0 +1,65 @@ +//CentralServerMetricsData.h +//Copyright 2002 Sony Online Entertainment + + +#ifndef _CentralServerMetricsData_H +#define _CentralServerMetricsData_H + +//----------------------------------------------------------------------- + +#include "serverMetrics/MetricsData.h" + +//----------------------------------------------------------------------- + +class CentralServerMetricsData : public MetricsData +{ +public: + CentralServerMetricsData(); + ~CentralServerMetricsData(); + + virtual void updateData(); + +private: + unsigned long m_numChatServers; + unsigned long m_numConnectionServers; + unsigned long m_numDatabaseServers; + unsigned long m_numGameServers; + unsigned long m_numPlanetServers; + unsigned long m_population; + unsigned long m_freeTrialPopulation; + unsigned long m_emptyScenePopulation; + unsigned long m_tutorialScenePopulation; + unsigned long m_falconScenePopulation; + unsigned long m_universeProcess; + unsigned long m_isLocked; + unsigned long m_isSecret; + unsigned long m_isLoading; + unsigned long m_clusterId; + unsigned long m_clusterStartupTime; + unsigned long m_systemTimeMismatch; + unsigned long m_taskManagerDisconnected; + unsigned long m_clusterWideDataQueuedRequests; + unsigned long m_characterMatchRequests; + unsigned long m_characterMatchResultsPerRequest; + unsigned long m_characterMatchTimePerRequest; + + time_t m_timePopulationStatisticsRefresh; + std::map m_mapPopulationStatisticsIndex; + + time_t m_timeGcwScoreStatisticsRefresh; + std::map m_mapGcwScoreStatisticsIndex; + + time_t m_timeLastLoginTimeStatisticsRefresh; + std::map m_mapLastLoginTimeStatisticsIndex; + std::map m_mapCreateTimeStatisticsIndex; + +private: + + // Disabled. + CentralServerMetricsData(const CentralServerMetricsData&); + CentralServerMetricsData &operator =(const CentralServerMetricsData&); +}; + + +//----------------------------------------------------------------------- +#endif diff --git a/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.cpp b/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.cpp new file mode 100644 index 00000000..9f38aa57 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.cpp @@ -0,0 +1,374 @@ +// ====================================================================== +// +// CharacterCreationTracker.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstCentralServer.h" +#include "CharacterCreationTracker.h" + +#include "ConfigCentralServer.h" +#include "UnicodeUtils.h" +#include "serverNetworkMessages/CentralConnectionServerMessages.h" +#include "serverNetworkMessages/LoginCreateCharacterAckMessage.h" +#include "serverNetworkMessages/LoginCreateCharacterMessage.h" +#include "serverUtility/ServerClock.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/FormattedString.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedNetworkMessages/NameErrors.h" +#include "sharedNetworkMessages/NetworkStringIds.h" +#include "sharedUtility/StartingLocationData.h" +#include "sharedUtility/StartingLocationManager.h" + +// ====================================================================== + +CharacterCreationTracker * CharacterCreationTracker::ms_instance = NULL; + +// ====================================================================== + +void CharacterCreationTracker::install() +{ + DEBUG_FATAL(ms_instance != NULL,("Called install() twice.\n")); + ms_instance = new CharacterCreationTracker; + ExitChain::add(CharacterCreationTracker::remove,"CharacterCreationTracker::remove"); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::remove() +{ + DEBUG_FATAL(!ms_instance,("Not installed.\n")); + delete ms_instance; + ms_instance = 0; +} + +// ---------------------------------------------------------------------- + +CharacterCreationTracker::CharacterCreationTracker() : + m_creations() +{ +} + +// ---------------------------------------------------------------------- + +CharacterCreationTracker::~CharacterCreationTracker() +{ + for (CreationsType::iterator i = m_creations.begin(); i != m_creations.end(); ++i) + delete i->second; +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::handleCreateNewCharacter(const ConnectionCreateCharacter &msg) +{ + // - Check whether a creation request is already active for this account + CreationsType::iterator creationRecord = m_creations.find(msg.getStationId()); + if (creationRecord != m_creations.end()) + { + if (ServerClock::getInstance().getGameTimeSeconds() > (creationRecord->second->m_creationTime + ConfigCentralServer::getCharacterCreationTimeout())) + { + LOG("TraceCharacterCreation", ("%d allowing character creation because previous one timed out", msg.getStationId())); + DEBUG_REPORT_LOG(true,("Allowing character creation for account %li because previous one timed out.\n",msg.getStationId())); + unlockAccount(msg.getStationId()); + creationRecord = m_creations.end(); + } + else + { + LOG("TraceCharacterCreation", ("%d refusing character creation because one is already in progress", msg.getStationId())); + DEBUG_REPORT_LOG(true,("Refusing character creation for account %li because one was already in progress.\n",msg.getStationId())); + ConnectionCreateCharacterFailed f(msg.getStationId(), msg.getCharacterName(), NameErrors::nameDeclinedRetry, FormattedString<2048>().sprintf("%lu refusing character creation because one is already in progress", msg.getStationId())); //lint !e40 // undeclared identifier nameDeclinedEntry + CentralServer::getInstance().sendToConnectionServerForAccount(msg.getStationId(), f, true); + return; + } + } + + // - Check whether they are creating characters too rapidly + // Note that this locks only when creation succeeds. Failing to create a lot of characters in a row does not lock the account. + FastCreationLockType::iterator fcl = m_fastCreationLock.find(msg.getStationId()); + if (fcl != m_fastCreationLock.end()) + { + if (!msg.getNoRateLimit() && ((Clock::timeSeconds() - fcl->second) < (msg.getIsForCharacterTransfer() ? static_cast(ConfigCentralServer::getCharacterCtsCreationRateLimitSeconds()) : static_cast(ConfigCentralServer::getCharacterCreationRateLimitSeconds())))) + { + LOG("TraceCharacterCreation", ("%d refusing character creation because not enough time has passed since the previous one", msg.getStationId())); + DEBUG_REPORT_LOG(true,("Refusing character creation for account %li because not enough time has passed since the previous one\n",msg.getStationId())); + ConnectionCreateCharacterFailed f(msg.getStationId(), msg.getCharacterName(), NameErrors::nameDeclinedTooFast, FormattedString<2048>().sprintf("%lu refusing character creation because not enough time has passed since the previous one", msg.getStationId())); + CentralServer::getInstance().sendToConnectionServerForAccount(msg.getStationId(), f, true); + return; + } + } + + if (creationRecord == m_creations.end()) + creationRecord = m_creations.insert(std::make_pair(msg.getStationId(),new CreationRecord)).first; + + // - determine starting location + static std::string tutorialPlanetName("tutorial"); + std::string planetName; + Vector coordinates(0.0f,0.0f,0.0f); + NetworkId cellId(NetworkId::cms_invalid); + bool useNewbieTutorial = (ConfigCentralServer::getNewbieTutorialEnabled() && msg.getUseNewbieTutorial() && ! msg.getIsForCharacterTransfer()); + if (useNewbieTutorial) + planetName = tutorialPlanetName; + else + { + if (!getStartLocation(msg.getStartingLocation(), planetName, coordinates, cellId)) + { + // bad starting location + LOG("TraceCharacterCreation", ("%d bad starting location (%s)", msg.getStationId(), msg.getStartingLocation().c_str())); + ConnectionCreateCharacterFailed cccf(msg.getStationId(), msg.getCharacterName(), SharedStringIds::character_create_failed_bad_location, FormattedString<2048>().sprintf("%lu bad starting location (%s)", msg.getStationId(), msg.getStartingLocation().c_str())); + CentralServer::getInstance().sendToConnectionServerForAccount(msg.getStationId(), cccf, true); + unlockAccount(msg.getStationId()); + return; + } + } + + // - send request to game server + creationRecord->second->m_gameCreationRequest = new CentralCreateCharacter( + msg.getStationId(), + msg.getCharacterName(), + msg.getTemplateName(), + msg.getScaleFactor(), + planetName, + coordinates, + cellId, + msg.getAppearanceData(), + msg.getHairTemplateName(), + msg.getHairAppearanceData(), + msg.getProfession(), + msg.getBiography(), + useNewbieTutorial, + msg.getSkillTemplate(), + msg.getWorkingSkill(), + msg.getJedi(), + msg.getGameFeatures()); + uint32 gameServerId = CentralServer::getInstance().sendToRandomGameServer(*(creationRecord->second->m_gameCreationRequest)); + if (gameServerId == 0) + { + DEBUG_REPORT_LOG(true, ("Could not find a game server for character creation, starting a tutorial server\n")); + LOG("TraceCharacterCreation", ("%d waiting for game server", msg.getStationId())); + CentralServer::getInstance().startPlanetServer(CentralServer::getInstance().getHostForScene(tutorialPlanetName), tutorialPlanetName, 0); + creationRecord->second->m_stage = CreationRecord::S_queuedForGameServer; + return; + } + + LOG("TraceCharacterCreation", ("%d sending CentralCreateCharacter(%s) to game server %lu", msg.getStationId(), Unicode::wideToNarrow(msg.getCharacterName()).c_str(), gameServerId)); + creationRecord->second->m_stage = CreationRecord::S_sentToGameServer; + creationRecord->second->m_gameServerId = gameServerId; +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::unlockAccount(StationId account) +{ + delete m_creations[account]; + IGNORE_RETURN(m_creations.erase(account)); + LOG("TraceCharacterCreation", ("%d removing character creation lock", account)); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::retryGameServerCreates() +{ + for (CreationsType::iterator i=m_creations.begin(); i!=m_creations.end(); ++i) + { + if (i->second->m_stage == CreationRecord::S_queuedForGameServer) + { + uint32 gameServerId = CentralServer::getInstance().sendToRandomGameServer(*i->second->m_gameCreationRequest); + if (gameServerId != 0) + { + i->second->m_stage = CreationRecord::S_sentToGameServer; + i->second->m_gameServerId = gameServerId; + LOG("TraceCharacterCreation", ("%d sending CentralCreateCharacter to game server %lu", i->first,gameServerId)); + } + else + { + i->second->m_gameServerId = 0; + } + } + } +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::retryLoginServerCreates() +{ + for (CreationsType::iterator i=m_creations.begin(); i!=m_creations.end(); ++i) + { + if (i->second->m_stage == CreationRecord::S_queuedForLoginServer) + { + uint32 loginServerId = CentralServer::getInstance().sendToArbitraryLoginServer(*i->second->m_loginCreationRequest, false); + if (loginServerId != 0 ) + { + i->second->m_loginServerId = loginServerId; + i->second->m_stage = CreationRecord::S_sentToLoginServer; + LOG("TraceCharacterCreation", ("%d sending LoginCreateCharacterMessage", i->first)); + } + else + { + i->second->m_loginServerId = 0; + } + } + } +} + +// ---------------------------------------------------------------------- + +const bool CharacterCreationTracker::getStartLocation(const std::string & name, std::string & planetName, Vector & coordinates, NetworkId & cellId) const +{ + const StartingLocationData * const sld = StartingLocationManager::findLocationByName (name); + if (sld) + { + planetName = sld->planet; + coordinates.x = sld->x; + coordinates.z = sld->z; + cellId = NetworkId (sld->cellId); + return true; + } + + REPORT_LOG(true, ("The start location \"%s\" could not be found in StartingLocationManager", name.c_str())); + return false; +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::onGameServerDisconnect(uint32 serverId) +{ + for (CreationsType::iterator i=m_creations.begin(); i!=m_creations.end(); ++i) + { + if (i->second->m_stage == CreationRecord::S_sentToGameServer && i->second->m_gameServerId==serverId) + { + i->second->m_stage = CreationRecord::S_queuedForGameServer; + i->second->m_gameServerId = 0; + LOG("TraceCharacterCreation", ("%d requeueing because game server disconnected", i->first)); + } + } + retryGameServerCreates(); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::onLoginServerDisconnect(uint32 loginServerId) +{ + for (CreationsType::iterator i=m_creations.begin(); i!=m_creations.end(); ++i) + { + if (i->second->m_stage == CreationRecord::S_sentToLoginServer && i->second->m_loginServerId==loginServerId) + { + i->second->m_stage = CreationRecord::S_queuedForLoginServer; + i->second->m_loginServerId = 0; + LOG("TraceCharacterCreation", ("%d requeueing because login server disconnected", i->first)); + } + } + retryLoginServerCreates(); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::handleDatabaseCreateCharacterSuccess(StationId account, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi) +{ + // - Check we are at the right stage + LOG("TraceCharacterCreation", ("%d DatabaseCreateCharacterSuccess(%s)", account, characterObjectId.getValueString().c_str())); + CreationsType::iterator creationRecord=m_creations.find(account); + if (creationRecord==m_creations.end() || creationRecord->second->m_stage != CreationRecord::S_sentToGameServer) + { + LOG("TraceCharacterCreation", ("%d DatabaseCreateCharacterSuccess was unexpected - exiting", account)); + DEBUG_WARNING(true,("Programmer bug: got GameCreateCharacter message for accout %d, which we weren't expecting.\n",account)); + return; + } + + // - Tell the login server to add the character + LoginCreateCharacterMessage *msg = new LoginCreateCharacterMessage(account,characterName,characterObjectId,templateId,jedi); + creationRecord->second->m_loginCreationRequest = msg; + creationRecord->second->m_characterId = characterObjectId; + uint32 loginServerId = CentralServer::getInstance().sendToArbitraryLoginServer(*msg, false); + if (loginServerId != 0) + { + creationRecord->second->m_loginServerId = loginServerId; + creationRecord->second->m_stage = CreationRecord::S_sentToLoginServer; + LOG("TraceCharacterCreation", ("%d sending LoginCreateCharacterMessage", account)); + } + else + { + creationRecord->second->m_loginServerId = 0; + creationRecord->second->m_stage = CreationRecord::S_queuedForLoginServer; + LOG("TraceCharacterCreation", ("%d waiting for login server", account)); + } +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::handleLoginCreateCharacterAck(StationId account) +{ + // - Check we are at the right stage + LOG("TraceCharacterCreation", ("%d LoginCreateCharacterAckMessage", account)); + CreationsType::iterator creationRecord=m_creations.find(account); + if (creationRecord==m_creations.end() || creationRecord->second->m_stage != CreationRecord::S_sentToLoginServer) + { + LOG("TraceCharacterCreation", ("%d LoginCreateCharacterAckMessage was unexpected - exiting", account)); + DEBUG_WARNING(true,("Programmer bug: got LoginCreateCharacterAckMessage message for account %d, which we weren't expecting.\n",account)); + return; + } + + // - Tell the client the character has been created + LOG("TraceCharacterCreation", ("%d acknowledgeCharacterCreate(%s)", account, creationRecord->second->m_characterId.getValueString().c_str())); + LOG("CustomerService", ("Player:created character %s for stationId %u", creationRecord->second->m_characterId.getValueString().c_str(), account)); + const ConnectionCreateCharacterSuccess c(account, creationRecord->second->m_characterId); + CentralServer::getInstance().sendToConnectionServerForAccount(account, c, true); + unlockAccount(account); + + // let all connection servers know that a new character has been created for the station account + GenericValueTypeMessage const ncc("NewCharacterCreated", account); + CentralServer::getInstance().sendToAllConnectionServers(ncc, true); + + setFastCreationLock(account); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::handleGameCreateCharacterFailed(StationId account, Unicode::String const &characterName, StringId const &errorMessage, std::string const &optionalDetailedErrorMessage) +{ + CreationsType::iterator creationRecord=m_creations.find(account); + if (creationRecord==m_creations.end() || creationRecord->second->m_stage != CreationRecord::S_sentToGameServer) + { + LOG("TraceCharacterCreation", ("%d got handleGameCreateCharacterFailed, but we weren't in the sentToGameServer stage - ignoring", account)); + DEBUG_WARNING(true,("Programmer bug: got handleGameCreateCharacterFailed message for account %d, which we weren't expecting.\n",account)); + return; + } + + LOG("TraceCharacterCreation", ("%d received GameCreateCharacterFailed(%s)", account, Unicode::wideToNarrow(characterName).c_str())); + ConnectionCreateCharacterFailed cccf(account, characterName, errorMessage, optionalDetailedErrorMessage); + CentralServer::getInstance().sendToConnectionServerForAccount(account, cccf, true); + unlockAccount(account); +} + +// ---------------------------------------------------------------------- + +void CharacterCreationTracker::setFastCreationLock(StationId account) +{ + m_fastCreationLock[account]=Clock::timeSeconds(); +} + +// ====================================================================== + +CharacterCreationTracker::CreationRecord::CreationRecord() : + m_stage(S_queuedForGameServer), + m_gameCreationRequest(NULL), + m_loginCreationRequest(NULL), + m_creationTime(ServerClock::getInstance().getGameTimeSeconds()), + m_gameServerId(0), + m_loginServerId(0), + m_characterId(NetworkId::cms_invalid) +{ +} + +// ---------------------------------------------------------------------- + +CharacterCreationTracker::CreationRecord::~CreationRecord() +{ + delete m_gameCreationRequest; + delete m_loginCreationRequest; + m_gameCreationRequest = 0; + m_loginCreationRequest = 0; +} diff --git a/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.h b/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.h new file mode 100644 index 00000000..7d0418de --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/CharacterCreationTracker.h @@ -0,0 +1,84 @@ +// ====================================================================== +// +// CharacterCreationTracker.h +// copyright (c) 2003 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_CharacterCreationTracker_H +#define INCLUDED_CharacterCreationTracker_H + +// ====================================================================== + +class ConnectionCreateCharacter; +class LoginCreateCharacterMessage; + +// ====================================================================== + +class CharacterCreationTracker +{ +public: + static CharacterCreationTracker &getInstance(); + static void install(); + static void remove(); + CharacterCreationTracker(); + ~CharacterCreationTracker(); + +public: + void handleCreateNewCharacter (const ConnectionCreateCharacter &msg); + void handleDatabaseCreateCharacterSuccess (StationId account, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi); + void handleLoginCreateCharacterAck (StationId account); + void handleGameCreateCharacterFailed (StationId account, Unicode::String const &characterName, StringId const &errorMessage, std::string const &optionalDetailedErrorMessage); + void retryGameServerCreates (); + void retryLoginServerCreates (); + void onGameServerDisconnect (uint32 serverId); + void onLoginServerDisconnect (uint32 loginServerId); + void setFastCreationLock (StationId account); + +private: + + struct CreationRecord + { + enum Stage {S_queuedForGameServer, S_sentToGameServer, S_queuedForLoginServer, S_sentToLoginServer}; + + Stage m_stage; + CentralCreateCharacter * m_gameCreationRequest; + LoginCreateCharacterMessage * m_loginCreationRequest; + uint32 m_creationTime; + uint32 m_gameServerId; + uint32 m_loginServerId; + NetworkId m_characterId; + + CreationRecord(); + ~CreationRecord(); + + private: + CreationRecord (const CreationRecord&); //disable + CreationRecord &operator=(const CreationRecord&); //disable + }; + + typedef std::map CreationsType; + CreationsType m_creations; + + typedef std::map FastCreationLockType; + FastCreationLockType m_fastCreationLock; + +private: + void unlockAccount (StationId account); + const bool getStartLocation (const std::string & name, std::string & planetName, Vector & coordinates, NetworkId & cellId) const; + +private: + static CharacterCreationTracker *ms_instance; +}; + +// ====================================================================== + +inline CharacterCreationTracker &CharacterCreationTracker::getInstance() +{ + NOT_NULL(ms_instance); + return *ms_instance; +} + +// ====================================================================== + +#endif diff --git a/engine/server/application/CentralServer/src/shared/ChatServerConnection.cpp b/engine/server/application/CentralServer/src/shared/ChatServerConnection.cpp new file mode 100644 index 00000000..5fa160f8 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ChatServerConnection.cpp @@ -0,0 +1,64 @@ +// ChatServerConnection.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "ChatServerConnection.h" + +//----------------------------------------------------------------------- + +ChatServerConnection::ChatServerConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection(u, t), +gameServicePort(0) +{ +} + +//----------------------------------------------------------------------- + +ChatServerConnection::~ChatServerConnection() +{ +} + +//----------------------------------------------------------------------- + +const unsigned short ChatServerConnection::getGameServicePort() const +{ + return gameServicePort; +} + +//----------------------------------------------------------------------- + +void ChatServerConnection::onConnectionOpened() +{ + ServerConnection::onConnectionOpened(); + static MessageConnectionCallback m("ChatServerConnectionOpened"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void ChatServerConnection::onConnectionClosed() +{ + ServerConnection::onConnectionClosed(); + static MessageConnectionCallback m("ChatServerConnectionClosed"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void ChatServerConnection::onReceive(const Archive::ByteStream & message) +{ + ServerConnection::onReceive(message); +} + +//----------------------------------------------------------------------- + +void ChatServerConnection::setGameServicePort(const unsigned short p) +{ + gameServicePort = p; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/CentralServer/src/shared/ChatServerConnection.h b/engine/server/application/CentralServer/src/shared/ChatServerConnection.h new file mode 100644 index 00000000..1ac213a1 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ChatServerConnection.h @@ -0,0 +1,34 @@ +// ChatServerConnection.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ChatServerConnection_H +#define _INCLUDED_ChatServerConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +//----------------------------------------------------------------------- + +class ChatServerConnection : public ServerConnection +{ +public: + explicit ChatServerConnection(UdpConnectionMT *, TcpClient *); + ~ChatServerConnection(); + const unsigned short getGameServicePort () const; + void onConnectionClosed (); + void onConnectionOpened (); + void onReceive (const Archive::ByteStream & message); + void setGameServicePort (const unsigned short gameServicePort); + +private: + ChatServerConnection & operator = (const ChatServerConnection & rhs); + ChatServerConnection(const ChatServerConnection & source); + unsigned short gameServicePort; + +}; //lint !e1712 default constructor not defined + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ChatServerConnection_H diff --git a/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp new file mode 100644 index 00000000..e7aa881d --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp @@ -0,0 +1,165 @@ +// ConfigCentralServer.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "serverUtility/ConfigServerUtility.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "ConfigCentralServer.h" + +//----------------------------------------------------------------------- + +ConfigCentralServer::Data * ConfigCentralServer::data = 0; + +#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("CentralServer", #a, b)) +#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("CentralServer", #a, b)) +#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("CentralServer", #a, b)) + +//----------------------------------------------------------------------- + +namespace ConfigCentralServerNamespace +{ + typedef std::vector StringPtrArray; + StringPtrArray ms_startPlanets; // ConfigFile owns the pointer + StringPtrArray ms_startConnectionServer; +} + +using namespace ConfigCentralServerNamespace; + +// ====================================================================== + +int ConfigCentralServer::getNumberOfStartPlanets() +{ + return static_cast(ms_startPlanets.size()); +} + +// ---------------------------------------------------------------------- + +char const * ConfigCentralServer::getStartPlanet(int index) +{ + VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfStartPlanets()); + return ms_startPlanets[static_cast(index)]; +} + +// ---------------------------------------------------------------------- + +int ConfigCentralServer::getNumberOfStartingConnectionServers() +{ + return static_cast(ms_startConnectionServer.size()); +} + +// ---------------------------------------------------------------------- + +char const * ConfigCentralServer::getStartingConnectionServer(int index) +{ + VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfStartingConnectionServers()); + return ms_startConnectionServer[static_cast(index)]; +} + +// ---------------------------------------------------------------------- + +void ConfigCentralServer::install(void) +{ + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + ConfigServerUtility::install(); + + data = new ConfigCentralServer::Data; + + KEY_INT (chatServicePort, 61232); + KEY_INT (connectionServicePort, 0); + KEY_INT (customerServicePort, 61242); + KEY_INT (gameServicePort, 44451); + KEY_STRING (loginServerAddress, "64.37.132.178"); + KEY_INT (loginServerPort, 44452); + KEY_STRING (clusterName, "devcluster"); + KEY_STRING (startPlanet, "tatooine"); + KEY_INT (taskManagerPort, 60001); + KEY_INT (planetServicePort, 44455); + KEY_INT (planetServerRestartDelayTimeSeconds, 60); + KEY_INT (connectionServerRestartDelayTimeSeconds, 60); + KEY_INT (chatServerRestartDelayTimeSeconds, 60); + KEY_INT (updatePlayerCountFrequency, 10); + KEY_BOOL (newbieTutorialEnabled, false); + KEY_STRING (chatServiceBindInterface, ""); + KEY_STRING (connectionServiceBindInterface, ""); + KEY_STRING (customerServiceBindInterface, ""); + KEY_STRING (gameServiceBindInterface, ""); + KEY_STRING (loginServiceBindInterface, ""); + KEY_STRING (planetServiceBindInterface, ""); + KEY_INT (firstPlanetWatcherPort, 60002); + KEY_INT (loginServicePort, 44452); + KEY_BOOL (developmentMode, true); + KEY_BOOL (shouldSleep, true); + KEY_BOOL (startPublic, false); + KEY_INT (consoleServicePort, 61000); + KEY_STRING (consoleServiceBindInterface, ""); + KEY_INT (characterCreationTimeout,5*60); // seconds + KEY_STRING (chatServerHost, "local"); + KEY_STRING (dbServerHost, "local"); + KEY_INT (serverPingTimeout,0); // seconds + KEY_INT (recentLoadingStateSeconds,60*60); + KEY_INT (characterCreationRateLimitSeconds, 0); + KEY_INT (characterCtsCreationRateLimitSeconds, 0); + KEY_STRING (transferServerAddress, "127.0.0.1"); + KEY_INT (transferServerPort, 0); // TransferServer listens on 50005, default to "off" + KEY_STRING (stationPlayersCollectorAddress, "127.0.0.1"); + KEY_INT (stationPlayersCollectorPort, 0); // StationPlayersCollector listens on 50010, default to "off" + KEY_BOOL (allowZeroConnectionServerPort, true); + KEY_INT (clusterWideDataLockTimeout, 300); // seconds + KEY_STRING (commodityServerServiceBindInterface, ""); + KEY_INT (commodityServerServicePort, 44456); + KEY_BOOL (shutdown, false); + KEY_BOOL (validateBuildVersionNumber, false); + KEY_INT (gameServerConnectionPendingAllocatedSizeLimit, 0); + KEY_INT (systemTimeMismatchAlertIntervalSeconds, 1*60*60); // seconds + KEY_INT (ctsDenyLoginThresholdSeconds, 2*60*60); // seconds + KEY_BOOL (auctionEnabled, false); + KEY_STRING (auctionServer, "sdt-plattestsys2.station.sony.com"); + KEY_INT (auctionPort, 5901 ); + KEY_STRING (auctionIDPrefix, "SWG+"); + KEY_BOOL (disconnectDuplicateConnectionsOnOtherGalaxies, false); + KEY_BOOL (requestDbSaveOnPlanetServerCrash, true); + KEY_INT (maxTimeToWaitForPlanetServerStartSeconds, 5*60); // seconds + + int index = 0; + char const * result = 0; + do + { + result = ConfigFile::getKeyString("CentralServer", "startPlanet", index++, 0); + if (result != 0) + { + ms_startPlanets.push_back(result); + } + } + while (result); + + index = 0; + result = 0; + do + { + result = ConfigFile::getKeyString("CentralServer", "startConnectionServer", index++, 0); + if (result != 0) + { + ms_startConnectionServer.push_back(result); + } + } + while (result); +} + +//----------------------------------------------------------------------- + +void ConfigCentralServer::remove(void) +{ + delete data; + data = 0; + ConfigServerUtility::remove(); +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/CentralServer/src/shared/ConfigCentralServer.h b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.h new file mode 100644 index 00000000..fdc5b131 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.h @@ -0,0 +1,515 @@ +// ConfigCentralServer.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _ConfigCentralServer_H +#define _ConfigCentralServer_H + +//----------------------------------------------------------------------- + +class ConfigCentralServer +{ +public: + struct Data + { + int chatServicePort; + int connectionServicePort; + int customerServicePort; + const char * clusterName; + int gameServicePort; + const char * loginServerAddress; + int loginServerPort; + const char * startPlanet; + int taskManagerPort; + int planetServicePort; + int planetServerRestartDelayTimeSeconds; + int connectionServerRestartDelayTimeSeconds; + int chatServerRestartDelayTimeSeconds; + int updatePlayerCountFrequency; + bool newbieTutorialEnabled; + const char * chatServiceBindInterface; + const char * connectionServiceBindInterface; + const char * customerServiceBindInterface; + const char * gameServiceBindInterface; + const char * loginServiceBindInterface; + const char * planetServiceBindInterface; + int firstPlanetWatcherPort; + int loginServicePort; + bool developmentMode; + bool shouldSleep; + bool startPublic; + const char * consoleServiceBindInterface; + int consoleServicePort; + int characterCreationTimeout; + const char * chatServerHost; + const char * dbServerHost; + int serverPingTimeout; + int recentLoadingStateSeconds; + int characterCreationRateLimitSeconds; + int characterCtsCreationRateLimitSeconds; + const char * transferServerAddress; + int transferServerPort; + const char * stationPlayersCollectorAddress; + int stationPlayersCollectorPort; + bool allowZeroConnectionServerPort; + int clusterWideDataLockTimeout; + const char * commodityServerServiceBindInterface; + int commodityServerServicePort; + bool shutdown; + bool validateBuildVersionNumber; + int gameServerConnectionPendingAllocatedSizeLimit; + int systemTimeMismatchAlertIntervalSeconds; + int ctsDenyLoginThresholdSeconds; + + bool auctionEnabled; + const char * auctionServer; + int auctionPort; + const char * auctionIDPrefix; + + bool disconnectDuplicateConnectionsOnOtherGalaxies; + + bool requestDbSaveOnPlanetServerCrash; + + int maxTimeToWaitForPlanetServerStartSeconds; + }; + + static const unsigned short getChatServicePort (); + static const unsigned short getConnectionServicePort(); + static const char * getConsoleServiceBindInterface(); + static const unsigned short getConsoleServicePort(); + static const unsigned short getCustomerServicePort (); + static const char * getClusterName (); + static const unsigned short getGameServicePort (); + static const char * getLoginServerAddress (); + static const unsigned short getLoginServerPort (); + static const char * getStartPlanet (); + static const unsigned short getTaskManagerPort (); + static const unsigned short getPlanetServicePort (); + static const unsigned int getPlanetServerRestartDelayTimeSeconds(); + static const unsigned int getConnectionServerRestartDelayTimeSeconds(); + static const unsigned int getChatServerRestartDelayTimeSeconds(); + static int getUpdatePlayerCountFrequency (); + static bool getNewbieTutorialEnabled(); + static const char * getChatServiceBindInterface (); + static const char * getConnectionServiceBindInterface (); + static const char * getCustomerServiceBindInterface (); + static const char * getGameServiceBindInterface (); + static const char * getLoginServiceBindInterface (); + static const char * getPlanetServiceBindInterface (); + static const unsigned short getLoginServicePort (); + static void install (); + static void remove (); + static uint16 getFirstPlanetWatcherPort(); + static bool getDevelopmentMode (); + static bool getLogLoopTimes (); + static bool getShouldSleep (); + static bool getStartPublic (); + static unsigned int getCharacterCreationTimeout(); + static const char * getChatServerHost(); + static const char * getDbServerHost(); + static const int getServerPingTimeout(); + static const int getRecentLoadingStateSeconds(); + static const int getCharacterCreationRateLimitSeconds(); + static const int getCharacterCtsCreationRateLimitSeconds(); + static const char * getTransferServerAddress(); + static unsigned short getTransferServerPort(); + static const char * getStationPlayersCollectorAddress(); + static unsigned short getStationPlayersCollectorPort(); + static bool getAllowZeroConnectionServerPort(); + static int getClusterWideDataLockTimeout(); + static const char * getCommodityServerServiceBindInterface(); + static const unsigned short getCommodityServerServicePort(); + + static int getNumberOfStartPlanets(); + static char const * getStartPlanet(int index); + static int getNumberOfStartingConnectionServers(); + static char const * getStartingConnectionServer(int index); + static bool getShutdown(); + static bool getValidateBuildVersionNumber(); + static unsigned int getGameServerConnectionPendingAllocatedSizeLimit(); + static int getSystemTimeMismatchAlertIntervalSeconds(); + static int getCtsDenyLoginThresholdSeconds(); + + static bool getAuctionEnabled(); + static const char * getAuctionServer(); + static int getAuctionPort(); + static const char * getAuctionIDPrefix(); + + static bool getDisconnectDuplicateConnectionsOnOtherGalaxies(); + + static bool getRequestDbSaveOnPlanetServerCrash(); + + static int getMaxTimeToWaitForPlanetServerStartSeconds(); + +private: + static Data * data; +}; + +//----------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getChatServicePort() +{ + return static_cast(data->chatServicePort); +} + +//----------------------------------------------------------------------- + +inline bool ConfigCentralServer::getShouldSleep() +{ + return data->shouldSleep; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getConnectionServicePort() +{ + return static_cast(data->connectionServicePort); +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getCustomerServicePort() +{ + return static_cast(data->customerServicePort); +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getClusterName() +{ + return data->clusterName; +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigCentralServer::getGameServicePort() +{ + return static_cast(data->gameServicePort); +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getLoginServerAddress() +{ + return data->loginServerAddress; +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigCentralServer::getLoginServerPort() +{ + return static_cast(data->loginServerPort); +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getStartPlanet() +{ + return data->startPlanet; +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigCentralServer::getTaskManagerPort() +{ + return static_cast(data->taskManagerPort); +} + +// ---------------------------------------------------------------------- + +inline const uint16 ConfigCentralServer::getPlanetServicePort() +{ + return static_cast(data->planetServicePort); +} + +// ---------------------------------------------------------------------- + +inline const unsigned int ConfigCentralServer::getPlanetServerRestartDelayTimeSeconds() +{ + return static_cast(data->planetServerRestartDelayTimeSeconds); +} + +// ---------------------------------------------------------------------- + +inline const unsigned int ConfigCentralServer::getConnectionServerRestartDelayTimeSeconds() +{ + return static_cast(data->connectionServerRestartDelayTimeSeconds); +} + +// ---------------------------------------------------------------------- + +inline const unsigned int ConfigCentralServer::getChatServerRestartDelayTimeSeconds() +{ + return static_cast(data->chatServerRestartDelayTimeSeconds); +} + +//----------------------------------------------------------------------- + +inline int ConfigCentralServer::getUpdatePlayerCountFrequency() +{ + return data->updatePlayerCountFrequency; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getNewbieTutorialEnabled() +{ + return data->newbieTutorialEnabled; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getChatServiceBindInterface() +{ + return data->chatServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getConnectionServiceBindInterface() +{ + return data->connectionServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getCustomerServiceBindInterface() +{ + return data->customerServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getGameServiceBindInterface() +{ + return data->gameServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getLoginServiceBindInterface() +{ + return data->loginServiceBindInterface; +} + +//----------------------------------------------------------------------- + + +inline const char * ConfigCentralServer::getPlanetServiceBindInterface() +{ + return data->planetServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline uint16 ConfigCentralServer::getFirstPlanetWatcherPort() +{ + return static_cast(data->firstPlanetWatcherPort); +} + +// ---------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getLoginServicePort() +{ + return static_cast(data->loginServicePort); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getStartPublic() +{ + return data->startPublic; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getDevelopmentMode() +{ + return data->developmentMode; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getConsoleServiceBindInterface() +{ + return data->consoleServiceBindInterface; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getConsoleServicePort() +{ + return static_cast(data->consoleServicePort); +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCentralServer::getCharacterCreationTimeout() +{ + return static_cast(data->characterCreationTimeout); +} + +//------------------------------------------------------------------------------------------ + +inline const char * ConfigCentralServer::getChatServerHost() +{ + return data->chatServerHost; +} + +//------------------------------------------------------------------------------------------ + +inline const char * ConfigCentralServer::getDbServerHost() +{ + return data->dbServerHost; +} + +//------------------------------------------------------------------------------------------ + +inline const int ConfigCentralServer::getServerPingTimeout() +{ + return data->serverPingTimeout; +} + +// ---------------------------------------------------------------------- + +inline const int ConfigCentralServer::getRecentLoadingStateSeconds() +{ + return data->recentLoadingStateSeconds; +} + +// ---------------------------------------------------------------------- + +inline const int ConfigCentralServer::getCharacterCreationRateLimitSeconds() +{ + return data->characterCreationRateLimitSeconds; +} + +// ---------------------------------------------------------------------- + +inline const int ConfigCentralServer::getCharacterCtsCreationRateLimitSeconds() +{ + return data->characterCtsCreationRateLimitSeconds; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getTransferServerAddress() +{ + return data->transferServerAddress; +} + +// ---------------------------------------------------------------------- + +inline unsigned short ConfigCentralServer::getTransferServerPort() +{ + return static_cast(data->transferServerPort); +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getStationPlayersCollectorAddress() +{ + return data->stationPlayersCollectorAddress; +} + +// ---------------------------------------------------------------------- + +inline unsigned short ConfigCentralServer::getStationPlayersCollectorPort() +{ + return static_cast(data->stationPlayersCollectorPort); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getAllowZeroConnectionServerPort() +{ + return data->allowZeroConnectionServerPort; +} + +// ---------------------------------------------------------------------- + +inline int ConfigCentralServer::getClusterWideDataLockTimeout() +{ + return data->clusterWideDataLockTimeout; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigCentralServer::getCommodityServerServiceBindInterface() +{ + return data->commodityServerServiceBindInterface; +} + +// ---------------------------------------------------------------------- + +inline const unsigned short ConfigCentralServer::getCommodityServerServicePort() +{ + return static_cast(data->commodityServerServicePort); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getShutdown() +{ + return data->shutdown; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getValidateBuildVersionNumber() +{ + return data->validateBuildVersionNumber; +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCentralServer::getGameServerConnectionPendingAllocatedSizeLimit() +{ + return static_cast(data->gameServerConnectionPendingAllocatedSizeLimit); +} + +// ---------------------------------------------------------------------- + +inline int ConfigCentralServer::getSystemTimeMismatchAlertIntervalSeconds() +{ + return data->systemTimeMismatchAlertIntervalSeconds; +} + +// ---------------------------------------------------------------------- + +inline int ConfigCentralServer::getCtsDenyLoginThresholdSeconds() +{ + return data->ctsDenyLoginThresholdSeconds; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getAuctionEnabled() { return data->auctionEnabled; } +inline const char * ConfigCentralServer::getAuctionServer() { return data->auctionServer; } +inline int ConfigCentralServer::getAuctionPort() { return data->auctionPort; } +inline const char * ConfigCentralServer::getAuctionIDPrefix() { return data->auctionIDPrefix; } + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getDisconnectDuplicateConnectionsOnOtherGalaxies() +{ + return data->disconnectDuplicateConnectionsOnOtherGalaxies; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCentralServer::getRequestDbSaveOnPlanetServerCrash() +{ + return data->requestDbSaveOnPlanetServerCrash; +} + +// ---------------------------------------------------------------------- + +inline int ConfigCentralServer::getMaxTimeToWaitForPlanetServerStartSeconds() +{ + return data->maxTimeToWaitForPlanetServerStartSeconds; +} + +// ====================================================================== + +#endif // _ConfigCentralServer_H diff --git a/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.cpp b/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.cpp new file mode 100644 index 00000000..3ef1d338 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.cpp @@ -0,0 +1,427 @@ +// ConnectionServerConnection.cpp +// copyright 2001 Verant Interactive + + + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "ConnectionServerConnection.h" + +#include "serverNetworkMessages/AccountFeatureIdRequest.h" +#include "serverNetworkMessages/AdjustAccountFeatureIdRequest.h" +#include "serverNetworkMessages/CentralConnectionServerMessages.h" +#include "serverNetworkMessages/CentralGameServerMessages.h" +#include "serverNetworkMessages/EnumerateServers.h" +#include "serverNetworkMessages/LoginConnectionServerAddress.h" +#include "serverNetworkMessages/TaskSpawnProcess.h" +#include "serverNetworkMessages/ToggleAvatarLoginStatus.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "serverNetworkMessages/TransferCharacterDataArchive.h" +#include "serverNetworkMessages/UpdateConnectionServerStatus.h" +#include "serverNetworkMessages/UpdateLoginConnectionServerStatus.h" +#include "sharedLog/Log.h" +#include "sharedMessageDispatch/Transceiver.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +//----------------------------------------------------------------------- + +namespace ConnectionServerConnectionNamespace +{ + std::map > s_pseudoClientConnectionMap; +} + +using namespace ConnectionServerConnectionNamespace; + +int ConnectionServerConnection::ms_connectionServerNumber = 0; +struct OnConnectionServerConnectionClosed {}; + +//----------------------------------------------------------------------- + +ConnectionServerConnection::ConnectionServerConnection(const std::string & a, const uint16 p) : +ServerConnection (a, p, NetworkSetupData()), +m_chatServicePort (0), +m_csServicePort (0), +m_clientServicePortPrivate (0), +m_clientServicePortPublic (0), +m_gameServicePort (0), +m_id (0), +m_pingPort (0), +m_connectionServerNumber (0), +m_gameServiceAddress (), +m_playerCount (0), +m_freeTrialCount (0), +m_emptySceneCount (0), +m_tutorialSceneCount (0), +m_falconSceneCount (0), +m_clientServiceAddress (), +m_chatServiceAddress (), +m_customerServiceAddress () +{ +} + +//----------------------------------------------------------------------- + +ConnectionServerConnection::ConnectionServerConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection (u, t), +m_chatServicePort (0), +m_csServicePort (0), +m_clientServicePortPrivate (0), +m_clientServicePortPublic (0), +m_gameServicePort (0), +m_id (0), +m_pingPort (0), +m_connectionServerNumber (0), +m_gameServiceAddress (), +m_playerCount (0), +m_freeTrialCount (0), +m_emptySceneCount (0), +m_tutorialSceneCount (0), +m_falconSceneCount (0), +m_clientServiceAddress (), +m_chatServiceAddress (), +m_customerServiceAddress () +{ +} + +//----------------------------------------------------------------------- + +ConnectionServerConnection::~ConnectionServerConnection() +{ + // remove ConnectionServerConnection *'s from the + // s_pseudoClientConnectionMap + std::map >::iterator i; + for(i = s_pseudoClientConnectionMap.begin(); i != s_pseudoClientConnectionMap.end();) + { + if(i->second.second == this) + { + if (i->second.first == TransferRequestMoveValidation::TRS_transfer_server) + { + GenericValueTypeMessage failed("TransferFailConnectionServerClosedConnectionWithCentralServer", i->first); + CentralServer::getInstance().sendToTransferServer(failed); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Transfer failed: ConnectionServer connection closed with CentralServer while transfer was in progress for station id %u", i->first)); + } + + s_pseudoClientConnectionMap.erase(i++); + } + else + { + ++i; + } + } +} + +//----------------------------------------------------------------------- + +bool ConnectionServerConnection::sendToPseudoClientConnection(unsigned int stationId, const GameNetworkMessage & message) +{ + bool result = false; + std::map >::iterator f = s_pseudoClientConnectionMap.find(stationId); + if(f != s_pseudoClientConnectionMap.end()) + { + result = true; + f->second.second->send(message, true); + } + return result; +} + +//----------------------------------------------------------------------- + +void ConnectionServerConnection::onConnectionClosed() +{ + static MessageDispatch::Transceiver t; + static OnConnectionServerConnectionClosed c; + t.emitMessage(c);//lint !e738 // I want the default initialization + + ServerConnection::onConnectionClosed(); + CentralServer::getInstance().removeConnectionServerConnection(this); + static MessageConnectionCallback m("ConnectionServerConnectionClosed"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void ConnectionServerConnection::onConnectionOpened() +{ + ServerConnection::onConnectionOpened(); + + m_id = ++ms_connectionServerNumber; + ConnectionServerId message(m_id); + + send(message, true); + // push encryption keys to the connection server + CentralServer::getInstance().pushAllKeys(this); + + static MessageConnectionCallback m("ConnectionServerConnectionOpened"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void ConnectionServerConnection::onReceive(const Archive::ByteStream & message) +{ + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); + + if(m.isType("NewCentralConnectionServer")) + { + const NewCentralConnectionServer ncs(ri); + + m_chatServicePort = ncs.getChatServicePort(); + m_csServicePort = ncs.getCustomerServicePort(); + + m_clientServicePortPrivate = ncs.getClientServicePortPrivate(); + m_clientServicePortPublic = ncs.getClientServicePortPublic(); + m_gameServicePort = ncs.getGameServicePort(); + m_pingPort = ncs.getPingPort (); + m_connectionServerNumber = ncs.getConnectionServerNumber(); + m_gameServiceAddress = ncs.getGameServiceAddress(); + m_clientServiceAddress = ncs.getClientServiceAddress(); + m_chatServiceAddress = ncs.getChatServiceAddress(); + m_customerServiceAddress = ncs.getCustomerServiceAddress(); + + CentralServer::getInstance().addConnectionServerConnection(this); + + //Now broadcast to gameservers + ConnectionServerAddress const addressMessage(m_gameServiceAddress, m_gameServicePort); + CentralServer::getInstance().broadcastToGameServers(addressMessage); + + //Send to chat server + const int ct = static_cast(EnumerateServers::CONNECTION_SERVER); + EnumerateServers e(true, getChatServiceAddress(), getChatServicePort(), ct); + + if (!getChatServiceAddress().empty() && (getChatServicePort() != 0)) + { + CentralServer::getInstance().broadcastToChatServers(e); + } + else + { + LOG("ChatServ", ("ConnectionServerConnection::onReceive() Chat service address and port are invalid, unable to CentralServer::getInstance().broadcastToChatServers()")); + } + + //Send to CS servers + const EnumerateServers e2(true, getCustomerServiceAddress(), getCustomerServicePort(), ct); + + if ( !getCustomerServiceAddress().empty() + && (getCustomerServicePort() != 0)) + { + CentralServer::getInstance().broadcastToCustomerServiceServers(e2); + } + else + { + LOG("ChatServ", ("ConnectionServerConnection::onReceive() Customer service address and port are invalid, unable to CentralServer::getInstance().broadcastToCustomerServiceServers()")); + } + + //Send to login Servers + if ( (getClientServicePortPrivate() != 0) || (getClientServicePortPublic() != 0) ) + { + const LoginConnectionServerAddress csa(m_id, getClientServiceAddress(), getClientServicePortPrivate(), + getClientServicePortPublic(), getPlayerCount(), getPingPort ()); + CentralServer::getInstance().sendToAllLoginServers(csa); + } + } + else if (m.isType("UpdateConnectionServerStatus")) + { + DEBUG_REPORT_LOG(true, ("Got update status for connection server\n")); + const UpdateConnectionServerStatus ucs(ri); + m_clientServicePortPublic = ucs.getPublicPort(); + m_clientServicePortPrivate = ucs.getPrivatePort(); + UpdateLoginConnectionServerStatus ulc(getId(), m_clientServicePortPublic, m_clientServicePortPrivate, getPlayerCount()); + CentralServer::getInstance().sendToAllLoginServers(ulc); + } + + else if(m.isType("TaskSpawnProcess")) + { + const TaskSpawnProcess spawn(ri); + CentralServer::getInstance().sendTaskMessage(spawn); + } + else if(m.isType("NewPseudoClientConnection")) + { + const GenericValueTypeMessage > info(ri); + s_pseudoClientConnectionMap[info.getValue().first] = std::make_pair(static_cast(info.getValue().second), this); + + // remove corresponding "non pseudo client connection" + CentralServer::getInstance().removeFromAccountConnectionMap(static_cast(info.getValue().first)); + } + else if(m.isType("DestroyPseudoClientConnection")) + { + const GenericValueTypeMessage info(ri); + std::map >::iterator f = s_pseudoClientConnectionMap.find(info.getValue()); + if(f != s_pseudoClientConnectionMap.end()) + { + s_pseudoClientConnectionMap.erase(f); + } + } + else if(m.isType("TransferReceiveDataFromGameServer")) + { + const GenericValueTypeMessage transferReply(ri); + + if(transferReply.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(transferReply); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Got TransferReceiveDataFromGameServer: %s", transferReply.getValue().toString().c_str())); + + // send character to ConnectionServer for creation on the destination server + GenericValueTypeMessage login("TransferLoginCharacterToDestinationServer", transferReply.getValue()); + CentralServer::getInstance().sendToArbitraryLoginServer(login); + LOG("CustomerService", ("CharacterTransfer: Sending TransferLoginCharacterToDestinationServer to CentralServer (via LoginServer) (%s) for (%s)", transferReply.getValue().getDestinationGalaxy().c_str(), login.getValue().toString().c_str())); + } + } + else if(m.isType("ApplyTransferDataSuccess")) + { + const GenericValueTypeMessage success(ri); + + // send message to source galaxy (via LoginServer) to mark + // the source character as having been transferred to prevent + // all future login of the character + { + const GenericValueTypeMessage > msg("CtsCompletedForcharacter", std::make_pair(success.getValue().getSourceGalaxy(), success.getValue().getCharacterId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(msg)); + } + + // send the message back to the transfer server, which then + // sends a disable login request to the source central server, + // "removing" the account on the source galaxy. + if(success.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(success); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferDataSuccess from ConnectionServer. %s", success.getValue().toString().c_str())); + LOG("CustomerService", ("CharacterTransfer: Sending ToggleAvatarLoginStatus request to LoginServer")); + + const ToggleAvatarLoginStatus toggleLoginStatus(success.getValue().getSourceGalaxy(), success.getValue().getSourceStationId(), success.getValue().getCharacterId(), false); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(toggleLoginStatus)); + } + } + else if(m.isType("ApplyTransferDataFail")) + { + const GenericValueTypeMessage fail(ri); + + // send the message back to the transfer server, which then + // sends a delete request to the destination central server, + // "removing" the account on the destination galaxy. + if(fail.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(fail); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferDataFail from ConnectionServer. %s", fail.getValue().toString().c_str())); + LOG("CustomerService", ("CharacterTransfer: failed to apply transfer data. Deleting character on destination server. %s", fail.getValue().toString().c_str())); + + GenericValueTypeMessage const deleteCharacter("DeleteFailedTransfer", fail.getValue()); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(deleteCharacter)); + + GenericValueTypeMessage > const closeRequestSource("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getSourceGalaxy(), fail.getValue().getSourceStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestSource)); + + GenericValueTypeMessage > const closeRequestTarget("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getDestinationGalaxy(), fail.getValue().getDestinationStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestTarget)); + } + } + else if(m.isType("TransferCreateCharacterFailed")) + { + const GenericValueTypeMessage fail(ri); + + if(fail.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(fail); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Received TransferCreateCharacterFailed. %s", fail.getValue().toString().c_str())); + + GenericValueTypeMessage > const closeRequestSource("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getSourceGalaxy(), fail.getValue().getSourceStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestSource)); + + GenericValueTypeMessage > const closeRequestTarget("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getDestinationGalaxy(), fail.getValue().getDestinationStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestTarget)); + } + } + else if(m.isType("ReplyTransferDataFail")) + { + const GenericValueTypeMessage reply(ri); + + if(reply.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(reply); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Transfer failed: Failed to retrieve character data. %s", reply.getValue().toString().c_str())); + + GenericValueTypeMessage > const closeRequestSource("RequestTransferClosePseudoClientConnection", std::make_pair(reply.getValue().getSourceGalaxy(), reply.getValue().getSourceStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestSource)); + + GenericValueTypeMessage > const closeRequestTarget("RequestTransferClosePseudoClientConnection", std::make_pair(reply.getValue().getDestinationGalaxy(), reply.getValue().getDestinationStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestTarget)); + } + } + else if(m.isType("TransferFailGameServerClosedConnectionWithConnectionServer")) + { + const GenericValueTypeMessage fail(ri); + + if(fail.getValue().getTransferRequestSource() == TransferRequestMoveValidation::TRS_transfer_server) + { + CentralServer::getInstance().sendToTransferServer(fail); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Transfer failed: GameServer connection closed while transfer was in progress. %s", fail.getValue().toString().c_str())); + + GenericValueTypeMessage > const closeRequestSource("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getSourceGalaxy(), fail.getValue().getSourceStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestSource)); + + GenericValueTypeMessage > const closeRequestTarget("RequestTransferClosePseudoClientConnection", std::make_pair(fail.getValue().getDestinationGalaxy(), fail.getValue().getDestinationStationId())); + IGNORE_RETURN(CentralServer::getInstance().sendToArbitraryLoginServer(closeRequestTarget)); + } + } + else if(m.isType("AccountFeatureIdRequest")) + { + const AccountFeatureIdRequest msg(ri); + CentralServer::getInstance().sendToArbitraryLoginServer(msg); + } + else if(m.isType("AdjustAccountFeatureIdRequest")) + { + const AdjustAccountFeatureIdRequest msg(ri); + CentralServer::getInstance().sendToArbitraryLoginServer(msg); + } + else + { + ServerConnection::onReceive(message); + } +} + +//----------------------------------------------------------------------- + +ConnectionServerConnection * ConnectionServerConnection::getConnectionForAccount(unsigned int stationId) +{ + ConnectionServerConnection * result = 0; + std::map >::iterator f = s_pseudoClientConnectionMap.find(stationId); + if(f != s_pseudoClientConnectionMap.end()) + { + result = f->second.second; + } + return result; +} + +//----------------------------------------------------------------------- + +void ConnectionServerConnection::removeFromAccountConnectionMap(unsigned int stationId) +{ + std::map >::iterator f = s_pseudoClientConnectionMap.find(stationId); + if (f != s_pseudoClientConnectionMap.end()) + { + s_pseudoClientConnectionMap.erase(f); + } +} diff --git a/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.h b/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.h new file mode 100644 index 00000000..a39d8346 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConnectionServerConnection.h @@ -0,0 +1,253 @@ +// ConnectionServerConnection.h +// copyright 2001 Verant Interactive + +#ifndef _ConnectionServerConnection_H +#define _ConnectionServerConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +class ConnectionServerCommandChannel; + +//----------------------------------------------------------------------- + +class ConnectionServerConnection : public ServerConnection +{ +public: + + ConnectionServerConnection (const std::string & remoteAddress, const uint16 remotePort); + explicit ConnectionServerConnection (UdpConnectionMT *, TcpClient *); + ~ConnectionServerConnection (); + + const uint16 getChatServicePort () const; + const uint16 getVoiceChatServicePort () const; + const uint16 getCustomerServicePort () const; + const uint16 getClientServicePortPrivate () const; + const uint16 getClientServicePortPublic () const; + const uint16 getGameServicePort () const; + int getId() const; + const uint16 getPingPort () const; + int getConnectionServerNumber () const; + + const std::string & getGameServiceAddress () const; + const std::string & getClientServiceAddress () const; + const std::string & getChatServiceAddress () const; + const std::string & getVoiceChatServiceAddress () const; + const std::string & getCustomerServiceAddress () const; + + void onConnectionClosed (); + void onConnectionOpened (); + void onReceive (const Archive::ByteStream & message); + + void setPlayerCount (int count); + int getPlayerCount () const; + void setFreeTrialCount (int count); + int getFreeTrialCount () const; + void setEmptySceneCount (int count); + int getEmptySceneCount () const; + void setTutorialSceneCount (int count); + int getTutorialSceneCount () const; + void setFalconSceneCount (int count); + int getFalconSceneCount () const; + + static bool sendToPseudoClientConnection (unsigned int stationId, const GameNetworkMessage & message); + static ConnectionServerConnection * getConnectionForAccount(unsigned int stationId); + static void removeFromAccountConnectionMap(unsigned int stationId); + +private: + static int ms_connectionServerNumber; + + uint16 m_chatServicePort; + uint16 m_voiceChatServicePort; + uint16 m_csServicePort; + uint16 m_clientServicePortPrivate; + uint16 m_clientServicePortPublic; + uint16 m_gameServicePort; + int m_id; + uint16 m_pingPort; + int m_connectionServerNumber; + std::string m_gameServiceAddress; + int m_playerCount; + int m_freeTrialCount; + int m_emptySceneCount; + int m_tutorialSceneCount; + int m_falconSceneCount; + std::string m_clientServiceAddress; + std::string m_chatServiceAddress; + std::string m_voiceChatServiceAddress; + std::string m_customerServiceAddress; + + ConnectionServerConnection(const ConnectionServerConnection&); + ConnectionServerConnection& operator=(const ConnectionServerConnection&); +}; //lint !e1712 default constructor not defined + +//----------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getChatServicePort() const +{ + return m_chatServicePort; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getVoiceChatServicePort() const +{ + return m_voiceChatServicePort; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getCustomerServicePort() const +{ + return m_csServicePort; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getClientServicePortPrivate() const +{ + return m_clientServicePortPrivate; +} + +//----------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getClientServicePortPublic() const +{ + return m_clientServicePortPublic; +} + +//---------------------------------------------------------------------- +inline int ConnectionServerConnection::getId() const +{ + return m_id; +} +//---------------------------------------------------------------------- + +inline const unsigned short ConnectionServerConnection::getGameServicePort() const +{ + return m_gameServicePort; +} + +//----------------------------------------------------------------------- + +inline const std::string & ConnectionServerConnection::getGameServiceAddress() const +{ + return m_gameServiceAddress; +} + +//----------------------------------------------------------------------- + +inline const std::string & ConnectionServerConnection::getChatServiceAddress() const +{ + return m_chatServiceAddress; +} + +//----------------------------------------------------------------------- + +inline const std::string & ConnectionServerConnection::getVoiceChatServiceAddress() const +{ + return m_voiceChatServiceAddress; +} + +//----------------------------------------------------------------------- + +inline const std::string & ConnectionServerConnection::getCustomerServiceAddress() const +{ + return m_customerServiceAddress; +} + +//----------------------------------------------------------------------- + +inline void ConnectionServerConnection::setPlayerCount(int count) +{ + m_playerCount = count; +} + +//----------------------------------------------------------------------- + +inline int ConnectionServerConnection::getPlayerCount() const +{ + return m_playerCount; +} + +//---------------------------------------------------------------------- + +inline void ConnectionServerConnection::setFreeTrialCount(int count) +{ + m_freeTrialCount = count; +} + +//----------------------------------------------------------------------- + +inline int ConnectionServerConnection::getFreeTrialCount() const +{ + return m_freeTrialCount; +} + +//----------------------------------------------------------------------- + +inline void ConnectionServerConnection::setEmptySceneCount(int count) +{ + m_emptySceneCount = count; +} + +//----------------------------------------------------------------------- + +inline int ConnectionServerConnection::getEmptySceneCount() const +{ + return m_emptySceneCount; +} + +//----------------------------------------------------------------------- + +inline void ConnectionServerConnection::setTutorialSceneCount(int count) +{ + m_tutorialSceneCount = count; +} + +//----------------------------------------------------------------------- + +inline int ConnectionServerConnection::getTutorialSceneCount() const +{ + return m_tutorialSceneCount; +} + +//---------------------------------------------------------------------- + +inline void ConnectionServerConnection::setFalconSceneCount(int count) +{ + m_falconSceneCount = count; +} + +//----------------------------------------------------------------------- + +inline int ConnectionServerConnection::getFalconSceneCount() const +{ + return m_falconSceneCount; +} + +//---------------------------------------------------------------------- + +inline const std::string & ConnectionServerConnection::getClientServiceAddress() const +{ + return m_clientServiceAddress; +} + +//---------------------------------------------------------------------- + +inline const uint16 ConnectionServerConnection::getPingPort () const +{ + return m_pingPort; +} + +//---------------------------------------------------------------------- + +inline int ConnectionServerConnection::getConnectionServerNumber() const +{ + return m_connectionServerNumber; +} + +// ====================================================================== + +#endif // _ConnectionServerConnection_H diff --git a/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.cpp b/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.cpp new file mode 100644 index 00000000..6472faa5 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.cpp @@ -0,0 +1,132 @@ +// ConsoleCommandParser.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "ConsoleCommandParser.h" +#include "UnicodeUtils.h" + +#pragma warning(disable:4355) //'this' : used in base member initializer list + +//----------------------------------------------------------------------- + +namespace CommandNames +{ +#define MAKE_COMMAND(a) const char * const a = #a +#undef MAKE_COMMAND +} + +const CommandParser::CmdInfo cmds[] = +{ + {"transfer", 0, "", "send a request to the transfer server"}, + {"runState", 0, "", "Return the running state of the CentralServer. It should always return 'running'"}, + {"dbconnected", 0, "", "returns 1 if the database has connected"}, + {"getPlanetServersCount", 0, "", "returns the number of planet servers connected to the central server"}, + {"planet", 0, "", "send a request to the planet server"}, + {"hasPlanetServer", 1, "", "returns true if the CentralServer has a connection with the specified planet server"}, + {"", 0, "", ""} // this must be last +}; + + +//----------------------------------------------------------------------- + +ConsoleCommandParser::ConsoleCommandParser() : +CommandParser ("", 0, "...", "console commands", this) +{ + createDelegateCommands(cmds); +} + +//----------------------------------------------------------------------- + +ConsoleCommandParser::~ConsoleCommandParser() +{ +} + +//----------------------------------------------------------------------- + +bool ConsoleCommandParser::performParsing(const NetworkId & track, const StringVector_t & argv, const String_t & originalCommand, String_t & result, const CommandParser *) +{ + bool successResult = false; + if(argv.size() > 0) + { + if(isCommand(argv[0], "transfer")) + { + ConGenericMessage cm(Unicode::wideToNarrow(originalCommand), static_cast(track.getValue())); + CentralServer::getInstance().sendToTransferServer(cm); + } + if(isCommand(argv[0], "planet")) + { + if(argv.size() > 1) + { + ConGenericMessage cm(Unicode::wideToNarrow(originalCommand), static_cast(track.getValue())); + // which planet server? + std::string sceneName = Unicode::wideToNarrow(argv[1]); + + if(sceneName == "all") + { + CentralServer::getInstance().sendToAllPlanetServers(cm, true); + successResult = true; + } + else + { + if(CentralServer::getInstance().hasPlanetServer(sceneName)) + { + CentralServer::getInstance().sendToPlanetServer(sceneName, cm, true); + successResult = true; + } + } + } + } + + if(isCommand(argv[0], "runState")) + { + result += Unicode::narrowToWide("running"); + successResult = true; + } + if(isCommand(argv[0], "dbconnected")) + { + GameServerConnection * g = CentralServer::getInstance().getGameServer(CentralServer::getInstance().getDbProcessServerProcessId()); + if(g) + { + result += Unicode::narrowToWide("1"); + } + else + { + result += Unicode::narrowToWide("0"); + } + successResult = true; + } + if(isCommand(argv[0], "getPlanetServersCount")) + { + char countBuf[4]; + snprintf(countBuf, sizeof(countBuf), "%d", CentralServer::getInstance().getPlanetServersCount()); + countBuf[3] = 0; + result += Unicode::narrowToWide(countBuf); + successResult = true; + } + if(isCommand(argv[0], "hasPlanetServer")) + { + if(argv.size() > 1) + { + std::string sceneName = Unicode::wideToNarrow(argv[1]); + successResult = true; + if(CentralServer::getInstance().hasPlanetServer(sceneName)) + { + result += Unicode::narrowToWide("1"); + } + else + { + result += Unicode::narrowToWide("0"); + } + } + + } + } + return successResult; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.h b/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.h new file mode 100644 index 00000000..4ebf6387 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConsoleCommandParser.h @@ -0,0 +1,29 @@ +// ConsoleCommandParser.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConsoleCommandParser_H +#define _INCLUDED_ConsoleCommandParser_H + +//----------------------------------------------------------------------- + +#include "sharedCommandParser/CommandParser.h" + +//----------------------------------------------------------------------- + +class ConsoleCommandParser : public CommandParser +{ +public: + ConsoleCommandParser(); + ~ConsoleCommandParser(); + virtual bool performParsing(const NetworkId & userId, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser * node); + +private: + ConsoleCommandParser & operator = (const ConsoleCommandParser & rhs); + ConsoleCommandParser(const ConsoleCommandParser & source); +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConsoleCommandParser_H + diff --git a/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.cpp b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.cpp new file mode 100644 index 00000000..dcc6ea1d --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.cpp @@ -0,0 +1,65 @@ +// ConsoleCommandParserDatabase.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "CentralServer.h" +#include "ConsoleCommandParserDatabase.h" +#include "ConsoleConnection.h" +#include "GameServerConnection.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "UnicodeUtils.h" +#include "sharedLog/Log.h" + + +//----------------------------------------------------------------------- + +namespace CommandNames +{ +#define MAKE_COMMAND(a) const char * const a = #a + MAKE_COMMAND(database); +#undef MAKE_COMMAND +} + +/* +const CommandParser::CmdInfo cmds[] = +{ + {CommandNames::game, 1, "", ""}, + {"", 0, "", ""} // this must be last +}; +*/ + +//----------------------------------------------------------------------- + +ConsoleCommandParserDatabase::ConsoleCommandParserDatabase() : +CommandParser ("database", 0, "...", "console commands", 0) +{ +} + +//----------------------------------------------------------------------- + +ConsoleCommandParserDatabase::~ConsoleCommandParserDatabase() +{ +} + +//----------------------------------------------------------------------- + +bool ConsoleCommandParserDatabase::performParsing(const NetworkId & track, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser *) +{ + bool successResult = false; + + if(isCommand(argv[0], CommandNames::database)) + { + ConGenericMessage cm(Unicode::wideToNarrow(originalCommand), static_cast(track.getValue())); + CentralServer::getInstance().sendToDBProcess(cm, true); + successResult = true; + } + + return successResult; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.h b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.h new file mode 100644 index 00000000..025c626f --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserDatabase.h @@ -0,0 +1,29 @@ +// ConsoleCommandParserGame.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConsoleCommandParserDatabase_H +#define _INCLUDED_ConsoleCommandParserDatabase_H + +//----------------------------------------------------------------------- + +#include "sharedCommandParser/CommandParser.h" + +//----------------------------------------------------------------------- + +class ConsoleCommandParserDatabase : public CommandParser +{ +public: + ConsoleCommandParserDatabase(); + ~ConsoleCommandParserDatabase(); + virtual bool performParsing(const NetworkId & userId, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser * node); + +private: + ConsoleCommandParserDatabase & operator = (const ConsoleCommandParserDatabase & rhs); + ConsoleCommandParserDatabase(const ConsoleCommandParserDatabase & source); + +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConsoleCommandParserDatabase_H diff --git a/engine/server/application/CentralServer/src/shared/ConsoleCommandParserGame.cpp b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserGame.cpp new file mode 100644 index 00000000..3231ecff --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/ConsoleCommandParserGame.cpp @@ -0,0 +1,212 @@ +// ConsoleCommandParserGame.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCentralServer.h" +#include "CentralServer.h" +#include "ConsoleCommandParserGame.h" +#include "ConsoleConnection.h" +#include "GameServerConnection.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "UnicodeUtils.h" +#include "sharedLog/Log.h" + + +//----------------------------------------------------------------------- + +namespace CommandNames +{ +#define MAKE_COMMAND(a) const char * const a = #a + MAKE_COMMAND(game); +#undef MAKE_COMMAND +} + +/* +const CommandParser::CmdInfo cmds[] = +{ + {CommandNames::game, 1, "", ""}, + {"", 0, "", ""} // this must be last +}; +*/ + +//----------------------------------------------------------------------- + +ConsoleCommandParserGame::ConsoleCommandParserGame() : +CommandParser ("game", 0, "...", "console commands", 0) +{ +} + +//----------------------------------------------------------------------- + +ConsoleCommandParserGame::~ConsoleCommandParserGame() +{ +} + +//----------------------------------------------------------------------- + +bool ConsoleCommandParserGame::performParsing(const NetworkId & track, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser *) +{ + bool successResult = false; + + if(isCommand(argv[0], CommandNames::game)) + { + if(argv.size() > 1) + { + std::string cmd = Unicode::wideToNarrow(argv[1]); + if(cmd == "any") + { + // grab a random game server to execute this command + GameServerConnection * gameConn = CentralServer::getInstance().getRandomGameServer(); + if(gameConn) + { + ConGenericMessage cm(Unicode::wideToNarrow(originalCommand), static_cast(track.getValue())); + gameConn->send(cm, true); + successResult = true; + } + else + { + result += Unicode::narrowToWide("No game servers available to service request"); + ConsoleConnection::onCommandComplete(Unicode::wideToNarrow(result), static_cast(track.getValue())); + } + + } + else if(cmd == "kill") + { + // kill the game server process specified (by disconnecting it from central) + if(argv.size() > 2) + { + unsigned int pid; + sscanf(Unicode::wideToNarrow(argv[2]).c_str(), "%d", &pid); + GameServerConnection * gameConn = CentralServer::getInstance().getGameServer(pid); + if(gameConn) + { + gameConn->setDisconnectReason("Central ConsoleCommandParserGame kill command"); + gameConn->disconnect(); + successResult = true; + ConsoleConnection::onCommandComplete(Unicode::wideToNarrow(result), static_cast(track.getValue())); + + } + } + } + else if(cmd == "enumerate") + { + std::vector gameServers = CentralServer::getInstance().getGameServers(); + std::vector::const_iterator i; + for(i = gameServers.begin(); i != gameServers.end(); ++i) + { + char entry[256] = {"\0"}; + IGNORE_RETURN(snprintf(entry, sizeof(entry), "%lu, %lu, %s, %s\n", (*i)->getProcessId(), (*i)->getOsProcessId(), (*i)->getRemoteAddress().c_str(), (*i)->getSceneId().c_str())); + result += Unicode::narrowToWide(entry); + } + ConsoleConnection::onCommandComplete(Unicode::wideToNarrow(result), static_cast(track.getValue())); + } + else if( cmd == "abortShutdown" ) + { + LOG("ServerConsole", ("Received command to abort the current shutdown sequence.")); + CentralServer::getInstance().abortShutdownProcess(); + result += Unicode::narrowToWide("Instructing Central Server to abort shutdown sequence.\n"); + successResult = true; + ConsoleConnection::onCommandComplete(Unicode::wideToNarrow(result), static_cast(track.getValue())); + } + // starts the shutdown process + else if(cmd == "shutdown") + { + if( argv.size() > 4 ) + { + LOG("ServerConsole", ("Received command to shutdown the cluster.")); + uint32 timeToShutdown = strtoul(Unicode::wideToNarrow(argv[2]).c_str(), NULL, 10); + uint32 maxTime = strtoul(Unicode::wideToNarrow(argv[3]).c_str(), NULL, 10); + Unicode::String systemMessage = Unicode::narrowToWide(""); + for(unsigned int i = 4; i < argv.size(); ++i) + { + systemMessage += argv[i] + Unicode::narrowToWide(" "); + } + CentralServer::getInstance().startShutdownProcess(timeToShutdown, maxTime, systemMessage); + result += Unicode::narrowToWide("Instructing Central Server to begin shutdown sequence.\n"); + successResult = true; + ConsoleConnection::onCommandComplete(Unicode::wideToNarrow(result), static_cast(track.getValue())); + } + // failed to provide enough parameters + else + { + LOG("ServerConsole", ("Received an improperly formatted shutdown command.")); + result += Unicode::narrowToWide("Not enough parameters specified. Usage is \"game shutdown