php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #59264 add support for unix domain sockets (unix://)
Submitted: 2010-06-16 08:45 UTC Modified: 2010-06-16 08:46 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: alexander dot krause at ed-solutions dot de Assigned:
Status: Open Package: memcached (PECL)
PHP Version: 5.3.2 OS: Gentoo
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2010-06-16 08:45 UTC] alexander dot krause at ed-solutions dot de
Description:
------------
The normal php-memcache extension allows the use of unix domain sockets.

However these don't work with the pecl-memcached.


Reproduce code:
---------------
$m=new Memcached();

$m->addServer(
	'/tmp/memcached.sock',
	0
);
$m->set('int', 99);

echo $m->getResultMessage();
//HOSTNAME LOOKUP FAILURE

Expected result:
----------------
SUCCESS

Actual result:
--------------
HOSTNAME LOOKUP FAILURE

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-06-16 08:46 UTC] alexander dot krause at ed-solutions dot de
Sorry for the wrong host-string, it has to be:
'unix:///tmp/memcached.sock'

I tried different things...
 [2010-10-18 06:55 UTC] ruslan dot usifov at gmail dot com
If any body interesting i have add my support for various connetions types to memcached server. I change prototype of addServer method, now it's like this:

addServer(<server decl>),
<server decl> = string || array

If <server decl> is string its have follow format (in pcre manner):

udp:host:port(( |:)<weight>)* - for udp 
host:port(( |:)<weight>)* - for tcp
/path_to_memcached_sock(( |:)<weight>)* - for unix socket

If <server decl> is array its have follow members:

array(
  "type" => MEMCACHED_CONNECTION_TCP | MEMCACHED_CONNECTION_UDP | MEMCACHED_CONNECTION_UNIX_SOCKET,
  "host" => <host>,
  "port" => <port, ignore if type == MEMCACHED_CONNECTION_UNIX_SOCKET>,
  "weight" => <weight>)

addServers, have similar declaration, except, its accept a list of <server decl>


Session save_path have follow declaration (string):

save_path=<server decl>(,<server decl>)*

diff -r 4140351daad9 php_memcached.c
--- a/php_memcached.c	Fri Oct 15 22:20:56 2010 +0400
+++ b/php_memcached.c	Mon Oct 18 14:36:41 2010 +0400
@@ -204,6 +204,173 @@
 static memcached_return php_memc_do_stats_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
 static memcached_return php_memc_do_version_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
 
