@@ -1196,6 +1196,67 @@ redis_parse_info_response(char *response, zval *z_ret)
11961196 }
11971197}
11981198
1199+ static void
1200+ redis_parse_client_info (char * info , zval * z_ret )
1201+ {
1202+ char * p1 , * s1 = NULL ;
1203+
1204+ ZVAL_FALSE (z_ret );
1205+ if ((p1 = php_strtok_r (info , " " , & s1 )) != NULL ) {
1206+ array_init (z_ret );
1207+ do {
1208+ char * p ;
1209+ zend_uchar type ;
1210+ zend_long lval ;
1211+ double dval ;
1212+ if ((p = strchr (p1 , '=' )) != NULL ) {
1213+ type = is_numeric_string (p + 1 , strlen (p + 1 ), & lval , & dval , 0 );
1214+ switch (type ) {
1215+ case IS_LONG :
1216+ add_assoc_long_ex (z_ret , p1 , p - p1 , lval );
1217+ break ;
1218+ case IS_DOUBLE :
1219+ add_assoc_double_ex (z_ret , p1 , p - p1 , dval );
1220+ break ;
1221+ default :
1222+ add_assoc_string_ex (z_ret , p1 , p - p1 , p + 1 );
1223+ }
1224+ } else {
1225+ add_next_index_string (z_ret , p1 );
1226+ }
1227+ } while ((p1 = php_strtok_r (NULL , " " , & s1 )) != NULL );
1228+ }
1229+ }
1230+
1231+ static int
1232+ redis_client_info_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1233+ {
1234+ char * resp ;
1235+ int resp_len ;
1236+ zval z_ret ;
1237+
1238+ /* Make sure we can read the bulk response from Redis */
1239+ if ((resp = redis_sock_read (redis_sock , & resp_len )) == NULL ) {
1240+ RETVAL_FALSE ;
1241+ return FAILURE ;
1242+ }
1243+
1244+ /* Parse it out */
1245+ redis_parse_client_info (resp , & z_ret );
1246+
1247+ /* Free our response */
1248+ efree (resp );
1249+
1250+ /* Return or append depending if we're atomic */
1251+ if (IS_ATOMIC (redis_sock )) {
1252+ RETVAL_ZVAL (& z_ret , 0 , 1 );
1253+ } else {
1254+ add_next_index_zval (z_tab , & z_ret );
1255+ }
1256+
1257+ return SUCCESS ;
1258+ }
1259+
11991260/*
12001261 * Specialized handling of the CLIENT LIST output so it comes out in a simple way for PHP userland code
12011262 * to handle.
@@ -1210,11 +1271,13 @@ redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zva
12101271 if ((resp = redis_sock_read (redis_sock , & resp_len )) == NULL ) {
12111272 RETVAL_FALSE ;
12121273 return FAILURE ;
1274+ } else if (resp_len > 0 ) {
1275+ /* Parse it out */
1276+ redis_parse_client_list_response (resp , & z_ret );
1277+ } else {
1278+ array_init (& z_ret );
12131279 }
12141280
1215- /* Parse it out */
1216- redis_parse_client_list_response (resp , & z_ret );
1217-
12181281 /* Free our response */
12191282 efree (resp );
12201283
@@ -1231,42 +1294,16 @@ redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zva
12311294PHP_REDIS_API void
12321295redis_parse_client_list_response (char * response , zval * z_ret )
12331296{
1234- char * p1 , * s1 = NULL ;
1297+ char * p , * s = NULL ;
12351298
12361299 ZVAL_FALSE (z_ret );
1237- if ((p1 = php_strtok_r (response , _NL , & s1 )) != NULL ) {
1300+ if ((p = php_strtok_r (response , _NL , & s )) != NULL ) {
12381301 array_init (z_ret );
12391302 do {
1240- char * p2 , * s2 = NULL ;
12411303 zval z_sub ;
1242-
1243- ZVAL_FALSE (& z_sub );
1244- if ((p2 = php_strtok_r (p1 , " " , & s2 )) != NULL ) {
1245- array_init (& z_sub );
1246- do {
1247- char * p ;
1248- zend_uchar type ;
1249- zend_long lval ;
1250- double dval ;
1251- if ((p = strchr (p2 , '=' )) != NULL ) {
1252- type = is_numeric_string (p + 1 , strlen (p + 1 ), & lval , & dval , 0 );
1253- switch (type ) {
1254- case IS_LONG :
1255- add_assoc_long_ex (& z_sub , p2 , p - p2 , lval );
1256- break ;
1257- case IS_DOUBLE :
1258- add_assoc_double_ex (& z_sub , p2 , p - p2 , dval );
1259- break ;
1260- default :
1261- add_assoc_string_ex (& z_sub , p2 , p - p2 , p + 1 );
1262- }
1263- } else {
1264- add_next_index_string (& z_sub , p2 );
1265- }
1266- } while ((p2 = php_strtok_r (NULL , " " , & s2 )) != NULL );
1267- }
1304+ redis_parse_client_info (p , & z_sub );
12681305 add_next_index_zval (z_ret , & z_sub );
1269- } while ((p1 = php_strtok_r (NULL , _NL , & s1 )) != NULL );
1306+ } while ((p = php_strtok_r (NULL , _NL , & s )) != NULL );
12701307 }
12711308}
12721309
@@ -1629,6 +1666,54 @@ redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
16291666 return SUCCESS ;
16301667}
16311668
1669+ static int
1670+ redis_client_trackinginfo_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1671+ {
1672+ int numElems ;
1673+ zval z_ret ;
1674+
1675+ if (read_mbulk_header (redis_sock , & numElems ) < 0 ) {
1676+ if (IS_ATOMIC (redis_sock )) {
1677+ RETVAL_FALSE ;
1678+ } else {
1679+ add_next_index_bool (z_tab , 0 );
1680+ }
1681+ return FAILURE ;
1682+ }
1683+
1684+ array_init (& z_ret );
1685+ redis_read_multibulk_recursive (redis_sock , numElems , 0 , & z_ret );
1686+ array_zip_values_and_scores (redis_sock , & z_ret , 0 );
1687+
1688+ if (IS_ATOMIC (redis_sock )) {
1689+ RETVAL_ZVAL (& z_ret , 0 , 1 );
1690+ } else {
1691+ add_next_index_zval (z_tab , & z_ret );
1692+ }
1693+
1694+ return SUCCESS ;
1695+ }
1696+
1697+ PHP_REDIS_API int
1698+ redis_client_response (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1699+ {
1700+ if (ctx == NULL ) {
1701+ return redis_client_info_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1702+ } else if (ctx == PHPREDIS_CTX_PTR ) {
1703+ return redis_client_list_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1704+ } else if (ctx == PHPREDIS_CTX_PTR + 1 ) {
1705+ return redis_boolean_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1706+ } else if (ctx == PHPREDIS_CTX_PTR + 2 ) {
1707+ return redis_long_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1708+ } else if (ctx == PHPREDIS_CTX_PTR + 3 ) {
1709+ return redis_string_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1710+ } else if (ctx == PHPREDIS_CTX_PTR + 4 ) {
1711+ return redis_client_trackinginfo_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , NULL );
1712+ } else {
1713+ ZEND_ASSERT (!"memory corruption?" );
1714+ }
1715+ }
1716+
16321717/* Helper function to consume Redis stream message data. This is useful for
16331718 * multiple stream callers (e.g. XREAD[GROUP], and X[REV]RANGE handlers). */
16341719PHP_REDIS_API int
0 commit comments