1717#include "php_memcached.h"
1818#include "php_memcached_private.h"
1919#include "php_memcached_server.h"
20+ #include "php_network.h"
2021
2122#include <event2/listener.h>
2223
23- #undef NDEBUG
24- #undef _NDEBUG
2524#include <assert.h>
2625
2726#define MEMC_GET_CB (cb_type ) (MEMC_SERVER_G(callbacks)[cb_type])
@@ -58,9 +57,9 @@ typedef struct {
5857static
5958long s_invoke_php_callback (php_memc_server_cb_t * cb , zval * params , ssize_t param_count )
6059{
61- zval * retval = NULL ;
60+ zval retval ;
6261
63- cb -> fci .retval = retval ;
62+ cb -> fci .retval = & retval ;
6463 cb -> fci .params = params ;
6564 cb -> fci .param_count = param_count ;
6665#if PHP_VERSION_ID < 80000
@@ -73,7 +72,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t para
7372 efree (buf );
7473 }
7574
76- return retval == NULL ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long (retval );
75+ return Z_ISUNDEF ( retval ) ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long (& retval );
7776}
7877
7978// memcached protocol callbacks
@@ -96,6 +95,7 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke
9695 ZVAL_LONG (& zflags , flags );
9796 ZVAL_LONG (& zexptime , exptime );
9897 ZVAL_NULL (& zresult_cas );
98+ ZVAL_MAKE_REF (& zresult_cas );
9999
100100 ZVAL_COPY (& params [0 ], & zcookie );
101101 ZVAL_COPY (& params [1 ], & zkey );
@@ -142,6 +142,7 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event
142142 ZVAL_STRINGL (& zvalue , data , data_len );
143143 ZVAL_DOUBLE (& zcas , cas );
144144 ZVAL_NULL (& zresult_cas );
145+ ZVAL_MAKE_REF (& zresult_cas );
145146
146147 ZVAL_COPY (& params [0 ], & zcookie );
147148 ZVAL_COPY (& params [1 ], & zkey );
@@ -198,11 +199,13 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con
198199 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
199200
200201 ZVAL_STRINGL (& zkey , key , key_len );
201- ZVAL_LONG (& zdelta , (long ) delta );
202- ZVAL_LONG (& zinital , (long ) initial );
203- ZVAL_LONG (& zexpiration , (long ) expiration );
202+ ZVAL_LONG (& zdelta , (zend_long ) delta );
203+ ZVAL_LONG (& zinital , (zend_long ) initial );
204+ ZVAL_LONG (& zexpiration , (zend_long ) expiration );
204205 ZVAL_LONG (& zresult , 0 );
206+ ZVAL_MAKE_REF (& zresult );
205207 ZVAL_NULL (& zresult_cas );
208+ ZVAL_MAKE_REF (& zresult_cas );
206209
207210 ZVAL_COPY (& params [0 ], & zcookie );
208211 ZVAL_COPY (& params [1 ], & zkey );
@@ -296,6 +299,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe
296299 }
297300
298301 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
302+ ZVAL_LONG (& zwhen , when );
299303
300304 ZVAL_COPY (& params [0 ], & zcookie );
301305 ZVAL_COPY (& params [1 ], & zwhen );
@@ -322,6 +326,13 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k
322326 }
323327
324328 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
329+ ZVAL_STRINGL (& zkey , key , key_len );
330+ ZVAL_NULL (& zvalue );
331+ ZVAL_MAKE_REF (& zvalue );
332+ ZVAL_NULL (& zflags );
333+ ZVAL_MAKE_REF (& zflags );
334+ ZVAL_NULL (& zresult_cas );
335+ ZVAL_MAKE_REF (& zresult_cas );
325336
326337 ZVAL_COPY (& params [0 ], & zcookie );
327338 ZVAL_COPY (& params [1 ], & zkey );
@@ -436,11 +447,12 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c
436447 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
437448
438449 ZVAL_STRINGL (& zkey , key , key_len );
439- ZVAL_STRINGL (& zdata , (( char * ) data ), ( int ) data_len );
440- ZVAL_LONG (& zflags , (long ) flags );
441- ZVAL_LONG (& zexpiration , (long ) expiration );
450+ ZVAL_STRINGL (& zdata , data , data_len );
451+ ZVAL_LONG (& zflags , (zend_long ) flags );
452+ ZVAL_LONG (& zexpiration , (zend_long ) expiration );
442453 ZVAL_DOUBLE (& zcas , (double ) cas );
443454 ZVAL_NULL (& zresult_cas );
455+ ZVAL_MAKE_REF (& zresult_cas );
444456
445457 ZVAL_COPY (& params [0 ], & zcookie );
446458 ZVAL_COPY (& params [1 ], & zkey );
@@ -494,41 +506,65 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void *
494506{
495507 zval params [3 ];
496508 protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ;
497- zval zcookie , zkey , zbody ;
509+ zval zcookie , zkey , zstats ;
498510
499511 if (!MEMC_HAS_CB (MEMC_SERVER_ON_STAT )) {
500512 return retval ;
501513 }
502514
503515 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
504516
505- ZVAL_STRINGL (& zkey , key , key_len );
506- ZVAL_NULL (& zbody );
517+ if (key && key_len ) {
518+ ZVAL_STRINGL (& zkey , key , key_len );
519+ } else {
520+ ZVAL_NULL (& zkey );
521+ }
522+ array_init (& zstats );
523+ ZVAL_MAKE_REF (& zstats );
507524
508525 ZVAL_COPY (& params [0 ], & zcookie );
509526 ZVAL_COPY (& params [1 ], & zkey );
510- ZVAL_COPY (& params [2 ], & zbody );
527+ ZVAL_COPY (& params [2 ], & zstats );
511528
512529 retval = s_invoke_php_callback (& MEMC_GET_CB (MEMC_SERVER_ON_STAT ), params , 3 );
513530
514531 if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS ) {
515- if (Z_TYPE (zbody ) == IS_NULL ) {
516- retval = response_handler (cookie , NULL , 0 , NULL , 0 );
532+ zval * zarray = & zstats ;
533+ zend_string * key ;
534+ zend_long idx ;
535+ zval * val ;
536+
537+ ZVAL_DEREF (zarray );
538+ if (Z_TYPE_P (zarray ) != IS_ARRAY ) {
539+ convert_to_array (zarray );
517540 }
518- else {
519- if (Z_TYPE (zbody ) != IS_STRING ) {
520- convert_to_string (& zbody );
541+
542+ ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P (zarray ), idx , key , val )
543+ {
544+ zend_string * val_str = zval_get_string (val );
545+
546+ if (key ) {
547+ retval = response_handler (cookie , key -> val , key -> len , val_str -> val , val_str -> len );
548+ } else {
549+ char buf [0x20 ], * ptr , * end = & buf [sizeof (buf ) - 1 ];
550+ ptr = zend_print_long_to_buf (end , idx );
551+ retval = response_handler (cookie , ptr , end - ptr , val_str -> val , val_str -> len );
552+ }
553+ zend_string_release (val_str );
554+
555+ if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS ) {
556+ break ;
521557 }
522- retval = response_handler (cookie , key , key_len , Z_STRVAL (zbody ), (uint32_t ) Z_STRLEN (zbody ));
523558 }
559+ ZEND_HASH_FOREACH_END ();
524560 }
525561
526562 zval_ptr_dtor (& params [0 ]);
527563 zval_ptr_dtor (& params [1 ]);
528564 zval_ptr_dtor (& params [2 ]);
529565 zval_ptr_dtor (& zcookie );
530566 zval_ptr_dtor (& zkey );
531- zval_ptr_dtor (& zbody );
567+ zval_ptr_dtor (& zstats );
532568 return retval ;
533569}
534570
@@ -547,12 +583,12 @@ protocol_binary_response_status s_version_handler (const void *cookie,
547583 MEMC_MAKE_ZVAL_COOKIE (zcookie , cookie );
548584
549585 ZVAL_NULL (& zversion );
586+ ZVAL_MAKE_REF (& zversion );
550587
551588 ZVAL_COPY (& params [0 ], & zcookie );
552589 ZVAL_COPY (& params [1 ], & zversion );
553590
554591 retval = s_invoke_php_callback (& MEMC_GET_CB (MEMC_SERVER_ON_VERSION ), params , 2 );
555-
556592 if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS ) {
557593 if (Z_TYPE (zversion ) != IS_STRING ) {
558594 convert_to_string (& zversion );
@@ -581,31 +617,25 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg)
581617
582618 if (!client -> on_connect_invoked ) {
583619 if (MEMC_HAS_CB (MEMC_SERVER_ON_CONNECT )) {
584- zval zremoteip , zremoteport ;
585- zval params [2 ];
620+ zend_string * zremoteaddr_str ;
621+ zval zremoteaddr ;
622+ zval params [1 ];
586623 protocol_binary_response_status retval ;
587624
588- struct sockaddr_in addr_in ;
589- socklen_t addr_in_len = sizeof (addr_in );
625+ ZVAL_NULL (& zremoteaddr );
590626
591- if (getpeername (fd , (struct sockaddr * ) & addr_in , & addr_in_len ) == 0 ) {
592- ZVAL_STRING (& zremoteip , inet_ntoa (addr_in .sin_addr ));
593- ZVAL_LONG (& zremoteport , ntohs (addr_in .sin_port ));
627+ if (SUCCESS == php_network_get_peer_name (fd , & zremoteaddr_str , NULL , NULL )) {
628+ ZVAL_STR (& zremoteaddr , zremoteaddr_str );
594629 } else {
595630 php_error_docref (NULL , E_WARNING , "getpeername failed: %s" , strerror (errno ));
596- ZVAL_NULL (& zremoteip );
597- ZVAL_NULL (& zremoteport );
598631 }
599632
600- ZVAL_COPY (& params [0 ], & zremoteip );
601- ZVAL_COPY (& params [1 ], & zremoteport );
633+ ZVAL_COPY (& params [0 ], & zremoteaddr );
602634
603- retval = s_invoke_php_callback (& MEMC_GET_CB (MEMC_SERVER_ON_CONNECT ), params , 2 );
635+ retval = s_invoke_php_callback (& MEMC_GET_CB (MEMC_SERVER_ON_CONNECT ), params , 1 );
604636
605637 zval_ptr_dtor (& params [0 ]);
606- zval_ptr_dtor (& params [1 ]);
607- zval_ptr_dtor (& zremoteip );
608- zval_ptr_dtor (& zremoteport );
638+ zval_ptr_dtor (& zremoteaddr );
609639
610640 if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS ) {
611641 memcached_protocol_client_destroy (client -> protocol_client );
@@ -714,22 +744,20 @@ php_memc_proto_handler_t *php_memc_proto_handler_new ()
714744}
715745
716746static
717- evutil_socket_t s_create_listening_socket (const char * spec )
747+ evutil_socket_t s_create_listening_socket (const zend_string * spec )
718748{
719749 evutil_socket_t sock ;
720750 struct sockaddr_storage addr ;
721- int addr_len ;
722-
751+ socklen_t addr_len ;
723752 int rc ;
724753
725754 addr_len = sizeof (struct sockaddr );
726- rc = evutil_parse_sockaddr_port (spec , (struct sockaddr * ) & addr , & addr_len );
727- if (rc != 0 ) {
728- php_error_docref (NULL , E_WARNING , "Failed to parse bind address" );
755+ if (SUCCESS != php_network_parse_network_address_with_port (spec -> val , spec -> len , (struct sockaddr * ) & addr , & addr_len )) {
756+ php_error_docref (NULL , E_WARNING , "Failed to parse bind address: %s" , spec -> val );
729757 return -1 ;
730758 }
731759
732- sock = socket (AF_INET , SOCK_STREAM , 0 );
760+ sock = socket (addr . ss_family , SOCK_STREAM , 0 );
733761 if (sock < 0 ) {
734762 php_error_docref (NULL , E_WARNING , "socket failed: %s" , strerror (errno ));
735763 return -1 ;
@@ -770,7 +798,7 @@ evutil_socket_t s_create_listening_socket (const char *spec)
770798zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t * handler , zend_string * address )
771799{
772800 struct event * accept_event ;
773- evutil_socket_t sock = s_create_listening_socket (address -> val );
801+ evutil_socket_t sock = s_create_listening_socket (address );
774802
775803 if (sock == -1 ) {
776804 return 0 ;
0 commit comments