+/****************************************
+  php_memcached_servers_add_string
+****************************************/
+#define HUGE_STRING_LEN 8196
+
+memcached_return php_memcached_servers_add_string(memcached_st *memc_sess, char* buffer)
+{
+	memcached_return status;
+	char *ptr, *ptr2;
+	in_port_t port = 0;
+	uint32_t weight = 0;
+
+	if(strstr(buffer, "udp:"))
+	{
+		ptr= index(&buffer[4], ':');
+
+		if (ptr)
+		{
+			ptr[0]= 0;
+			ptr++;
+
+			port= (in_port_t) strtoul(ptr, (char **)NULL, 10);
+		};
+
+		ptr2= index(ptr, ' ');
+
+		if (! ptr2)
+			ptr2= index(ptr, ':');
+
+		if (ptr2)
+		{
+			ptr2++;
+			weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10);
+		};
+
+		status = memcached_server_add_udp_with_weight(memc_sess, buffer, port, weight);
+	}
+	else if(strchr(buffer, '/') == buffer)
+	{
+		ptr2= index(buffer, ' ');
+
+		if (! ptr2)
+			ptr2= index(buffer, ':');
+
+		if (ptr2)
+		{
+			ptr2[0] = 0;
+			ptr2++;
+			weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10);
+		};
+
+		status = memcached_server_add_unix_socket_with_weight(memc_sess, buffer, weight);
+	}
+	else if(index(buffer, ':'))
+	{
+		ptr= index(buffer, ':');
+
+		if (ptr)
+		{
+			ptr[0]= 0;
+			ptr++;
+
+			port= (in_port_t) strtoul(ptr, (char **)NULL, 10);
+		};
+
+		ptr2= index(ptr, ' ');
+
+		if (! ptr2)
+			ptr2= index(ptr, ':');
+
+		if (ptr2)
+		{
+			ptr2++;
+			weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10);
+		};
+
+		status = memcached_server_add_with_weight(memc_sess, buffer, port, weight);
+	};
+
+	return status;
+};
+
+int php_memcached_servers_add(memcached_st *memc, zval** entry TSRMLS_DC)
+{
+	int retval = 0;
+	memcached_return status;
+
+	if(Z_TYPE_PP(entry) == IS_STRING)
+	{
+		char buffer[HUGE_STRING_LEN];
+		size_t length= Z_STRLEN_PP(entry);
+		memcpy(buffer, Z_STRVAL_PP(entry), length);
+		buffer[length]= 0;
+
+		status = php_memcached_servers_add_string(memc, buffer);
+
+		if (php_memc_handle_error(status TSRMLS_CC) < 0){
+			retval = 1;
+		};
+	}
+	else if(Z_TYPE_PP(entry) == IS_ARRAY)
+	{
+		zval **z_host, **z_port, **z_weight, **z_type = NULL;
+
+		if(zend_hash_find(Z_ARRVAL_PP(entry), "type", sizeof("type"), (void **)&z_type) == FAILURE)
+		{
+			retval = 4;
+		}
+		else if(zend_hash_find(Z_ARRVAL_PP(entry), "host", sizeof("host"), (void **)&z_host) == FAILURE)
+		{
+			retval = 2;
+		}
+		else
+		{
+			convert_to_long_ex(z_type);
+
+			if(Z_LVAL_PP(z_type) != MEMCACHED_CONNECTION_UNIX_SOCKET)
+			{
+				if (zend_hash_find(Z_ARRVAL_PP(entry), "port", sizeof("port"), (void **)&z_port) == FAILURE)
+				{
+					retval = 3;
+				}
+				else
+				{
+					convert_to_long_ex(z_port);
+				};
+			};
+		};
+
+		if(!retval)
+		{
+			uint32_t weight = 0;
+			convert_to_string_ex(z_host);
+			
+
+			if(zend_hash_find(Z_ARRVAL_PP(entry), "weight", sizeof("weight"), (void **)&z_weight) == SUCCESS){
+				convert_to_long_ex(z_weight);
+				weight = Z_LVAL_PP(z_weight);
+			};
+
+			switch(Z_LVAL_PP(z_type)){
+				case MEMCACHED_CONNECTION_TCP:
+					status = memcached_server_add_with_weight(memc, Z_STRVAL_PP(z_host), Z_LVAL_PP(z_port), weight);
+				break;
+
+				case MEMCACHED_CONNECTION_UDP:
+					status = memcached_server_add_udp_with_weight(memc, Z_STRVAL_PP(z_host), Z_LVAL_PP(z_port), weight);
+				break;
+
+				case MEMCACHED_CONNECTION_UNIX_SOCKET:
+					status = memcached_server_add_unix_socket_with_weight(memc, Z_STRVAL_PP(z_host), weight);
+				break;
+			};
+
+			if (php_memc_handle_error(status TSRMLS_CC) != 0) {
+				retval = 1;
+			};
+		};
+	}
+	else
+	{
+		retval = 1;
+	};
+
+	return retval;
+};
+
 
 /****************************************
   Method implementations
@@ -1374,24 +1541,20 @@
    Adds the given memcache server to the list */
 PHP_METHOD(Memcached, addServer)
 {
-	char *host;
-	int   host_len;
-	long  port, weight = 0;
-	memcached_return status;
+	zval *server;
 	MEMC_METHOD_INIT_VARS;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &host, &host_len,
-							  &port, &weight) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &server) == FAILURE) {
 		return;
 	}
 
 	MEMC_METHOD_FETCH_OBJECT;
 	MEMC_G(rescode) = MEMCACHED_SUCCESS;
 
-	status = memcached_server_add_with_weight(i_obj->memc, host, port, weight);
-	if (php_memc_handle_error(status TSRMLS_CC) < 0) {
+	if(php_memcached_servers_add(i_obj->memc, &server) != 0)
+	{
 		RETURN_FALSE;
-	}
+	};
 
 	RETURN_TRUE;
 }
