diff --git a/cluster_library.c b/cluster_library.c index 98ba9c2..d1ec02e 100644 --- a/cluster_library.c +++ b/cluster_library.c @@ -634,8 +634,12 @@ cluster_node_create(redisCluster *c, char *host, size_t host_len, zend_llist_init(&node->slots, sizeof(redisSlotRange), NULL, 0); // Attach socket - node->sock = redis_sock_create(host, host_len, port, c->timeout, - c->read_timeout, c->persistent, NULL, 0); + node->sock = redis_sock_create(host, host_len, port, + c->flags->timeout, c->flags->read_timeout, + c->flags->persistent, NULL, 0); + + /* Stream context */ + node->sock->stream_ctx = c->flags->stream_ctx; redis_sock_set_auth(node->sock, c->flags->user, c->flags->pass); @@ -818,12 +822,12 @@ PHP_REDIS_API redisCluster *cluster_create(double timeout, double read_timeout, /* Initialize flags and settings */ c->flags = ecalloc(1, sizeof(RedisSock)); + c->flags->timeout = timeout; + c->flags->read_timeout = read_timeout; + c->flags->persistent = persistent; c->subscribed_slot = -1; c->clusterdown = 0; - c->timeout = timeout; - c->read_timeout = read_timeout; c->failover = failover; - c->persistent = persistent; c->err = NULL; /* Set up our waitms based on timeout */ @@ -993,9 +997,12 @@ void cluster_init_cache(redisCluster *c, redisCachedCluster *cc) { /* Create socket */ sock = redis_sock_create(ZSTR_VAL(cm->host.addr), ZSTR_LEN(cm->host.addr), cm->host.port, - c->timeout, c->read_timeout, c->persistent, + c->flags->timeout, c->flags->read_timeout, c->flags->persistent, NULL, 0); + /* Stream context */ + sock->stream_ctx = c->flags->stream_ctx; + /* Add to seed nodes */ zend_hash_str_update_ptr(c->seeds, key, keylen, sock); @@ -1027,7 +1034,8 @@ void cluster_init_cache(redisCluster *c, redisCachedCluster *cc) { * seeds array and know we have a non-empty array of strings all in * host:port format. */ PHP_REDIS_API void -cluster_init_seeds(redisCluster *cluster, zend_string **seeds, uint32_t nseeds) { +cluster_init_seeds(redisCluster *c, zend_string **seeds, uint32_t nseeds) +{ RedisSock *sock; char *seed, *sep, key[1024]; int key_len, i, *map; @@ -1044,19 +1052,22 @@ cluster_init_seeds(redisCluster *cluster, zend_string **seeds, uint32_t nseeds) ZEND_ASSERT(sep != NULL); // Allocate a structure for this seed - sock = redis_sock_create(seed, sep - seed, - (unsigned short)atoi(sep+1), cluster->timeout, - cluster->read_timeout, cluster->persistent, NULL, 0); + sock = redis_sock_create(seed, sep - seed, atoi(sep + 1), + c->flags->timeout, c->flags->read_timeout, + c->flags->persistent, NULL, 0); + + /* Stream context */ + sock->stream_ctx = c->flags->stream_ctx; /* Credentials */ - redis_sock_set_auth(sock, cluster->flags->user, cluster->flags->pass); + redis_sock_set_auth(sock, c->flags->user, c->flags->pass); // Index this seed by host/port key_len = snprintf(key, sizeof(key), "%s:%u", ZSTR_VAL(sock->host), sock->port); // Add to our seed HashTable - zend_hash_str_update_ptr(cluster->seeds, key, key_len, sock); + zend_hash_str_update_ptr(c->seeds, key, key_len, sock); } efree(map); diff --git a/cluster_library.h b/cluster_library.h index de9d171..98e9b0e 100644 --- a/cluster_library.h +++ b/cluster_library.h @@ -186,12 +186,8 @@ typedef struct clusterFoldItem clusterFoldItem; /* RedisCluster implementation structure */ typedef struct redisCluster { - /* Timeout and read timeout (for normal operations) */ - double timeout; - double read_timeout; - - /* Are we using persistent connections */ - int persistent; + /* One RedisSock struct for serialization and prefix information */ + RedisSock *flags; /* How long in milliseconds should we wait when being bounced around */ long waitms; @@ -241,9 +237,6 @@ typedef struct redisCluster { /* The slot where we're subscribed */ short subscribed_slot; - /* One RedisSock struct for serialization and prefix information */ - RedisSock *flags; - /* The first line of our last reply, not including our reply type byte * or the trailing \r\n */ char line_reply[1024]; diff --git a/library.c b/library.c index 2f95aea..5ae25ef 100644 --- a/library.c +++ b/library.c @@ -2165,9 +2165,9 @@ PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock) { struct timeval tv, read_tv, *tv_ptr = NULL; zend_string *persistent_id = NULL, *estr = NULL; - char host[1024], *pos, *address, *schema = NULL; + char host[1024], *pos, *address, *scheme = NULL; const char *fmtstr = "%s://%s:%d"; - int host_len, usocket = 0, err = 0, tcp_flag = 1; + int host_len, usocket = 0, err = 0, tcp_flag = 1, scheme_free = 0; ConnectionPool *p = NULL; if (redis_sock->stream != NULL) { @@ -2175,9 +2175,12 @@ PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock) } address = ZSTR_VAL(redis_sock->host); - if ((pos = strstr(address, "://")) != NULL) { - schema = estrndup(address, pos - address); + if ((pos = strstr(address, "://")) == NULL) { + scheme = redis_sock->stream_ctx ? "ssl" : "tcp"; + } else { + scheme = estrndup(address, pos - address); address = pos + sizeof("://") - 1; + scheme_free = 1; } if (address[0] == '/' && redis_sock->port < 1) { host_len = snprintf(host, sizeof(host), "unix://%s", address); @@ -2193,9 +2196,9 @@ PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock) fmtstr = "%s://[%s]:%d"; } #endif - host_len = snprintf(host, sizeof(host), fmtstr, schema ? schema : "tcp", address, redis_sock->port); - if (schema) efree(schema); + host_len = snprintf(host, sizeof(host), fmtstr, scheme, address, redis_sock->port); } + if (scheme_free) efree(scheme); if (redis_sock->persistent) { if (INI_INT("redis.pconnect.pooling_enabled")) { diff --git a/redis_cluster.c b/redis_cluster.c index 3233b65..5cb453b 100644 --- a/redis_cluster.c +++ b/redis_cluster.c @@ -351,7 +351,7 @@ void free_cluster_context(zend_object *object) { /* Attempt to connect to a Redis cluster provided seeds and timeout options */ static void redis_cluster_init(redisCluster *c, HashTable *ht_seeds, double timeout, double read_timeout, int persistent, zend_string *user, - zend_string *pass) + zend_string *pass, zval *context) { zend_string *hash = NULL, **seeds; redisCachedCluster *cc; @@ -369,10 +369,13 @@ static void redis_cluster_init(redisCluster *c, HashTable *ht_seeds, double time c->flags->user = zend_string_copy(user); if (pass && ZSTR_LEN(pass)) c->flags->pass = zend_string_copy(pass); + if (context) { + redis_sock_set_stream_context(c->flags, context); + } - c->timeout = timeout; - c->read_timeout = read_timeout; - c->persistent = persistent; + c->flags->timeout = timeout; + c->flags->read_timeout = read_timeout; + c->flags->persistent = persistent; c->waitms = timeout * 1000L; /* Attempt to load slots from cache if caching is enabled */ @@ -450,7 +453,7 @@ void redis_cluster_load(redisCluster *c, char *name, int name_len) { } /* Attempt to create/connect to the cluster */ - redis_cluster_init(c, ht_seeds, timeout, read_timeout, persistent, user, pass); + redis_cluster_init(c, ht_seeds, timeout, read_timeout, persistent, user, pass, NULL); /* Clean up */ zval_dtor(&z_seeds); @@ -464,38 +467,36 @@ void redis_cluster_load(redisCluster *c, char *name, int name_len) { /* Create a RedisCluster Object */ PHP_METHOD(RedisCluster, __construct) { - zval *object, *z_seeds = NULL, *z_auth = NULL; + zval *object, *z_seeds = NULL, *z_auth = NULL, *context = NULL; zend_string *user = NULL, *pass = NULL; double timeout = 0.0, read_timeout = 0.0; size_t name_len; zend_bool persistent = 0; - redisCluster *context = GET_CONTEXT(); + redisCluster *c = GET_CONTEXT(); char *name; // Parse arguments if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Os!|addbz", &object, redis_cluster_ce, &name, + "Os!|addbza", &object, redis_cluster_ce, &name, &name_len, &z_seeds, &timeout, &read_timeout, - &persistent, &z_auth) == FAILURE) + &persistent, &z_auth, &context) == FAILURE) { RETURN_FALSE; } - // Require a name - if (name_len == 0 && ZEND_NUM_ARGS() < 2) { - CLUSTER_THROW_EXCEPTION("You must specify a name or pass seeds!", 0); - } - /* If we've got a string try to load from INI */ if (ZEND_NUM_ARGS() < 2) { - redis_cluster_load(context, name, name_len); + if (name_len == 0) { // Require a name + CLUSTER_THROW_EXCEPTION("You must specify a name or pass seeds!", 0); + } + redis_cluster_load(c, name, name_len); return; } /* The normal case, loading from arguments */ redis_extract_auth_info(z_auth, &user, &pass); - redis_cluster_init(context, Z_ARRVAL_P(z_seeds), timeout, read_timeout, - persistent, user, pass); + redis_cluster_init(c, Z_ARRVAL_P(z_seeds), timeout, read_timeout, + persistent, user, pass, context); if (user) zend_string_release(user); if (pass) zend_string_release(pass);