11#include " datapack.hpp"
2+ #include " protocol.hpp"
23
34#include < GarrysMod/Lua/Helpers.hpp>
45#include < GarrysMod/FunctionPointers.hpp>
1011#include < iclient.h>
1112#include < eiface.h>
1213#include < LzmaLib.h>
13- #include < 7zCrc.h>
14+ #include < Sha256.h>
15+
16+ #include < vector>
17+ #include < array>
1418
1519class GModDataPack ;
1620
@@ -100,24 +104,30 @@ namespace DataPack
100104 int GModDataPackProxy::lua_receiving_client = -1 ;
101105 const char GModDataPackProxy::lua_file_hook_name[] = " SendLuaFileToClient" ;
102106
103- static size_t Compress ( const std::string &input, std::vector<uint8_t > &output, size_t offset )
107+ inline size_t MaximumCompressedSize ( const std::string &input )
108+ {
109+ const size_t input_size = input.size ( ) + 1 ;
110+ return input_size + input_size / 3 + 128 ;
111+ }
112+
113+ static std::vector<uint8_t > Compress ( const std::string &input )
104114 {
105115 // The data is written:
106116 // 5 bytes: props
107117 // 8 bytes: uncompressed size
108118 // the rest: the actual data
109- size_t iInputLength = input.size ( ) + 1 ;
119+ const size_t iInputLength = input.size ( ) + 1 ;
110120 size_t props_size = LZMA_PROPS_SIZE;
111121 size_t iDestSize = iInputLength + iInputLength / 3 + 128 ;
112122
113- output. resize ( offset + iDestSize + LZMA_PROPS_SIZE + 8 );
123+ std::vector< uint8_t > output ( iDestSize + LZMA_PROPS_SIZE + 8 , 0 );
114124
115125 const uint8_t *pInputData = reinterpret_cast <const uint8_t *>( input.c_str ( ) );
116- uint8_t *pPropStart = reinterpret_cast < uint8_t *>( & output[offset] );
126+ uint8_t *pPropStart = output. data ( );
117127 uint8_t *pSizeStart = pPropStart + LZMA_PROPS_SIZE;
118128 uint8_t *pBodyStart = pSizeStart + 8 ;
119129
120- int res = LzmaCompress (
130+ const int res = LzmaCompress (
121131 pBodyStart, &iDestSize, // Dest out
122132 pInputData, iInputLength, // Input in
123133 pPropStart, &props_size, // Props out
@@ -131,10 +141,10 @@ namespace DataPack
131141 );
132142
133143 if ( props_size != LZMA_PROPS_SIZE )
134- return 0 ;
144+ return { } ;
135145
136146 if ( res != SZ_OK )
137- return 0 ;
147+ return { } ;
138148
139149 // Write our 8 byte LE size
140150 pSizeStart[0 ] = iInputLength & 0xFF ;
@@ -146,55 +156,53 @@ namespace DataPack
146156 pSizeStart[6 ] = 0 ;
147157 pSizeStart[7 ] = 0 ;
148158
149- output.resize ( offset + iDestSize + LZMA_PROPS_SIZE + 8 );
150- return iDestSize + LZMA_PROPS_SIZE + 8 ;
159+ output.resize ( iDestSize + LZMA_PROPS_SIZE + 8 );
160+ return output ;
151161 }
152162
153163 inline void SendLuaFile ( int client, int fileID, const std::string &substitute, bool autorefresh )
154164 {
155- std::vector<uint8_t > data;
165+ const char *path = client_lua_files->GetString ( fileID );
166+
167+ // Type 1b + SHA256 32b + compressed substitute Xb + alignment 4b
168+ int min_buffer_size = 1 + 32 + MaximumCompressedSize ( substitute ) + 4 ;
156169
157- const char *path = nullptr ;
158- size_t pathlen = 0 ;
159170 if ( autorefresh )
160171 {
161- path = client_lua_files->GetString ( fileID );
162- pathlen = std::strlen ( path ) + 1 ;
163- data.resize ( 1 + pathlen + 4 + 4 );
172+ if ( path == nullptr )
173+ return ;
174+
175+ // (File path + NUL) Xb + (SHA256 + compressed substitute) size 4b
176+ min_buffer_size += std::strlen ( path ) + 1 + 4 ;
164177 }
165178 else
166- data.resize ( 1 + 2 + 4 );
179+ // File ID 2b
180+ min_buffer_size += 2 ;
167181
168- size_t offset = 0 ;
182+ std::vector<uint8_t > buffer ( min_buffer_size, 0 );
183+ bf_write writer ( " sourcenet SendLuaFile writer" , buffer.data ( ), buffer.size ( ) );
169184
170- uint8_t msgType = autorefresh ? 1 : 4 ; // message type
171- std::memcpy ( &data[offset], &msgType, 1 );
172- ++offset;
185+ writer.WriteByte ( autorefresh ? 1 : 4 );
173186
174187 if ( autorefresh )
175- {
176- std::memcpy ( &data[offset], path, pathlen );
177- offset += pathlen;
178- }
188+ writer.WriteString ( path );
179189 else
180- {
181- std::memcpy ( &data[offset], &fileID, 2 );
182- offset += 2 ;
183- }
190+ writer.WriteWord ( fileID );
184191
192+ const std::vector<uint8_t > compressed_buffer = Compress ( substitute );
185193 if ( autorefresh )
186- {
187- size_t compressedLen = Compress ( substitute, data, offset + 8 ) + 4 ;
188- std::memcpy ( &data[offset], &compressedLen, 4 );
189- offset += 4 ;
190- }
191- else
192- Compress ( substitute, data, offset + 4 );
194+ writer.WriteUBitLong ( 32 + compressed_buffer.size ( ), 32 );
193195
194- uint32_t crc32 = CrcCalc ( &substitute[0 ], substitute.size ( ) + 1 );
195- std::memcpy ( &data[offset], &crc32, 4 );
196+ CSha256 sha256;
197+ Sha256_Init ( &sha256 );
198+ Sha256_Update ( &sha256, reinterpret_cast <const uint8_t *>( substitute.c_str ( ) ), substitute.size ( ) + 1 );
199+ std::array<uint8_t , 32 > sha256_buffer { };
200+ Sha256_Final ( &sha256, sha256_buffer.data ( ) );
201+ writer.WriteBytes ( sha256_buffer.data ( ), sha256_buffer.size ( ) );
196202
197- global::engine_server->GMOD_SendToClient ( client, &data[0 ], static_cast <int >( 8 * data.size ( ) ) );
203+ writer.WriteBytes ( compressed_buffer.data ( ), static_cast <int >( compressed_buffer.size ( ) ) );
204+
205+ global::engine_server->GMOD_SendToClient ( client, writer.GetData ( ), writer.GetNumBitsWritten ( ) );
198206 }
199207
200208 LUA_FUNCTION_STATIC ( SendLuaFile )
@@ -250,8 +258,6 @@ namespace DataPack
250258
251259 void Initialize ( GarrysMod::Lua::ILuaBase *LUA )
252260 {
253- CrcGenerateTable ( );
254-
255261 LUA->PushCFunction ( GModDataPackProxy::EnableLuaFileValidation );
256262 LUA->SetField ( GarrysMod::Lua::INDEX_GLOBAL, " EnableLuaFileValidation" );
257263
0 commit comments