@@ -1403,10 +1566,7 @@
 {
 	zval *servers;
 	zval **entry;
-	zval **z_host, **z_port, **z_weight = NULL;
-	uint32_t weight = 0;
-	int   entry_size, i = 0;
-	memcached_server_st *list = NULL;
+	int i = 0;
 	memcached_return status;
 	MEMC_METHOD_INIT_VARS;
 
@@ -1421,61 +1581,25 @@
 		 zend_hash_get_current_data(Z_ARRVAL_P(servers), (void **)&entry) == SUCCESS;
 		 zend_hash_move_forward(Z_ARRVAL_P(servers)), i++) {
 
-		if (Z_TYPE_PP(entry) != IS_ARRAY) {
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "server list entry #%d is not an array", i+1);
-			continue;
-		}
-
-		entry_size = zend_hash_num_elements(Z_ARRVAL_PP(entry));
-
-		if (entry_size > 1) {
-			zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
-
-			/* Check that we have a host */
-			if (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_host) == FAILURE) {
+		switch(php_memcached_servers_add(i_obj->memc, entry TSRMLS_CC))
+		{
+			case 1:
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not add entry #%d to the server list", i+1);
+			break;
+
+			case 2:
 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server host for entry #%d", i+1);
-				continue;
-			}
-
-			/* Check that we have a port */
-			if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE ||
-				zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_port) == FAILURE) {
+			break;
+
+			case 3:
 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server port for entry #%d", i+1);
-				continue;
-			}
-
-			convert_to_string_ex(z_host);
-			convert_to_long_ex(z_port);
-
-			weight = 0;
-			if (entry_size > 2) {
-				/* Try to get weight */
-				if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE ||
-					zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_weight) == FAILURE) {
-					php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server weight for entry #%d", i+1);
-				}
-
-				convert_to_long_ex(z_weight);
-				weight = Z_LVAL_PP(z_weight);
-			}
-
-			list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host),
-				Z_LVAL_PP(z_port), weight, &status);
-
-			if (php_memc_handle_error(status TSRMLS_CC) == 0) {
-				continue;
-			}
-		}
-
-		/* catch-all for all errors */
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not add entry #%d to the server list", i+1);
-	}
-
-	status = memcached_server_push(i_obj->memc, list);
-	memcached_server_list_free(list);
-	if (php_memc_handle_error(status TSRMLS_CC) < 0) {
-		RETURN_FALSE;
-	}
+			break;
+
+			case 4:
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server type for entry #%d", i+1);
+			break;
+		};
+	};
 
 	RETURN_TRUE;
 }
@@ -2448,24 +2572,49 @@
 PS_OPEN_FUNC(memcached)
 {
 	memcached_st *memc_sess = PS_GET_MOD_DATA();
-	memcached_server_st *servers;
-	memcached_return status;
-
-	servers = memcached_servers_parse((char *)save_path);
-	if (servers) {
-		memc_sess = memcached_create(NULL);
-		if (memc_sess) {
-			status = memcached_server_push(memc_sess, servers);
-			if (status == MEMCACHED_SUCCESS) {
-				PS_SET_MOD_DATA(memc_sess);
-				return SUCCESS;
+	memc_sess = memcached_create(NULL);
+
+	if (memc_sess)
+	{
+		const char *begin_ptr;
+		const char *end_ptr;
+		char *string;
+		memcached_return status;
+		end_ptr= (char *)save_path + strlen(save_path);
+
+		for (begin_ptr= (char *)save_path, string= index((char *)save_path, ','); 
+	       begin_ptr != end_ptr; 
+	       string= index(begin_ptr, ','))
+		{
+			char buffer[HUGE_STRING_LEN];
+
+			if (string)
+			{
+				memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
+				buffer[(unsigned int)(string - begin_ptr)]= 0;
+				begin_ptr= string+1;
 			}
-		} else {
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure");
-		}
-	} else {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path");
+			else
+			{
+				size_t length= strlen(begin_ptr);
+				memcpy(buffer, begin_ptr, length);
+				buffer[length]= 0;
+				begin_ptr= end_ptr;
+			};
+
+			status = php_memcached_servers_add_string(memc_sess, buffer);
+
+			if (isspace(*begin_ptr))
+				begin_ptr++;
+		};
+
+		PS_SET_MOD_DATA(memc_sess);
+		return SUCCESS;
 	}
+	else
+	{
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure");
+	};
 
 	PS_SET_MOD_DATA(NULL);
 	return FAILURE;
@@ -2998,6 +3147,19 @@
     php_session_register_module(ps_memcached_ptr);
 #endif
 
+	/* CONST_MEMC_START */
+	REGISTER_LONG_CONSTANT("MEMCACHED_CONNECTION_UDP",
+		MEMCACHED_CONNECTION_UDP,
+		CONST_CS | CONST_PERSISTENT);
+
+	REGISTER_LONG_CONSTANT("MEMCACHED_CONNECTION_TCP",
+		MEMCACHED_CONNECTION_TCP,
+		CONST_CS | CONST_PERSISTENT);
+
+	REGISTER_LONG_CONSTANT("MEMCACHED_CONNECTION_UNIX_SOCKET",
+		MEMCACHED_CONNECTION_UNIX_SOCKET,
+		CONST_CS | CONST_PERSISTENT);
+
 	return SUCCESS;
 }
 /* }}} */
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Jun 26 05:01:25 2019 UTC