@@ -140,6 +140,66 @@ static int session_gc_maxlifetime(void) {
140140 return value ;
141141}
142142
143+ /* Retrieve redis.session.compression from php.ini */
144+ static int session_compression_type (void ) {
145+ #ifdef HAVE_REDIS_LZF
146+ if (strncasecmp (INI_STR ("redis.session.compression" ), "lzf" , sizeof ("lzf" ) - 1 ) == 0 ) {
147+ return REDIS_COMPRESSION_LZF ;
148+ }
149+ #endif
150+ #ifdef HAVE_REDIS_ZSTD
151+ if (strncasecmp (INI_STR ("redis.session.compression" ), "zstd" , sizeof ("zstd" ) - 1 ) == 0 ) {
152+ return REDIS_COMPRESSION_ZSTD ;
153+ }
154+ #endif
155+ #ifdef HAVE_REDIS_LZ4
156+ if (strncasecmp (INI_STR ("redis.session.compression" ), "lz4" , sizeof ("lz4" ) - 1 ) == 0 ) {
157+ return REDIS_COMPRESSION_LZ4 ;
158+ }
159+ #endif
160+ if (strncasecmp (INI_STR ("redis.session.compression" ), "none" , sizeof ("none" ) - 1 ) == 0 ) {
161+ return REDIS_COMPRESSION_NONE ;
162+ }
163+
164+ // E_NOTICE when outside of valid values
165+ php_error_docref (NULL , E_NOTICE , "redis.session.compression is outside of valid values, disabling" );
166+
167+ return REDIS_COMPRESSION_NONE ;
168+ }
169+
170+ /* Helper to compress session data */
171+ static int
172+ session_compress_data (RedisSock * redis_sock , char * data , size_t len ,
173+ char * * compressed_data , size_t * compressed_len )
174+ {
175+ if (redis_sock -> compression ) {
176+ if (redis_compress (redis_sock , compressed_data , compressed_len , data , len )) {
177+ return 1 ;
178+ }
179+ }
180+
181+ * compressed_data = data ;
182+ * compressed_len = len ;
183+
184+ return 0 ;
185+ }
186+
187+ /* Helper to uncompress session data */
188+ static int
189+ session_uncompress_data (RedisSock * redis_sock , char * data , size_t len ,
190+ char * * decompressed_data , size_t * decompressed_len ) {
191+ if (redis_sock -> compression ) {
192+ if (redis_uncompress (redis_sock , decompressed_data , decompressed_len , data , len )) {
193+ return 1 ;
194+ }
195+ }
196+
197+ * decompressed_data = data ;
198+ * decompressed_len = len ;
199+
200+ return 0 ;
201+ }
202+
143203/* Send a command to Redis. Returns byte count written to socket (-1 on failure) */
144204static int redis_simple_cmd (RedisSock * redis_sock , char * cmd , int cmdlen ,
145205 char * * reply , int * replylen )
@@ -478,6 +538,9 @@ PS_OPEN_FUNC(redis)
478538 redis_sock -> dbNumber = db ;
479539 }
480540
541+ redis_sock -> compression = session_compression_type ();
542+ redis_sock -> compression_level = INI_INT ("redis.session.compression_level" );
543+
481544 if (Z_TYPE (context ) == IS_ARRAY ) {
482545 redis_sock_set_stream_context (redis_sock , & context );
483546 }
@@ -685,10 +748,10 @@ PS_UPDATE_TIMESTAMP_FUNC(redis)
685748 */
686749PS_READ_FUNC (redis )
687750{
688- char * resp , * cmd ;
689- int resp_len , cmd_len ;
751+ char * resp , * cmd , * compressed_buf ;
752+ int resp_len , cmd_len , compressed_free ;
690753 const char * skey = ZSTR_VAL (key );
691- size_t skeylen = ZSTR_LEN (key );
754+ size_t skeylen = ZSTR_LEN (key ), compressed_len ;
692755
693756 if (!skeylen ) return FAILURE ;
694757
@@ -737,8 +800,13 @@ PS_READ_FUNC(redis)
737800 if (resp_len < 0 ) {
738801 * val = ZSTR_EMPTY_ALLOC ();
739802 } else {
740- * val = zend_string_init (resp , resp_len , 0 );
803+ compressed_free = session_uncompress_data (redis_sock , resp , resp_len , & compressed_buf , & compressed_len );
804+ * val = zend_string_init (compressed_buf , compressed_len , 0 );
805+ if (compressed_free ) {
806+ efree (compressed_buf ); // Free the buffer allocated by redis_uncompress
807+ }
741808 }
809+
742810 efree (resp );
743811
744812 return SUCCESS ;
@@ -749,10 +817,10 @@ PS_READ_FUNC(redis)
749817 */
750818PS_WRITE_FUNC (redis )
751819{
752- char * cmd , * response ;
753- int cmd_len , response_len ;
820+ char * cmd , * response , * compressed_buf = NULL ;
821+ int cmd_len , response_len , compressed_free = 0 ;
754822 const char * skey = ZSTR_VAL (key ), * sval = ZSTR_VAL (val );
755- size_t skeylen = ZSTR_LEN (key ), svallen = ZSTR_LEN (val );
823+ size_t skeylen = ZSTR_LEN (key ), svallen = ZSTR_LEN (val ), compressed_len = 0 ;
756824
757825 if (!skeylen ) return FAILURE ;
758826
@@ -767,8 +835,15 @@ PS_WRITE_FUNC(redis)
767835 /* send SET command */
768836 zend_string * session = redis_session_key (redis_sock , skey , skeylen );
769837
838+ compressed_free = session_compress_data (redis_sock , ZSTR_VAL (val ), ZSTR_LEN (val ), & compressed_buf , & compressed_len );
839+ sval = compressed_buf ;
840+ svallen = compressed_len ;
841+
770842 cmd_len = REDIS_SPPRINTF (& cmd , "SETEX" , "Sds" , session , session_gc_maxlifetime (), sval , svallen );
771843 zend_string_release (session );
844+ if (compressed_free ) {
845+ efree (compressed_buf );
846+ }
772847
773848 if (!write_allowed (redis_sock , & pool -> lock_status )) {
774849 php_error_docref (NULL , E_WARNING , "Unable to write session: session lock not held" );
@@ -942,6 +1017,9 @@ PS_OPEN_FUNC(rediscluster) {
9421017 c -> flags -> prefix = CLUSTER_DEFAULT_PREFIX ();
9431018 }
9441019
1020+ c -> flags -> compression = session_compression_type ();
1021+ c -> flags -> compression_level = INI_INT ("redis.session.compression_level" );
1022+
9451023 redis_sock_set_auth (c -> flags , user , pass );
9461024
9471025 if ((context = REDIS_HASH_STR_FIND_TYPE_STATIC (ht_conf , "stream" , IS_ARRAY )) != NULL ) {
@@ -1142,8 +1220,9 @@ PS_UPDATE_TIMESTAMP_FUNC(rediscluster) {
11421220PS_READ_FUNC (rediscluster ) {
11431221 redisCluster * c = PS_GET_MOD_DATA ();
11441222 clusterReply * reply ;
1145- char * cmd , * skey ;
1146- int cmdlen , skeylen , free_flag ;
1223+ char * cmd , * skey , * compressed_buf ;
1224+ int cmdlen , skeylen , free_flag , compressed_free ;
1225+ size_t compressed_len ;
11471226 short slot ;
11481227
11491228 /* Set up our command and slot information */
@@ -1181,7 +1260,11 @@ PS_READ_FUNC(rediscluster) {
11811260 if (reply -> str == NULL ) {
11821261 * val = ZSTR_EMPTY_ALLOC ();
11831262 } else {
1184- * val = zend_string_init (reply -> str , reply -> len , 0 );
1263+ compressed_free = session_uncompress_data (c -> flags , reply -> str , reply -> len , & compressed_buf , & compressed_len );
1264+ * val = zend_string_init (compressed_buf , compressed_len , 0 );
1265+ if (compressed_free ) {
1266+ efree (compressed_buf ); // Free the buffer allocated by redis_uncompress
1267+ }
11851268 }
11861269
11871270 free_flag = 1 ;
@@ -1198,16 +1281,24 @@ PS_READ_FUNC(rediscluster) {
11981281PS_WRITE_FUNC (rediscluster ) {
11991282 redisCluster * c = PS_GET_MOD_DATA ();
12001283 clusterReply * reply ;
1201- char * cmd , * skey ;
1202- int cmdlen , skeylen ;
1284+ char * cmd , * skey , * compressed_buf = NULL , * sval = ZSTR_VAL ( val ) ;
1285+ int cmdlen , skeylen , compressed_free = 0 , svallen = ZSTR_LEN ( val ) ;
12031286 short slot ;
1287+ size_t compressed_len = 0 ;
1288+
1289+ compressed_free = session_compress_data (c -> flags , sval , svallen , & compressed_buf , & compressed_len );
1290+ sval = compressed_buf ;
1291+ svallen = compressed_len ;
12041292
12051293 /* Set up command and slot info */
12061294 skey = cluster_session_key (c , ZSTR_VAL (key ), ZSTR_LEN (key ), & skeylen , & slot );
12071295 cmdlen = redis_spprintf (NULL , NULL , & cmd , "SETEX" , "sds" , skey ,
12081296 skeylen , session_gc_maxlifetime (),
1209- ZSTR_VAL ( val ), ZSTR_LEN ( val ) );
1297+ sval , svallen );
12101298 efree (skey );
1299+ if (compressed_free ) {
1300+ efree (compressed_buf );
1301+ }
12111302
12121303 /* Attempt to send command */
12131304 c -> readonly = 0 ;
0 commit comments