Skip to content

Commit 9cd4a01

Browse files
authored
Merge pull request #474 from m6w6/fix-memcachedserver
fix MemcachedServer
2 parents e6df8ab + 10f4497 commit 9cd4a01

8 files changed

+515
-51
lines changed

package.xml

+4-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ Fixes
173173
<file role='test' name='stats_hang.phpt'/>
174174
<file role='test' name='default_behavior.phpt'/>
175175
<file role='test' name='reset_keyprefix.phpt'/>
176-
<file role='test' name='session_lock-php71.phpt'/>
176+
<file role='test' name='session_lock-php71.phpt'/>
177+
<file role='test' name='server.inc'/>
178+
<file role='test' name='server.php'/>
179+
<file role='test' name='memcachedserver.phpt'/>
177180
</dir>
178181
</dir>
179182
</contents>

php_memcached.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -3519,6 +3519,8 @@ static
35193519
void php_memc_server_free_storage(zend_object *object)
35203520
{
35213521
php_memc_server_t *intern = php_memc_server_fetch_object(object);
3522+
3523+
php_memc_proto_handler_destroy(&intern->handler);
35223524
zend_object_std_dtor(&intern->zo);
35233525
}
35243526

@@ -3532,6 +3534,7 @@ zend_object *php_memc_server_new(zend_class_entry *ce)
35323534
object_properties_init(&intern->zo, ce);
35333535

35343536
intern->zo.handlers = &memcached_server_object_handlers;
3537+
intern->handler = php_memc_proto_handler_new();
35353538

35363539
return &intern->zo;
35373540
}
@@ -3921,7 +3924,6 @@ static
39213924
PHP_GINIT_FUNCTION(php_memcached)
39223925
{
39233926
#ifdef HAVE_MEMCACHED_SESSION
3924-
39253927
php_memcached_globals->session.lock_enabled = 0;
39263928
php_memcached_globals->session.lock_wait_max = 150;
39273929
php_memcached_globals->session.lock_wait_min = 150;
@@ -3940,8 +3942,12 @@ PHP_GINIT_FUNCTION(php_memcached)
39403942
php_memcached_globals->session.persistent_enabled = 0;
39413943
php_memcached_globals->session.sasl_username = NULL;
39423944
php_memcached_globals->session.sasl_password = NULL;
3945+
#endif
39433946

3947+
#ifdef HAVE_MEMCACHED_PROTOCOL
3948+
memset(&php_memcached_globals->server, 0, sizeof(php_memcached_globals->server));
39443949
#endif
3950+
39453951
php_memcached_globals->memc.serializer_name = NULL;
39463952
php_memcached_globals->memc.serializer_type = SERIALIZER_DEFAULT;
39473953
php_memcached_globals->memc.compression_name = NULL;

php_memcached_server.c

+74-46
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@
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 {
5857
static
5958
long 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

716746
static
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)
770798
zend_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;

server-example/run-server.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
$server = new MemcachedServer();
44

55
$server->on (Memcached::ON_CONNECT,
6-
function ($remote_ip, $remote_port) {
7-
echo "Incoming connection from {$remote_ip}:{$remote_port}" . PHP_EOL;
6+
function ($remote_addr) {
7+
echo "Incoming connection from {$remote_addr}" . PHP_EOL;
88
return Memcached::RESPONSE_SUCCESS;
99
});
1010

@@ -89,4 +89,4 @@ function ($client_id) {
8989
return Memcached::RESPONSE_SUCCESS;
9090
});
9191

92-
$server->run ("127.0.0.1:3434");
92+
$server->run ("127.0.0.1:3434");

0 commit comments

Comments
 (0)